如何在标题栏上增加按钮

来源:互联网 发布:华为mate抢购软件 编辑:程序博客网 时间:2024/05/22 07:04

如何在标题栏上增加按钮

---- 大家在使用某些软件的过程中,有没有注意到有些软件有一些很有趣的东西。比如说在主窗口的标
题栏上居然有一个按钮。在Internet中随处可见这样的小控件。按钮怎么可以加入到非客户区(Client)
呢? 

---- 在这里,最关键的一点就是,大家不要被传统知识误导:真的认为它是一个按钮。有名柄(handle)
的控件当然不能放在标题栏上了。有经验的程序员用Spy++跟踪一下的话,马上就会发现其中的秘密。它
并不是一个按钮,只不过是处理成按钮的样子罢了。 

---- 既然知道了所以然,那么我们为什么不能自己来做一个呢,当然没问题,下面我们就用Delphi来实

它,讲注意我的注解。 

---- 在具体实例之前,我们应该知道几个关于标题栏的重要的消息: 

---- WM_NCPAINT:重画标题栏消息。我们必须截住它,可以在这里重画按钮; 

---- WM_NCLBUTTONDOWN:在标题栏上按下鼠标左键消息。我们可以截住它,在标题栏上画出按钮按下的
样子,并且可以在其中进行自已的单击事件的处理,使得它像一个按钮; 

---- WM_NCLBUTTONUP:在标题栏上释放鼠标左键消息。我们可以截住它,在标题栏上画出按钮弹起的样
子; 

---- WM_NCLBUTTONDBLCLK:在标题栏上双击鼠标左键消息。我们可以截住它,当在按钮区域双击时,
我们就该使其无效,从而避免窗体执行最大化和还原操作。 

---- WM_NCRBUTTONDOWN:在标题栏上按下鼠标右键消息。我们可以截住它,当在按钮区域双击时,我
们就该使其无效,从而避免弹出窗体按制菜单。 

---- WM_NCMOUSEMOVE:在标题栏上移动鼠标消息。我们可以截住它,当鼠标移出按钮区域时,我们就
必须画出按钮没有被按下,即凸起时的样子。 

---- WM_NCACTIVATE:当标题栏在激活与非激活之间切换时收到该消息。我们可以截住它,当该窗口处
理激活状态时,我们可以做一些事情,比如说将我们的标题栏按钮上的字体变灰或变黑来指示该窗口的
当前状态。下面我没有加入该项功能,如果大家感兴趣的话,可以自己完成。 
---- (大家从这里可以发现,标题栏的消息都是WM_NC开头的) 

---- 知道了原理之后,相信大家一定可以做出更漂亮的按钮来。


WinAPI: DrawFrameControl - 绘制控件


