编写Flat风格的Button

本文介绍如何在Delphi中自定义一个扁平风格的按钮组件,通过重写CreateParams方法并利用BS_FLAT样式实现。该组件支持主题服务,适用于希望简化界面风格的应用程序。

  • Delphi标准的组件中的Button组件都是3D风格的组件,即使像SpeedButton组件具有Flat属性,但是确没有了Border。因此我们需要一个简单功能的Flat风格组件又不想使用第三方组件,该怎么办呢?通过阅读delphi源代码和反复尝试,我们发现组件的风格主要通过重载    procedure CreateParams(var Params: TCreateParams); override;方法来实现,这也是delphi组件和windows标准组件结合的位置。我们看一下源代码:
    procedure TButton.CreateParams(var Params: TCreateParams);
    const
      ButtonStyles: array[Boolean] of DWORD = (BS_PUSHBUTTON, BS_DEFPUSHBUTTON);
    begin
      inherited CreateParams(Params);  //继承祖先的方法
      CreateSubClass(Params, 'BUTTON'); //创建windows组件button类
      Params.Style := Params.Style or ButtonStyles[FDefault];  //设置button类型
    end;
    我们继续跟踪发现ButtonStyles控制了他的border外观,同时由FDefault来确定。我们继续跟踪,就来到了Windows单元,组件风格的秘密就全在这里了。我们来看看:
    BS_PUSHBUTTON,
    BS_DEFPUSHBUTTON
    通过字面意思不难理解,BS_FLAT就是我们要找的。好了,接下来我们实现它就OK了。
    代码及测试代码实现如下:
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Buttons, StdCtrls, Themes;
     
    type
      TFlatButton = class(TButtonControl)
      private
        FCancel: Boolean;
        FDefault: Boolean;
        FActive: Boolean;
        FModalResult: TModalResult;
        procedure SetDefault(const Value: Boolean);
        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;
      public
        constructor Create(AOwner: TComponent); override;
        procedure Click; override;
        function UseRightToLeftAlignment: Boolean; override;
      published
        property Action;
        property Anchors;
        property BiDiMode;
        property Cancel: Boolean read FCancel write FCancel default False;
        property Caption;
        property Constraints;
        property Default: Boolean read FDefault write SetDefault default False;
        property DragCursor;
        property DragKind;
        property DragMode;
        property Enabled;
        property Font;
        property ModalResult: TModalResult read FModalResult write FModalResult default 0;
        property ParentBiDiMode;
        property ParentFont;
        property ParentShowHint;
        property PopupMenu;
        property ShowHint;
        property TabOrder;
        property TabStop default True;
        property Visible;
        property WordWrap;
        property OnClick;
        property OnContextPopup;
        property OnDragDrop;
        property OnDragOver;
        property OnEndDock;
        property OnEndDrag;
        property OnEnter;
        property OnExit;
        property OnKeyDown;
        property OnKeyPress;
        property OnKeyUp;
        property OnMouseDown;
        property OnMouseMove;
        property OnMouseUp;
        property OnStartDock;
        property OnStartDrag;
      end;
     
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        procedure MyClick(Sender: TObject);
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    { TFlatButton }
     
    procedure TFlatButton.Click;
    var
      Form: TCustomForm;
    begin
      Form := GetParentForm(Self);
      if Form <> nil then Form.ModalResult := ModalResult;
      inherited Click;
    end;
     
    procedure TFlatButton.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;
     
    constructor TFlatButton.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Width := 75;
      Height := 25;
      TabStop := True;
    end;
     
    procedure TFlatButton.CreateParams(var Params: TCreateParams);
    const
      ButtonStyles: array[Boolean] of DWORD = (BS_FLAT, BS_DEFPUSHBUTTON);
    begin
      inherited CreateParams(Params);
      CreateSubClass(Params, 'BUTTON');
      Params.Style := Params.Style or BS_FLAT;//ButtonStyles[FDefault];
    end;
     
    procedure TFlatButton.CreateWnd;
    begin
      inherited CreateWnd;
      FActive := FDefault;
    end;
     
    procedure TFlatButton.SetDefault(const Value: Boolean);
    begin
      FDefault := Value;
    end;
     
    function TFlatButton.UseRightToLeftAlignment: Boolean;
    begin
      Result := False;
    end;
     
    procedure TFlatButton.WMEraseBkgnd(var Message: TWMEraseBkgnd);
    begin
      if ThemeServices.ThemesEnabled then
        Message.Result := 1
      else
        DefaultHandler(Message);
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      button: TFlatButton;
    begin
      button := TFlatButton.Create(self);
      button.Parent := self;
      button.Caption := '&OK';
      button.SetBounds(10, 10, 75, 25);
      button.OnClick := myClick;
    end;
     
    procedure TForm1.MyClick(Sender: TObject);
    begin
      showmessage('you clicked me!');
    end;
     
    end.
