大家在使用某些軟件的過程中,有沒有注意到有些軟件有一些很有趣的東西。
比如說在主窗口的標題欄上居然有一個按鈕。在Internet中隨處可見這樣的小
控件。按鈕怎麼可以加入到非客戶區(Client)呢?
在這裡,最關鍵的一點就是,大家不要被傳統知識誤導:真的認為它是
一個按鈕。有名柄(handle)的控件當然不能放在標題欄上了。有經驗的程序員
用Spy++跟蹤一下的話,馬上就會發現其中的秘密。它並不是一個按鈕,只不
過是處理成按鈕的樣子罷了。
既然知道了所以然,那麼我們為什麼不能自己來做一個呢,當然沒問題,下面我們就用
Delphi來實現它,講注意我的注解。
在具體實例之前,我們應該知道幾個關於標題欄的重要的消息:
WM_NCPAINT:重畫標題欄消息。我們必須截住它,可以在這裡重畫按鈕;
WM_NCLBUTTONDOWN:在標題欄上按下鼠標左鍵消息。我們可以截住它,在標題欄上畫出
按鈕按下的樣子,並且可以在其中進行自已的單擊事件的處理,使得它像一個按鈕;
WM_NCLBUTTONUP:在標題欄上釋放鼠標左鍵消息。我們可以截住它,在標題欄上畫出按
鈕彈起的樣子;
WM_NCLBUTTONDBLCLK:在標題欄上雙擊鼠標左鍵消息。我們可以截住它,當在按鈕區域
雙擊時,我們就該使其無效,從而避免窗體執行最大化和還原操作。
WM_NCRBUTTONDOWN:在標題欄上按下鼠標右鍵消息。我們可以截住它,當在按鈕區域雙
擊時,我們就該使其無效,從而避免彈出窗體按制菜單。
WM_NCMOUSEMOVE:在標題欄上移動鼠標消息。我們可以截住它,當鼠標移出按鈕區域
時,我們就必須畫出按鈕沒有被按下,即凸起時的樣子。
WM_NCACTIVATE:當標題欄在激活與非激活之間切換時收到該消息。我們可以截住它,
當該窗口處理激活狀態時,我們可以做一些事情,比如說將我們的標題欄按鈕上的字體
變灰或變黑來指示該窗口的當前狀態。下面我沒有加入該項功能,如果大家感興趣的
話,可以自己完成。
(大家從這裡可以發現,標題欄的消息都是WM_NC開頭的)
實例文件如下:
unit main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Menus;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
CBBtnRect: TRect; // Caption Bar Button Rectangle
CBBtnFont: TFont; // Caption Bar Button Font
procedure DrawCaptionBtn(uEdge: 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(uEdge: UINT);
var
hCaptionDC: HDC; // 標題條Device Context
hOldFont: HFONT; // 原來的字體
r: TRect;
begin
hCaptionDC := GetWindowDC(Self.Handle); // 注意不能用GetDC,那樣的話,將得不
到標題欄
// 的設備上下文
file://畫按鈕的樣子,如果uEdge=EDGE_RAISED,則畫出的樣子為凸起;如果
file://uEdge=EDGE_SUNKEN,則畫出的樣子為凹下。
DrawEdge(hCaptionDC, CBBtnRect, uEdge, BF_RECT or BF_MIDDLE or
BF_SOFT);