当前位置: 源码素材网 » Delphi教程 » 详情页

Delphi在窗口的标题栏上绘制按钮

  •   时间:2019-04-24
  • 概述:标题栏 按钮 窗体设计

Delphi在窗口的标题栏上绘制按钮,本例在窗体的标题栏上绘制一个按钮,以给人别出心裁之感。下面是几个关于标题栏的重要的消息:

(1) WM_NCPAINT:重画标题栏消息,拦截这个消息可以重画按钮。

(2) WM_NCLBUTTONDOWN:在标题栏上按下鼠标左键消息,拦截这个消息就可以在标题栏上画出按钮按下的样式,并且可以在其中处理单击事件,使得所画按钮的行为如同一个按钮。

(3) WM_NCLBUTTONUP:在标题栏上释放鼠标左键消息,拦截这个消息,可以在标题栏上画出按钮弹起的样式。

(4) WM_NCLBUTTONDBLCLK:在标题栏上双击鼠标左键消息,拦截这个消息可在按钮区域双击时使其无效,从而避免窗体执行最大化和还原操作。

(5) WM_NCRBUTTONDOWN:在标题栏上按下鼠标右键消息,拦截这个消息可在按钮区域双击时使其无效,从而避免弹出窗体的快捷菜单。

(6) WM_NCMOUSEMOVE:在标题栏上移动鼠标消息,拦截这个消息可在鼠标移出按钮区域时画出按钮没有被按下,即凸起时的样式。

(7) WM_NCACTIVATE:当标题栏在激活与非激活之间切换时的消息,拦截这个消息可以处理程序切换过程中的事件。

编程要点:

首先声明一个TRect类型的全局变量ButtonRect,在其中存储待绘制按钮的区域。在程序中添加一个自定义过程DrawCaptionBtn,它的作用是在标题栏上绘制一个按钮。该过程只有一个参数BtnStyle,表示画按钮的样式,如果BtnStyle为EDGE_RAISED,则样式为凸起;为EDGE_SUNKEN,则样式为凹下。自定义过程的响应代码如下:

procedure TForm1.DrawCaptionBtn(BtnStyle: UINT);
var
   hCaptionDC: HDC;
   r: TRect;
begin
  hCaptionDC := GetWindowDC(Self.Handle);
  DrawEdge(hCaptionDC,ButtonRect,BtnStyle,BF_RECT or BF_MIDDLE or BF_SOFT);
  SetBkMode(hCaptionDC, TRANSPARENT);
  if BtnStyle = EDGE_RAISED then
     DrawText(hCaptionDC, '按钮',4, ButtonRect, DT_CENTER)
  else
  begin
     r := ButtonRect;
     OffsetRect(r, 1, 1);
     DrawText(hCaptionDC, '按下',4, r, DT_CENTER);
  end;
end;

下面还有一个编程要点要注意,以WM_NCLBUTTONDOWN消息处理为例来说明假按钮事件的处理过程。首先在程序中声明对WM_NCLBUTTONDOWN消息的拦截:

procedure WMNcLButtonDown(var m: TMessage);message WM_NCLBUTTONDOWN;

然后添加如下的WM_NCLBUTTONDOWN消息处理代码:

procedure TForm1.WMNcLButtonDown(var m: TMessage);
var
   p: TPoint;
begin
     p.x := LOWORD(m.lParam) - Self.Left;
     p.y := HIWORD(m.lParam) - Self.Top;
     if PtInRect(ButtonRect, p) then
     begin
        Self.BringToFront;
        DrawCaptionBtn(EDGE_SUNKEN);
        ShowMessage('按下了按钮');
     end
     else
        inherited;
end;

当用户在假按钮上按下鼠标左键时,procedure TForm1.WMNcLButtonDown(var m: TMessage)处理过程。鼠标的位置信息存储在变量m中,通过PtInRect函数可以判断鼠标位置是否在假按钮上。如果在,那么绘制凹下按钮的样式,同时显示一个对话框。其他的消息处理过程请参看源程序自己添加,它们的运行原理基本一致。程序代码如下:

unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;
type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    ButtonRect: TRect;
    //工具栏中按钮的区域
    procedure DrawCaptionBtn(BtnStyle: UINT);
procedure WMNcLButtonDown(var m: TMessage);
message WM_NCLBUTTONDOWN;
    // 当在标题栏上按下鼠标左按钮时进入该过程
    procedure WMNcLButtonUp(var m: TMessage);message WM_NCLBUTTONUP;
    // 当在标题栏上放开鼠标左按钮时进入该过程
procedure WMNcMouseMove(var m: TMessage);
message WM_NCMOUSEMOVE;
    // 当在标题栏上移动鼠标时进入该过程
procedure WMNcLButtonDBLClk(var m: TMessage); 
message WM_NCLBUTTONDBLCLK;
    // 当在标题栏上双击鼠标左铵钮时进入该过程
