编写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

相关文章

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

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

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

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

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

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

使用Java编写一个文件批量重命名工具

《使用Java编写一个文件批量重命名工具》这篇文章主要为大家详细介绍了如何使用Java编写一个文件批量重命名工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录背景处理1. 文件夹检查与遍历2. 批量重命名3. 输出配置代码片段完整代码背景在开发移动应用时,UI设计通常会提供不

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

Flutter Button使用

Material 组件库中有多种按钮组件如ElevatedButton、TextButton、OutlineButton等,它们的父类是于ButtonStyleButton。         基本的按钮特点:         1.按下时都会有“水波文动画”。         2.onPressed属性设置点击回调,如果不提供该回调则按钮会处于禁用状态,禁用状态不响应用户点击。

Wondows dos下怎么编写bat批处理文件

最近搞php,在运行时,以Nginx+php-cgi.exe方式运行Wordpress项目 打开dos,先cd到php-cgi.exe文件当前目录下执行启动命令:php-cgi.exe -b 127.0.0.1:9001再打开一个dos,再cd到nginx.exe文件当前目录下执行启动命令:start nginx 大概过程要经过这些步骤,觉得很麻烦,就学下怎么编写一个bat文件,以双击运行代替

小程序button控件上下边框的显示和隐藏

问题 想使用button自带的loading图标功能,但又不需要button显示边框线 button控件有一条淡灰色的边框,在控件上了样式 border:none; 无法让button边框隐藏 代码如下: <button class="btn">.btn{border:none; /*一般使用这个就是可以去掉边框了*/} 解决方案 发现button控件有一个伪元素(::after

用Python编写倒计时程序:详细教程

目录 引言 环境准备 基本概念 代码实现 步骤一:导入必要的库 步骤二:获取用户输入 步骤三:实现倒计时逻辑 步骤四:整合代码 运行程序 高级功能 扩展功能示例:支持分钟和小时输入 扩展功能示例:图形用户界面 (GUI) 总结 引言 倒计时程序是一个非常常见的小工具,广泛用于各种应用场景中,例如考试时间提醒、烹饪计时器、会议倒计时等。Python 作为一种

glShadeModel函数 GL_SMOOTH与GL_FLAT的区别

glShadeModel函数用于控制opengl中绘制指定两点间其他点颜色的过渡模式 参数一般为GL_SMOOTH(默认),GL_FLAT opengl默认是将制定的两点颜色进行插值,绘制之间的其他点 如果两点的颜色相同,使用两个参数效果相同 如果两点颜色不同,GL_SMOOTH会出现过渡效果,GL_FLAT 则只是以指定的某一点的单一色绘制其他所有点 如图可以对比GL_SM