對於我們熟悉的標准windows窗口來講,標題欄上一般包含有3個按鈕,即最大化按鈕,最小化按鈕和關閉按鈕。你想不想在Windows的窗口標題欄上添加一個新的自定義按鈕,滿足你的個性化需求,從而也使自己的窗口更具特色呢?!
下面我們就討論一下在Delphi中如何給窗口的標題欄上添加新的按鈕。
一、實現起來要定義以下過程:
1、 定義DrawCaptButton過程,這個過程的功能是在指定的位置畫出按鈕。
在過程中要使用win32函數GetSystemMetrics得到窗口的大小和標題按鈕的大小;使用delphi函數Bounds定義一個矩形,這個矩形就是新按鈕的位置;再定義一個小的矩形,這個矩形是為了填寫文本;最後就調用delphi中比較有用的函數drawbuttonface把按鈕畫出來。
2、 每次我們對窗口進行操作,例如,最大化操作或最小化操作,新按鈕就會消失,為了解決這個問題,我們對所有的消息要進行處理,給每個消息編寫一個過程對按鈕進行重畫。
A、定義WMNCPaint(var Msg:TWMNCPaint)過程,處理消息WM_NCPaint。
B、定義WMNCActivate(var Msg :TWMNCActivate)過程,處理消息WM_NCACTIVATE。
C、定義WMSetText(var Msg:TWMSetText)過程,處理消息WM_SETTEXT。
D、定義WMNCHitTest(var Msg :TWMNCHitTest)過程,處理消息WM_NCHITTEST。
E、定義WMNCLButtonDown(var Msg : TWMNCLButtonDown)過程,處理消息WM_NCLBUTTONDOWN。
二、 具體的源程序如下:
我們結合源程序來講述過程的實現,從中可以看出程序對win32函數的調用,以及drawbuttonface函數的使用方法。
unit Main;
interface
uses
Windows, Buttons, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormResize(Sender: TObject);
private
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;
implementation
const
htCaptionBtn = htSizeLast + 1;
{$R *.DFM}
procedure TForm1.DrawCaptButton;
file://drawcapbuttton過程的具體實現
var
xFrame,
yFrame,
xSize,
ySize : Integer;
R : TRect;
begin
xFrame := GetSystemMetrics(SM_CXFRAME);
yFrame := GetSystemMetrics(SM_CYFRAME);
file://把窗口的寬度置於變量xFrame,把窗口的高度置於變量yFrame
xSize:= GetSystemMetrics(SM_CXSIZE);
ySize:= GetSystemMetrics(SM_CYSIZE);
// 把標題欄按鈕的寬度置於變量xSize,把標題欄按鈕的高度置於變量ySize
CaptionBtn := Bounds(Width - xFrame - 4*xSize + 2,
yFrame + 2, xSize - 2, ySize - 4);
file://定義出新的標題按鈕的位置,值放在變量CaptionBtn中
Canvas.Handle := GetWindowDC(Self.Handle);
file://得到窗口的句柄
Canvas.Font.Name := 'Symbol';
Canvas.Font.Color := clBlue;
Canvas.Font.Style := [fsBold];
Canvas.Pen.Color := clYellow;
Canvas.Brush.Color := clBtnFace;
file://定義畫布的字體、畫筆、刷子等屬性
try
DrawButtonFace(Canvas, CaptionBtn, 1, bsAutoDetect, False, False, False);
file://在畫布上畫出定義的按鈕
R := Bounds(Width - xFrame - 4 * xSize + 2,
yFrame + 3, xSize - 6, ySize - 7);
file://在新按鈕上畫出一個小矩形
with CaptionBtn do
Canvas.TextRect(R, R.Left + 2, R.Top - 1, 'W');
file://在上面畫出的小矩形上填寫一個字符'w'字符
finally
ReleaseDC(Self.Handle, Canvas.Handle);
Canvas.Handle := 0;
file://容錯處理,假如出現異常,把句柄釋放掉
end;
end;
procedure TForm1.WMNCPaint(var Msg : TWMNCPaint);
//WMNCPaint過程的具體實現,該過程在繪制窗口時被調用
begin
inherited;//繼續默認的消息處理程序
DrawCaptButton;//對按鈕進行重畫
end;
procedure TForm1. (var Msg : TWMNCActivate);
// WMNCActivate過程與WMNCPaint過程實現方法相同,該過程在窗口的非客戶區要更改為激活狀態或非激活狀態時被調用
begin
inherited;
DrawCaptButton;
end;
procedure TForm1.WMSetText(var Msg : TWMSetText);
// WMSetText過程與WMNCPaint過程實現方法相同,該過程在設置窗口的文本時被調用
begin
inherited;
DrawCaptButton;
end;
procedure TForm1.WMNCHitTest(var Msg : TWMNCHitTest);
file:// WMNCHitTest過程與WMNCPaint過程實現方法相同,該過程在光標移動或鼠標按鈕被按下或鼠標按鈕被釋放時調用
begin
inherited;
with Msg do
if PtInRect(CaptionBtn, Point(XPos - Left, YPos - Top)) then
Result := htCaptionBtn;//判定鼠標所在位置是否在新按鈕的矩形范圍內,假如在返回新按鈕的標識值
end;
procedure TForm1.WMNCLButtonDown(var Msg : TWMNCLButtonDown);
// WMNCLButtonDown過程與WMNCPaint過程實現方法相同,當光標處於窗口非客戶區范圍內鼠標左鍵被按下時調用該過程
begin
inherited;
if (Msg.HitTest = htCaptionBtn) then
ShowMessage('你點擊的是標題欄上的新按鈕');
file://判定被點擊的是否是新按鈕,假如是顯示上面的信息,在這裡你可以按你的需要編寫程序代碼
end;
procedure TForm1.FormResize(Sender: TObject);
begin
Perform(WM_NCACTIVATE, Word(Active), 0);
file://假如窗口大小改變則重畫標題欄
end;
end.