//声明:DrawFrameControl(  DC: HDC;            {设备环境句柄}  const Rect: TRect;  {矩形}  uType, uState: UINT {控件类型与控件状态}): BOOL;//控件类型 uType 参数可选值:DFC_CAPTION   = 1; {标题按钮}DFC_MENU      = 2; {菜单}DFC_SCROLL    = 3; {滚动条按钮}DFC_BUTTON    = 4; {标准按钮}DFC_POPUPMENU = 5; {弹出菜单}//控件状态  uState 参数可选值:{针对 DFC_CAPTION}DFCS_CAPTIONCLOSE   = 0;DFCS_CAPTIONMIN     = 1;DFCS_CAPTIONMAX     = 2;DFCS_CAPTIONRESTORE = 3;DFCS_CAPTIONHELP    = 4;{针对 DFC_MENU}DFCS_MENUARROW      = 0;DFCS_MENUCHECK      = 1;DFCS_MENUBULLET     = 2;DFCS_MENUARROWRIGHT = 4;{针对 DFC_SCROLL}DFCS_SCROLLUP            = 0;DFCS_SCROLLDOWN          = 1;DFCS_SCROLLLEFT          = 2;DFCS_SCROLLRIGHT         = 3;DFCS_SCROLLCOMBOBOX      = 5;DFCS_SCROLLSIZEGRIP      = 8;DFCS_SCROLLSIZEGRIPRIGHT = $10;{针对 DFC_BUTTON}DFCS_BUTTONCHECK      = 0;DFCS_BUTTONRADIOIMAGE = 1;DFCS_BUTTONRADIOMASK  = 2;DFCS_BUTTONRADIO      = 4;DFCS_BUTTON3STATE     = 8;DFCS_BUTTONPUSH       = $10;{通用状态}DFCS_INACTIVE    = $100;DFCS_PUSHED      = $200;DFCS_CHECKED     = $400;DFCS_TRANSPARENT = $800;DFCS_HOT         = $1000;DFCS_ADJUSTRECT  = $2000;DFCS_FLAT        = $4000;DFCS_MONO        = $8000;//举例:unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls, ExtCtrls;type  TForm1 = class(TForm)    RadioGroup1: TRadioGroup;    RadioGroup2: TRadioGroup;    RadioGroup3: TRadioGroup;    RadioGroup4: TRadioGroup;    RadioGroup5: TRadioGroup;    RadioGroup6: TRadioGroup;    Panel1: TPanel;    procedure RadioGroup1Click(Sender: TObject);    procedure RadioGroup2Click(Sender: TObject);    procedure RadioGroup3Click(Sender: TObject);    procedure RadioGroup4Click(Sender: TObject);    procedure RadioGroup5Click(Sender: TObject);    procedure RadioGroup6Click(Sender: TObject);    procedure Draw;  end;var  Form1: TForm1;implementation{$R *.dfm}var  DFC  : Integer = 0;  DFCS1: Integer = 0;  DFCS2: Integer = 0;procedure TForm1.Draw;begin  Panel1.Refresh;  DrawFrameControl(GetDC(Panel1.Handle), Rect(10,10,100,50), DFC, DFCS1 or DFCS2);end;procedure TForm1.RadioGroup1Click(Sender: TObject);begin  Panel1.Refresh;  case RadioGroup1.ItemIndex of    0: begin      DFC := DFC_CAPTION;      RadioGroup3.Enabled := True;      RadioGroup4.Enabled := False;      RadioGroup5.Enabled := False;      RadioGroup6.Enabled := False;    end;    1: begin      DFC := DFC_MENU;      RadioGroup3.Enabled := False;      RadioGroup4.Enabled := True;      RadioGroup5.Enabled := False;      RadioGroup6.Enabled := False;    end;    2: begin      DFC := DFC_SCROLL;      RadioGroup3.Enabled := False;      RadioGroup4.Enabled := False;      RadioGroup5.Enabled := True;      RadioGroup6.Enabled := False;    end;    3: begin      DFC := DFC_BUTTON;      RadioGroup3.Enabled := False;      RadioGroup4.Enabled := False;      RadioGroup5.Enabled := False;      RadioGroup6.Enabled := True;    end;    4: begin      DFC := DFC_POPUPMENU;      RadioGroup3.Enabled := False;      RadioGroup4.Enabled := True;      RadioGroup5.Enabled := False;      RadioGroup6.Enabled := False;    end;  end;end;procedure TForm1.RadioGroup2Click(Sender: TObject);begin  case RadioGroup2.ItemIndex of    0: DFCS1 := DFCS_INACTIVE;    1: DFCS1 := DFCS_PUSHED;    2: DFCS1 := DFCS_CHECKED;    3: DFCS1 := DFCS_TRANSPARENT;    4: DFCS1 := DFCS_HOT;    5: DFCS1 := DFCS_ADJUSTRECT;    6: DFCS1 := DFCS_FLAT;    7: DFCS1 := DFCS_MONO;  end;  Draw;end;procedure TForm1.RadioGroup3Click(Sender: TObject);begin  case RadioGroup3.ItemIndex of    0: DFCS2 := DFCS_CAPTIONCLOSE;    1: DFCS2 := DFCS_CAPTIONMIN;    2: DFCS2 := DFCS_CAPTIONMAX;    3: DFCS2 := DFCS_CAPTIONRESTORE;    4: DFCS2 := DFCS_CAPTIONHELP;  end;  Draw;end;procedure TForm1.RadioGroup4Click(Sender: TObject);begin  case RadioGroup4.ItemIndex of    0: DFCS2 := DFCS_MENUARROW;    1: DFCS2 := DFCS_MENUCHECK;    2: DFCS2 := DFCS_MENUBULLET;    3: DFCS2 := DFCS_MENUARROWRIGHT;  end;  Draw;end;procedure TForm1.RadioGroup5Click(Sender: TObject);begin  case RadioGroup5.ItemIndex of    0: DFCS2 := DFCS_SCROLLUP;    1: DFCS2 := DFCS_SCROLLDOWN;    2: DFCS2 := DFCS_SCROLLLEFT;    3: DFCS2 := DFCS_SCROLLRIGHT;    4: DFCS2 := DFCS_SCROLLCOMBOBOX;    5: DFCS2 := DFCS_SCROLLSIZEGRIP;    6: DFCS2 := DFCS_SCROLLSIZEGRIPRIGHT;  end;  Draw;end;procedure TForm1.RadioGroup6Click(Sender: TObject);begin  case RadioGroup6.ItemIndex of    0: DFCS2 := DFCS_BUTTONCHECK;    1: DFCS2 := DFCS_BUTTONRADIOIMAGE;    2: DFCS2 := DFCS_BUTTONRADIOMASK;    3: DFCS2 := DFCS_BUTTONRADIO;    4: DFCS2 := DFCS_BUTTON3STATE;    5: DFCS2 := DFCS_BUTTONPUSH;  end;  Draw;end;end.