procedure WMNcRButtonDown(var m: TMessage);
message WM_NCRBUTTONDOWN;
    // 当在标题栏上按下鼠标右按钮时进入该过程
    procedure WMNcPaint(var m: TMessage);message WM_NCPAINT;
    // 当画标题栏时进入该过程
    procedure WMNcActivate(var m: TMessage);message WM_NCACTIVATE;
    // 当标题栏在激活与非激活之间切换时进入该过程
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.DrawCaptionBtn(BtnStyle: UINT);
var
   hCaptionDC: HDC;
   //标题条的设备上下文
   r: TRect;
begin
     hCaptionDC := GetWindowDC(Self.Handle);
     //注意不能用GetDC,那样的话,将得不到标题栏的设备上下文
DrawEdge(hCaptionDC,ButtonRect,BtnStyle,BF_RECT or BF_MIDDLE or BF_SOFT);
     //画按钮的样式,如果BtnStyle =EDGE_RAISED,则画出的样式为凸起;
     //如果BtnStyle =EDGE_SUNKEN,则画出的样式为凹下。
     SetBkMode(hCaptionDC, TRANSPARENT);
     //设置标题栏的设备上下文为透明状态
     if BtnStyle = EDGE_RAISED then
        DrawText(hCaptionDC, '按钮',4, ButtonRect, DT_CENTER)
     else
     begin
        r := ButtonRect;
        OffsetRect(r, 1, 1);
        DrawText(hCaptionDC, '按下',4, r, DT_CENTER);
     end;
     //画按钮
end;
procedure TForm1.WMNcActivate(var m: TMessage);
begin
     inherited;
     DrawCaptionBtn(EDGE_RAISED);
end;
procedure TForm1.WMNcPaint(var m: TMessage);
begin
     inherited;
     DrawCaptionBtn(EDGE_RAISED);
end;
procedure TForm1.WMNcLButtonDBLClk(var m: TMessage);
var
   p: TPoint;
begin
     p.x := LOWORD(m.lParam) - Self.Left;
     p.y := HIWORD(m.lParam) - Self.Top;
     if not PtInRect(ButtonRect, p) then // 如果不在按钮区域内
        inherited;  // 执行默认的操作
end;
procedure TForm1.WMNcMouseMove(var m: TMessage);
var
   p: TPoint;
begin
     p.x := LOWORD(m.lParam) - Self.Left;
     p.y := HIWORD(m.lParam) - Self.Top;
     if not PtInRect(ButtonRect, p) then // 如果不在按钮区域
        DrawCaptionBtn(EDGE_RAISED)
     else
        inherited;
        // 执行默认的操作
end;
procedure TForm1.WMNcLButtonDown(var m: TMessage);
var
   p: TPoint;
begin
     p.x := LOWORD(m.lParam) - Self.Left;
     p.y := HIWORD(m.lParam) - Self.Top;
     if PtInRect(ButtonRect, p) then
     // 如果在按钮区域内
     begin
        Self.BringToFront;
        DrawCaptionBtn(EDGE_SUNKEN);
        ShowMessage('按下了按钮');
     end
     else
        inherited;
        // 执行默认的操作
end;
procedure TForm1.WMNcLButtonUp(var m: TMessage);
var
   p: TPoint;
begin
     p.x := LOWORD(m.lParam) - Self.Left;
     p.y := HIWORD(m.lParam) - Self.Top;
     if PtInRect(ButtonRect, p) then
     //如果在标题栏按钮区域释放鼠标
     begin
        DrawCaptionBtn(EDGE_RAISED);
     end
     else
        inherited;
        // 执行默认的操作
end;
procedure TForm1.WMNcRButtonDown(var m: TMessage);
var
   p: TPoint;
begin
     p.x := LOWORD(m.lParam) - Self.Left;
     p.y := HIWORD(m.lParam) - Self.Top;
     if not PtInRect(ButtonRect, p) then
        inherited;
        //如果不在标题栏按钮区域,执行默认的操作
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
     with ButtonRect do
     begin
          left := 100;
          top  := 4;
          right := 150;
          bottom := 22;
     end;
end;
end.

保存文件,然后按F9键运行程序,程序运行的初始画面如图所示。在标题栏上的“按钮”按钮上单击,弹出一个对话框,如图所示。通过这个实例读者可以学习到如何全面地理解鼠标类的消息,利用这种方法可以随意地模拟按钮的作用。如果想得到更好的效果,读者还可以为按钮添加自定义字体效果。

Delphi在窗口的标题栏上绘制按钮

    相关声明:

      若“Delphi在窗口的标题栏上绘制按钮”有损您的权益,请告之我们删除内容。
      部分文章来源于网络,版权归原作者所有。