编写Flat风格的Button

2024-01-10 13:48
文章标签 编写 风格 button flat

本文主要是介绍编写Flat风格的Button,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


  • 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.

这篇关于编写Flat风格的Button的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/591019

相关文章

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled

python编写朋克风格的天气查询程序

《python编写朋克风格的天气查询程序》这篇文章主要为大家详细介绍了一个基于Python的桌面应用程序,使用了tkinter库来创建图形用户界面并通过requests库调用Open-MeteoAPI... 目录工具介绍工具使用说明python脚本内容如何运行脚本工具介绍这个天气查询工具是一个基于 Pyt

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可

Mybatis嵌套子查询动态SQL编写实践

《Mybatis嵌套子查询动态SQL编写实践》:本文主要介绍Mybatis嵌套子查询动态SQL编写方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、实体类1、主类2、子类二、Mapper三、XML四、详解总结前言MyBATis的xml文件编写动态SQL

Kotlin Compose Button 实现长按监听并实现动画效果(完整代码)

《KotlinComposeButton实现长按监听并实现动画效果(完整代码)》想要实现长按按钮开始录音,松开发送的功能,因此为了实现这些功能就需要自己写一个Button来解决问题,下面小编给大... 目录Button 实现原理1. Surface 的作用(关键)2. InteractionSource3.

使用Java编写一个字符脱敏工具类

《使用Java编写一个字符脱敏工具类》这篇文章主要为大家详细介绍了如何使用Java编写一个字符脱敏工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、字符脱敏工具类2、测试工具类3、测试结果1、字符脱敏工具类import lombok.extern.slf4j.Slf4j

使用Python创建一个功能完整的Windows风格计算器程序

《使用Python创建一个功能完整的Windows风格计算器程序》:本文主要介绍如何使用Python和Tkinter创建一个功能完整的Windows风格计算器程序,包括基本运算、高级科学计算(如三... 目录python实现Windows系统计算器程序(含高级功能)1. 使用Tkinter实现基础计算器2.

基于.NET编写工具类解决JSON乱码问题

《基于.NET编写工具类解决JSON乱码问题》在开发过程中,我们经常会遇到JSON数据处理的问题,尤其是在数据传输和解析过程中,很容易出现编码错误导致的乱码问题,下面我们就来编写一个.NET工具类来解... 目录问题背景核心原理工具类实现使用示例总结在开发过程中,我们经常会遇到jsON数据处理的问题,尤其是

利用Python编写一个简单的聊天机器人

《利用Python编写一个简单的聊天机器人》这篇文章主要为大家详细介绍了如何利用Python编写一个简单的聊天机器人,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 使用 python 编写一个简单的聊天机器人可以从最基础的逻辑开始,然后逐步加入更复杂的功能。这里我们将先实现一个简单的

使用PyQt5编写一个简单的取色器

《使用PyQt5编写一个简单的取色器》:本文主要介绍PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16进制颜色编码,一款跟随鼠标刷新图像的RGB和16... 目录取色器1取色器2PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16