//效果图:

附上窗体结构代码:

附上窗体结构代码:object Form1: TForm1  Left = 0  Top = 0  Caption = 'Form1'  ClientHeight = 386  ClientWidth = 499  Color = clBtnFace  Font.Charset = DEFAULT_CHARSET  Font.Color = clWindowText  Font.Height = -11  Font.Name = 'Tahoma'  Font.Style = []  OldCreateOrder = False  PixelsPerInch = 96  TextHeight = 13  object RadioGroup1: TRadioGroup    Left = 0    Top = 8    Width = 137    Height = 129    Caption = 'RadioGroup1'    Items.Strings = (      'DFC_CAPTION   '      'DFC_MENU      '      'DFC_SCROLL    '      'DFC_BUTTON    '      'DFC_POPUPMENU ')    TabOrder = 0    OnClick = RadioGroup1Click  end  object RadioGroup2: TRadioGroup    Left = 0    Top = 143    Width = 137    Height = 170    Caption = 'RadioGroup2'    Items.Strings = (      'DFCS_INACTIVE'      'DFCS_PUSHED'      'DFCS_CHECKED'      'DFCS_TRANSPARENT'      'DFCS_HOT'      'DFCS_ADJUSTRECT'      'DFCS_FLAT'      'DFCS_MONO')    TabOrder = 1    OnClick = RadioGroup2Click  end  object RadioGroup3: TRadioGroup    Left = 143    Top = 8    Width = 178    Height = 129    Caption = 'RadioGroup3'    Items.Strings = (      'DFCS_CAPTIONCLOSE   '      'DFCS_CAPTIONMIN'      'DFCS_CAPTIONMAX'      'DFCS_CAPTIONRESTORE'      'DFCS_CAPTIONHELP')    TabOrder = 2    OnClick = RadioGroup3Click  end  object RadioGroup4: TRadioGroup    Left = 327    Top = 8    Width = 170    Height = 129    Caption = 'RadioGroup4'    Items.Strings = (      'DFCS_MENUARROW'      'DFCS_MENUCHECK'      'DFCS_MENUBULLET'      'DFCS_MENUARROWRIGHT')    TabOrder = 3    OnClick = RadioGroup4Click  end  object RadioGroup5: TRadioGroup    Left = 143    Top = 143    Width = 178    Height = 170    Caption = 'RadioGroup5'    Items.Strings = (      'DFCS_SCROLLUP'      'DFCS_SCROLLDOWN'      'DFCS_SCROLLLEFT'      'DFCS_SCROLLRIGHT'      'DFCS_SCROLLCOMBOBOX'      'DFCS_SCROLLSIZEGRIP'      'DFCS_SCROLLSIZEGRIPRIGHT')    TabOrder = 4    OnClick = RadioGroup5Click  end  object RadioGroup6: TRadioGroup    Left = 327    Top = 143    Width = 170    Height = 170    Caption = 'RadioGroup6'    Items.Strings = (      'DFCS_BUTTONCHECK'      'DFCS_BUTTONRADIOIMAGE'      'DFCS_BUTTONRADIOMASK'      'DFCS_BUTTONRADIO'      'DFCS_BUTTON3STATE'      'DFCS_BUTTONPUSH')    TabOrder = 5    OnClick = RadioGroup6Click  end  object Panel1: TPanel    Left = 0    Top = 319    Width = 499    Height = 67    Align = alBottom    Caption = 'Panel1'    TabOrder = 6  endend/////////////////////////////////////////////////////////////////////////////////////另一个例子unit Unit1;interfaceuses  Windows, Buttons, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,  StdCtrls;type  TForm1 = class(TForm)    procedure FormResize(Sender: TObject);  private    { Private declarations }    CaptionBtn:TRect;    procedure DrawCaptButton;    procedure WMNCPaint(var Msg:TWMNCPaint);message WM_NCPaint;    procedure WMNCActivate(var Msg:TWMNCActivate);message WM_NCActivate;    procedure WMSetText(var Msg:TWMSetText);message WM_SetText;    procedure WMNCHitTest(var Msg:TWMNCHitTest);message WM_NCHittest;    procedure WMNCLButtonDown(var Msg:TWMNCLButtonDown);message WM_NCLButtonDown;  public    { Public declarations }  end;var  Form1: TForm1;implementationconst  htCaptionBtn=htSizeLast+1;{$R *.DFM}procedure TForm1.DrawCaptButton;{绘制按钮}var  xFrame,yFrame,xSize,ySize:Integer;  R:TRect;begin  xFrame:=GetSystemMetrics(SM_CXFRAME);  yFrame:=GetSystemMetrics(SM_CYFRAME);  xSize:=GetSystemMetrics(SM_CXSIZE);  ySize:=GetSystemMetrics(SM_CYSIZE);  CaptionBtn:=Bounds(Width-xFrame-5*xSize+2,yFrame+2,xSize+13,ySize-4);  Canvas.Handle:=GetWindowDC(Self.Handle);  Canvas.Font.Name:='宋体';  Canvas.Font.Color:=clRed;  Canvas.Pen.Color:=clYellow;  Canvas.Brush.Color:=clBtnFace;  try    DrawButtonFace(Canvas,CaptionBtn,1,bsAutoDetect,False,False,False);    R:=Bounds(Width-xFrame-5*xSize+3,yFrame+3,xSize+10,ySize-7);    with CaptionBtn do      Canvas.TextRect(R,R.Left+2,R.Top,'按钮');  finally    ReleaseDC(Self.Handle,Canvas.Handle);    Canvas.Handle:=0;  end;end;procedure TForm1.WMNCActivate(var Msg: TWMNCActivate);begininherited;  DrawCaptButton;end;procedure TForm1.WMNCHitTest(var Msg: TWMNCHitTest);begininherited;  with Msg do    if PtInRect(CaptionBtn,Point(xPos-Left,yPos-Top)) then    Result:=htCaptionBtn;end;procedure TForm1.WMNCLButtonDown(var Msg: TWMNCLButtonDown);{标题栏按钮响应事件}begininherited;  if(Msg.HitTest=htCaptionBtn)then    showmessage('检验成功');end;procedure TForm1.WMNCPaint(var Msg: TWMNCPaint);begininherited;  DrawCaptButton;end;procedure TForm1.WMSetText(var Msg: TWMSetText);begininherited;  DrawCaptButton;end;procedure TForm1.FormResize(Sender: TObject);begin  Perform(WM_NCACTIVATE,Word(Active),0);end;end.///////////////////////////////////object Form1: TForm1  Left = 219  Top = 160  Width = 306  Height = 218  Caption = 'Form1'  Color = clTeal  Font.Charset = DEFAULT_CHARSET  Font.Color = clWindowText  Font.Height = -11  Font.Name = 'MS Sans Serif'  Font.Style = []  OldCreateOrder = False  OnResize = FormResize  PixelsPerInch = 96  TextHeight = 13end