FlatStyle .........\vcl_flatstyle .........\.............\vcl_flatstyle7 .........\.............\..............\Packages .........\.............\..............\........\FlatStyle_D5.cfg,382,2001-07-01 .........\.............\..............\........\FlatStyle_D5.dcu,4531,2001-07-01 .........\.............\..............\........\FlatStyle_D5.dof,1240,2001-07-01 .........\.............\..............\........\FlatStyle_D5.dpk,2301,2001-07-01 .........\.............\..............\........\FlatStyle_D5.res,1536,2001-07-01 .........\.............\..............\........\FlatStyle_D6.cfg,390,2002-08-29 .........\.............\..............\........\FlatStyle_D6.dcu,5009,2002-08-29 .........\.............\..............\........\FlatStyle_D6.dof,1421,2002-08-29 .........\.............\..............\........\FlatStyle_D6.dpk,2250,2001-07-01 .........\.............\..............\........\FlatStyle_D6.dsk,2462,2001-07-01 .........\.............\..............\........\FlatStyle_D6.res,1536,2001-07-01 .........\.............\..............\........\FlatStyle_D7.cfg,438,2004-10-26 .........\.............\..............\........\FlatStyle_D7.dcu,6183,2004-10-26 .........\.............\..............\........\FlatStyle_D7.dof,2023,2004-10-26 .........\.............\..............\........\FlatStyle_D7.dpk,2250,2001-07-01 .........\.............\..............\........\FlatStyle_D7.dsk,2568,2002-09-09 .........\.............\..............\........\FlatStyle_D7.res,1536,2001-07-01 .........\.............\..............\Source .........\.............\..............\......\DFS.INC,8673,2001-06-29 .........\.............\..............\......\FlatArrow.res,372,2001-06-29 .........\.............\..............\......\FlatGraphics.dcu,1710,2002-09-09 .........\.............\..............\......\FlatGraphics.pas,2168,2001-06-29 .........\.............\..............\......\FlatSound.res,71508,2001-06-29 .........\.............\..............\......\FlatUtilitys.dcu,11988,2002-09-09 .........\.............\..............\......\FlatUtilitys.pas,11687,2001-06-29 .........\.............\..............\......\HSLUtils.dcu,3209,2002-09-09 .........\.............\..............\......\HSLUtils.pas,4174,2001-06-29 .........\.............\..............\......\TFlatAnimationUnit.dcu,15066,2002-09-09 .........\.............\..............\......\TFlatAnimationUnit.pas,12001,2001-06-29 .........\.............\..............\......\TFlatAnimWndUnit.dcu,9884,2002-09-09 .........\.............\..............\......\TFlatAnimWndUnit.pas,6336,2001-06-29 .........\.............\..............\......\TFlatButtonUnit.dcu,28259,2002-09-09 .........\.............\..............\......\TFlatButtonUnit.pas,24710,2001-06-29 .........\.............\..............\......\TFlatCheckBoxUnit.dcu,20650,2002-09-09 .........\.............\..............\......\TFlatCheckBoxUnit.pas,15453,2001-06-29 .........\.............\..............\......\TFlatCheckListBoxUnit.dcu,27040,2002-09-09 .........\.............\..............\......\TFlatCheckListBoxUnit.pas,25105,2001-06-29 .........\.............\..............\......\TFlatColorComboBoxUnit.dcu,27520,2002-09-09 .........\.............\..............\......\TFlatColorComboBoxUnit.pas,19775,2001-06-29 .........\.............\..............\......\TFlatComboBoxUnit.dcu,21667,2002-09-09 .........\.............\..............\......\TFlatComboBoxUnit.pas,13785,2001-06-29 .........\.............\..............\......\TFlatDesignRegister.dcu,6690,2001-07-01 .........\.............\..............\......\TFlatDesignRegister.pas,5137,2001-07-01 .........\.............\..............\......\TFlatEditUnit.dcu,17400,2002-09-09 .........\.............\..............\......\TFlatEditUnit.pas,10760,2001-06-29 .........\.............\..............\......\TFlatGaugeUnit.dcu,10185,2002-09-09 .........\.............\..............\......\TFlatGaugeUnit.pas,7556,2001-07-01 .........\.............\..............\......\TFlatGroupBoxUnit.dcu,14451,2002-09-09 .........\.............\..............\......\TFlatGroupBoxUnit.pas,10964,2001-06-29 .........\.............\..............\......\TFlatHintUnit.dcu,15818,2002-09-09 .........\.............\..............\......\TFlatHintUnit.pas,12646,2001-06-29 .........\.............\..............\......\TFlatListBoxUnit.dcu,25421,2002-09-09 .........\.............\..............\......\TFlatListBoxUnit.pas,22127,2001-06-29 .........\.............\..............\......\TFlatMaskEditUnit.dcu,16638,2002-09-09 .........\.............\..............\......\TFlatMaskEditUnit.pas,9655,2001-06-29 .........\.............\..............\......\TFlatMemoUnit.dcu,14856,2002-09-09 .........\.............\..............\......\TFlatMemoUnit.pas,8473,2001-06-29 .........\.............\..............\......\TFlatPanelUnit.dcu,10308,2002-09-09 .........\.............\..............\......\TFlatPanelUnit.pas,4805,2001-06-29 .........\.............\..............\......\TFlatProgressBarUnit.dcu,12657,2002-09-09 .........\.............\..............\......\TFlatProgressBarUnit.pas,11030,2001-06-29 .........\.............\..............\......\TFlatRadioButtonUnit.dcu,20512,2002-09-09 .........\.............\..............\......\TFlatRadioButtonUnit.pas,15276,2001-06-29 .........\.............\..............\......\TFlatRegister.dcr,11732,2001-06-29 .........\.............\..............\......\TFlatRegister.dcu,3463,2002-09-09 .........\.............\..............\......\TFlatRegister.pas,1324,2001-06-29 .........\.............\..............\......\TFlatScrollbarUnit.dcu,33164,2002-09-09 .........\.............\..............\......\TFlatScrollbarUnit.pas,31957,2001-06-29 .........\.............\..............\......\TFlatScrollbarUnit.res,9996,2001-06-29 .........\.............\..............\......\TFlatSoundUnit.dcu,3106,2002-09-09 .........\.............\..............\......\TFlatSoundUnit.pas,1820,2001-06-29 .........\.............\..............\......\TFlatSpeedButtonUnit.dcu,24834,2002-09-09 .........\.............\..............\......\TFlatSpeedButtonUnit.pas,22668,2001-06-29 .........\.............\..............\......\TFlatSpinButtonUnit.dcu,14577,2002-09-09 .........\.............\..............\......\TFlatSpinButtonUnit.pas,9502,2001-06-29 .........\.............\..............\......\TFlatSpinEditUnit.dcu,27146,2002-09-09 .........\.............\..............\......\TFlatSpinEditUnit.pas,16383,2001-06-29 .........\.............\..............\......\TFlatSplitterUnit.dcu,15292,2002-09-09 .........\.............\..............\......\TFlatSplitterUnit.pas,10697,2001-06-29 .........\.............\..............\......\TFlatTabControlUnit.dcu,21602,2002-09-09 .........\.............\..............\......\TFlatTabControlUnit.pas,19674,2001-06-29 .........\.............\..............\......\TFlatTitlebarUnit.dcu,10441,2002-09-09 .........\.............\..............\......\TFlatTitlebarUnit.pas,6386,2001-06-29
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值