zoukankan      html  css  js  c++  java
  • VCL控件组件大都应该重载TWinControl的虚函数WndProc来进行处理窗口消息的工作

    TWinControl的构造函数中会调用MakeObjectInstance并且传递MainWndProc作为窗口消息处理函数,而MainWndProc则会调用虚函数WndProc来处理窗口消息。留个爪,对TButton的主要方法,都要仔细解读一下。

    推测VCL控件组件大都应该重载TWinControl的虚函数WndProc来进行处理窗口消息的工作,举例:

    procedure TButtonControl.WndProc(var Message: TMessage); override;
    begin
      case Message.Msg of
        WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
          if not (csDesigning in ComponentState) and not Focused then
          begin
            FClicksDisabled := True;
            Windows.SetFocus(Handle); // Windows单元
            FClicksDisabled := False;
            if not Focused then Exit;
          end;
        CN_COMMAND:
          if FClicksDisabled then Exit;
      end;
      inherited WndProc(Message);
      TButtonControl = class(TWinControl)
      private
        FClicksDisabled: Boolean;
        FWordWrap: Boolean;
        function IsCheckedStored: Boolean;
        procedure CNCtlColorStatic(var Message: TWMCtlColorStatic); message CN_CTLCOLORSTATIC;
        procedure WMEraseBkGnd(var Message: TWMEraseBkGnd); message WM_ERASEBKGND;
        procedure SetWordWrap(const Value: Boolean);
      protected
        procedure ActionChange(Sender: TObject; CheckDefaults: Boolean); override;
        function GetActionLinkClass: TControlActionLinkClass; override;
        function GetChecked: Boolean; virtual;
        procedure SetChecked(Value: Boolean); virtual;
        procedure WndProc(var Message: TMessage); override;
        procedure CreateParams(var Params: TCreateParams); override;
        property Checked: Boolean read GetChecked write SetChecked stored IsCheckedStored default False;
        property ClicksDisabled: Boolean read FClicksDisabled write FClicksDisabled;
        property WordWrap: Boolean read FWordWrap write SetWordWrap default False;
      public
        constructor Create(AOwner: TComponent); override;
      end;
    
      TButton = class(TButtonControl)
      private
        FDefault: Boolean;
        FCancel: Boolean;
        FActive: Boolean;
        FModalResult: TModalResult;
        procedure SetDefault(Value: Boolean);
        procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
        procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
        procedure CMFocusChanged(var Message: TCMFocusChanged); message CM_FOCUSCHANGED;
        procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
        procedure CNCtlColorBtn(var Message: TWMCtlColorBtn); message CN_CTLCOLORBTN;
        procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
      protected
        procedure CreateParams(var Params: TCreateParams); override;
        procedure CreateWnd; override;
        procedure SetButtonStyle(ADefault: Boolean); virtual;
      public
        constructor Create(AOwner: TComponent); override;
        procedure Click; override;
        function UseRightToLeftAlignment: Boolean; override;
    end;

    // TButtonControl 研究

    constructor TButtonControl.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      if SysLocale.FarEast and (Win32Platform = VER_PLATFORM_WIN32_NT) then
        ImeMode := imDisable;
    end;
    
    procedure TButtonControl.ActionChange(Sender: TObject; CheckDefaults: Boolean);
    begin
      inherited ActionChange(Sender, CheckDefaults);
      if Sender is TCustomAction then
        with TCustomAction(Sender) do
        begin
          if not CheckDefaults or (Self.Checked = False) then
            Self.Checked := Checked;
        end;
    end;
    
    function TButtonControl.GetActionLinkClass: TControlActionLinkClass;
    begin
      Result := TButtonActionLink;
    end;
    
    function TButtonControl.IsCheckedStored: Boolean;
    begin
      Result := (ActionLink = nil) or not TButtonActionLink(ActionLink).IsCheckedLinked;
    end;
    
    procedure TButtonControl.CNCtlColorStatic(var Message: TWMCtlColorStatic);
    begin
      with ThemeServices do
        if ThemesEnabled then
        begin
          DrawParentBackground(Handle, Message.ChildDC, nil, False);
          { Return an empty brush to prevent Windows from overpainting we just have created. }
          Message.Result := GetStockObject(NULL_BRUSH);
        end
        else
          inherited;
    end;
    
    procedure TButtonControl.WMEraseBkGnd(var Message: TWMEraseBkGnd);
    begin
      { Under theme services the background is drawn in CN_CTLCOLORSTATIC. }
      if ThemeServices.ThemesEnabled then
        Message.Result := 1
      else
        inherited;
    end;
    
    procedure TButtonControl.CreateParams(var Params: TCreateParams);
    begin
      inherited;
      if FWordWrap then
        Params.Style := Params.Style or BS_MULTILINE;
    end;
    
    procedure TButtonControl.SetWordWrap(const Value: Boolean);
    begin
      if FWordWrap <> Value then
      begin
        FWordWrap := Value;
        RecreateWnd;
      end;
    end;

    // TButton研究

    constructor TButton.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      ControlStyle := [csSetCaption, csDoubleClicks];
      Width := 75;
      Height := 25;
      TabStop := True;
    end;
    
    procedure TButton.Click;
    var
      Form: TCustomForm;
    begin
      Form := GetParentForm(Self);
      if Form <> nil then Form.ModalResult := ModalResult;
      inherited Click;
    end;
    
    function TButton.UseRightToLeftAlignment: Boolean;
    begin
      Result := False;
    end;
    
    procedure TButton.SetButtonStyle(ADefault: Boolean);
    const
      BS_MASK = $000F;
    var
      Style: Word;
    begin
      if HandleAllocated then
      begin
        if ADefault then Style := BS_DEFPUSHBUTTON else Style := BS_PUSHBUTTON;
        if GetWindowLong(Handle, GWL_STYLE) and BS_MASK <> Style then
          SendMessage(Handle, BM_SETSTYLE, Style, 1);
      end;
    end;
    
    procedure TButton.SetDefault(Value: Boolean);
    var
      Form: TCustomForm;
    begin
      FDefault := Value;
      if HandleAllocated then
      begin
        Form := GetParentForm(Self);
        if Form <> nil then
          Form.Perform(CM_FOCUSCHANGED, 0, Longint(Form.ActiveControl));
      end;
    end;
    
    procedure TButton.CreateParams(var Params: TCreateParams);
    const
      ButtonStyles: array[Boolean] of DWORD = (BS_PUSHBUTTON, BS_DEFPUSHBUTTON);
    begin
      inherited CreateParams(Params);
      CreateSubClass(Params, 'BUTTON');
      Params.Style := Params.Style or ButtonStyles[FDefault];
    end;
    
    procedure TButton.CreateWnd;
    begin
      inherited CreateWnd;
      FActive := FDefault;
    end;
    
    procedure TButton.CNCommand(var Message: TWMCommand);
    begin
      if Message.NotifyCode = BN_CLICKED then Click;
    end;
    
    procedure TButton.CMDialogKey(var Message: TCMDialogKey);
    begin
      with Message do
        if  (((CharCode = VK_RETURN) and FActive) or
          ((CharCode = VK_ESCAPE) and FCancel)) and
          (KeyDataToShiftState(Message.KeyData) = []) and CanFocus then
        begin
          Click;
          Result := 1;
        end else
          inherited;
    end;
    
    procedure TButton.CMDialogChar(var Message: TCMDialogChar);
    begin
      with Message do
        if IsAccel(CharCode, Caption) and CanFocus then
        begin
          Click;
          Result := 1;
        end else
          inherited;
    end;
    
    procedure TButton.CMFocusChanged(var Message: TCMFocusChanged);
    begin
      with Message do
        if Sender is TButton then
          FActive := Sender = Self
        else
          FActive := FDefault;
      SetButtonStyle(FActive);
      inherited;
    end;
    
    procedure TButton.WMEraseBkgnd(var Message: TWMEraseBkgnd);
    begin
      if ThemeServices.ThemesEnabled then
        Message.Result := 1
      else
        DefaultHandler(Message);
    end;
    
    procedure TButton.CNCtlColorBtn(var Message: TWMCtlColorBtn);
    begin
      with ThemeServices do
        if ThemesEnabled then
        begin
          DrawParentBackground(Handle, Message.ChildDC, nil, False);
          { Return an empty brush to prevent Windows from overpainting we just have created. }
          Message.Result := GetStockObject(NULL_BRUSH);
        end
        else
          inherited;
    end;

    其它继承的组件:
    TCustomCheckBox = class(TButtonControl)
    TCheckBox = class(TCustomCheckBox)
    TRadioButton = class(TButtonControl)

  • 相关阅读:
    分布式系统知识点六:分布式锁及其简单实现讲解 2 zookpeer的实现(转载)
    分布式系统知识点六:分布式锁及其简单实现讲解 1redis的实现(转载)
    分布式系统知识点五:分布式事务及其解决方案2 利用消息队列处理分布式事务(转载)
    分布式系统知识点五:分布式事务及其解决方案 1 2PC,3PC简洁(转载)
    分布式系统知识点四: 一致性hash介绍 (转载)
    分布式系统知识点三: Paxos知识2 Paxos实现简洁及MulitPaxos介绍 (转载)
    分布式系统知识点三: Paxos知识1 算法原理与推导 (转载)
    分布式系统知识点二: 分布式一致性模型分类 (转载)
    分布式系统知识点一: CAP理论 (转载)
    压缩目录下的文件
  • 原文地址:https://www.cnblogs.com/findumars/p/3249537.html
Copyright © 2011-2022 走看看