• 自绘标题栏


    https://bbs.csdn.net/topics/245498

    -- 大家在使用某些软件的过程中,有没有注意到有些软件有一些很有趣的东西。比如说在主窗口的标题栏上居然有一个按钮。在Internet中随处可见这样的小控件。按钮怎么可以加入到非客户区(Client)呢? 
    
    ---- 在这里,最关键的一点就是,大家不要被传统知识误导:真的认为它是一个按钮。有名柄(handle)的控件当然不能放在标题栏上了。有经验的程序员用Spy++跟踪一下的话,马上就会发现其中的秘密。它并不是一个按钮,只不过是处理成按钮的样子罢了。 
    
    ---- 既然知道了所以然,那么我们为什么不能自己来做一个呢,当然没问题,下面我们就用Delphi来实现它,讲注意我的注解。 
    
    ---- 在具体实例之前,我们应该知道几个关于标题栏的重要的消息: 
    
    ---- WM_NCPAINT:重画标题栏消息。我们必须截住它,可以在这里重画按钮; 
    
    ---- WM_NCLBUTTONDOWN:在标题栏上按下鼠标左键消息。我们可以截住它,在标题栏上画出按钮按下的样子,并且可以在其中进行自已的单击事件的处理,使得它像一个按钮; 
    
    ---- WM_NCLBUTTONUP:在标题栏上释放鼠标左键消息。我们可以截住它,在标题栏上画出按钮弹起的样子; 
    
    ---- WM_NCLBUTTONDBLCLK:在标题栏上双击鼠标左键消息。我们可以截住它,当在按钮区域双击时,我们就该使其无效,从而避免窗体执行最大化和还原操作。 
    
    ---- WM_NCRBUTTONDOWN:在标题栏上按下鼠标右键消息。我们可以截住它,当在按钮区域双击时,我们就该使其无效,从而避免弹出窗体按制菜单。 
    
    ---- WM_NCMOUSEMOVE:在标题栏上移动鼠标消息。我们可以截住它,当鼠标移出按钮区域时,我们就必须画出按钮没有被按下,即凸起时的样子。 
    
    ---- WM_NCACTIVATE:当标题栏在激活与非激活之间切换时收到该消息。我们可以截住它,当该窗口处理激活状态时,我们可以做一些事情,比如说将我们的标题栏按钮上的字体变灰或变黑来指示该窗口的当前状态。下面我没有加入该项功能,如果大家感兴趣的话,可以自己完成。 
    
    ---- (大家从这里可以发现,标题栏的消息都是WM_NC开头的) 
    ////////////////////////////////////////////////////////////////////////////////
    unit Capbtn;
    
    interface
    
    uses
     SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
     Forms, Dialogs, Buttons;
    
    type
     TTitleBtnForm = class(TForm)
       procedure FormResize(Sender: TObject);
     private
       TitleButton : TRect;
       procedure DrawTitleButton;
       {Paint-related messages}
       procedure WMSetText(var Msg : TWMSetText); message WM_SETTEXT;
       procedure WMNCPaint(var Msg : TWMNCPaint); message WM_NCPAINT;
       procedure WMNCActivate(var Msg : TWMNCActivate); message WM_NCACTIVATE;
       {Mouse down-related messages}
       procedure WMNCHitTest(var Msg : TWMNCHitTest); message WM_NCHITTEST;
       procedure WMNCLButtonDown(var Msg : TWMNCLButtonDown); message 
    
    WM_NCLBUTTONDOWN;
       function GetVerInfo : DWORD;
     end;
    
    var
     TitleBtnForm: TTitleBtnForm;
    
    const
     htTitleBtn = htSizeLast + 1;
    
    implementation
    {$R *.DFM}
    
    procedure TTitleBtnForm.DrawTitleButton;
    var
     bmap : TBitmap; {Bitmap to be drawn - 16 X 16 : 16 Colors}
     XFrame,  {X and Y size of Sizeable area of Frame}
     YFrame,
     XTtlBit, {X and Y size of Bitmaps in caption}
     YTtlBit  : Integer;
    begin
     {Get size of form frame and bitmaps in title bar}
     XFrame  := GetSystemMetrics(SM_CXFRAME);
     YFrame  := GetSystemMetrics(SM_CYFRAME);
     XTtlBit := GetSystemMetrics(SM_CXSIZE);
     YTtlBit := GetSystemMetrics(SM_CYSIZE);
    
     {$IFNDEF WIN32}
       TitleButton := Bounds(Width - (3 * XTtlBit) - ((XTtlBit div 2) - 2),
                             YFrame - 1,
                             XTtlBit + 2,
                             YTtlBit + 2);
    
     {$ELSE}     {Delphi 2.0 positioning}
       if (GetVerInfo = VER_PLATFORM_WIN32_NT) then
         TitleButton := Bounds(Width - (3 * XTtlBit) - ((XTtlBit div 2) - 2),
                               YFrame - 1,
                               XTtlBit + 2,
                               YTtlBit + 2)
       else
         TitleButton := Bounds(Width - XFrame - 4*XTtlBit + 2,
                              XFrame + 2,
                              XTtlBit + 2,
                              YTtlBit + 2);
     {$ENDIF}
    
    
     Canvas.Handle := GetWindowDC(Self.Handle); {Get Device context for drawing}
     try
       {Draw a button face on the TRect}
       DrawButtonFace(Canvas, TitleButton, 1, bsAutoDetect, False, False, False);
       bmap := TBitmap.Create;
       bmap.LoadFromFile('help.bmp');
       with TitleButton do
         {$IFNDEF WIN32}
           Canvas.Draw(Left + 2, Top + 2, bmap);
         {$ELSE}
           if (GetVerInfo = VER_PLATFORM_WIN32_NT) then
             Canvas.Draw(Left + 2, Top + 2, bmap)
           else
             Canvas.StretchDraw(TitleButton, bmap);
         {$ENDIF}
    
     finally
       ReleaseDC(Self.Handle, Canvas.Handle);
       bmap.Free;
       Canvas.Handle := 0;
     end;
    end;
    
    {Paint triggering events}
    procedure TTitleBtnForm.WMNCActivate(var Msg : TWMNCActivate);
    begin
     Inherited;
     DrawTitleButton;
    end;
    
    procedure TTitleBtnForm.FormResize(Sender: TObject);
    begin
     Perform(WM_NCACTIVATE, Word(Active), 0);
    end;
    
    {Painting events}
    procedure TTitleBtnForm.WMNCPaint(var Msg : TWMNCPaint);
    begin
     Inherited;
     DrawTitleButton;
    end;
    
    procedure TTitleBtnForm.WMSetText(var Msg : TWMSetText);
    begin
     Inherited;
     DrawTitleButton;
    end;
    
    {Mouse-related procedures}
    procedure TTitleBtnForm.WMNCHitTest(var Msg : TWMNCHitTest);
    begin
     Inherited;
     {Check to see if the mouse was clicked in the area of the button}
     with Msg do
       if PtInRect(TitleButton, Point(XPos - Left, YPos - Top)) then
         Result := htTitleBtn;
    end;
    
    procedure TTitleBtnForm.WMNCLButtonDown(var Msg : TWMNCLButtonDown);
    begin
     inherited;
     if (Msg.HitTest = htTitleBtn) then
       ShowMessage('You pressed the new button');
    end;
    
    function TTitleBtnForm.GetVerInfo : DWORD;
    var
    verInfo : TOSVERSIONINFO;
    begin
     verInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
     if GetVersionEx(verInfo) then
       Result := verInfo.dwPlatformID;
       {Returns:
         VER_PLATFORM_WIN32s             Win32s on Windows 3.1
         VER_PLATFORM_WIN32_WINDOWS        Win32 on Windows 95
         VER_PLATFORM_WIN32_NT           Windows NT }
    end;
    
    end.
  • 相关阅读:
    关于android的一些博文收集
    关于Synchronized关键字锁住对象的嵌套问题
    eclipse个人觉得有用的快捷键
    关于android 数据库查询出现 _id column do not exist 的处理
    【转】经典网文:追MM与设计模式
    Maven学习总结(28)——Maven+Nexus+Myeclipse集成
    Spring MVC学习总结(9)——Spring MVC整合swagger自动生成api接口文档
    Windows学习总结(7)——学会CMD命令提示符的重要性
    ActiveMQ学习总结(10)——ActiveMQ采用Spring注解方式发送和监听
    SVN学习总结(3)——分支合并
  • 原文地址:https://www.cnblogs.com/CipherLab/p/13091984.html
Copyright © 2020-2023  润新知