如何使用Delphi實(shí)現(xiàn)無(wú)邊界窗體的移動(dòng)

字號(hào):

在用Delphi制作Windows程序的窗體時(shí),窗體的邊界有四種選擇:對(duì)話(huà)框式(bsDialog),單邊固定式(bsSingle),雙邊可變式(bsSizeable),無(wú)邊界式(bsNone)。當(dāng)設(shè)置為bsNone時(shí),窗體也就沒(méi)有標(biāo)題條,很顯然,程序運(yùn)行以后就無(wú)法移動(dòng)窗體了。事實(shí)上,無(wú)邊界窗體是很有用的,例如,象Word里面的浮動(dòng)式工具箱其實(shí)就是無(wú)邊界窗體,它可以大大節(jié)約屏幕空間。那么,如何用Delphi實(shí)現(xiàn)這個(gè)功能呢?顯然,這需要修改Windows的內(nèi)部消息,也就是說(shuō),需要把“MouseDownonForm”這個(gè)消息改為“MouseDownonCaption”,這其中有三個(gè)關(guān)鍵: 捕捉MouseDown消息、判斷光標(biāo)位置、發(fā)送MouseDown消息。如果光標(biāo)在窗體中,則發(fā)送MouseDownonCaption消息。
    在Delphi的對(duì)象巡檢器中列出的所有事件是不能捕捉到Windows消息的,因?yàn)檫@些都是已經(jīng)發(fā)出的消息,無(wú)法修改了。捕捉Windows消息有兩種辦法:一個(gè)就是增加一個(gè)消息處理句柄,直接處理Windows消息;另一個(gè)是對(duì)消息進(jìn)行過(guò)濾,濾出所需消息。第二個(gè)辦法比較常用,適用于各種情況,下面就是移動(dòng)無(wú)邊界窗體程序片斷,加注釋部分是手動(dòng)加入的:
    unitUnit1;
    :
    type
    TForm1Κclass(TForm)
    procedureFormCreate(Sender:TObject);
    :
    public
    {申明消息過(guò)濾過(guò)程}
    procedureAppMessage(varMsg:TMsg;varHandled
    :Boolean);
    :
    implementation
    procedureTForm1.FormCreate(Sender:TObject)
    ;
    begin
    {捕捉消息:將程序的收到消息事件與消息過(guò)濾過(guò)程
    關(guān)聯(lián)起來(lái)}
    Application.OnMessage:ΚAppMessage;
    end;
    procedureTForm1.AppMessage(varMsg:TMsg;var
    Handled:Boolean);
    begin
    {如果鼠標(biāo)左鍵按下的話(huà)}
    ifMsg.messageΚWM—LButtonDownthen
    begin
    {判斷光標(biāo)是否在用戶(hù)工作區(qū)內(nèi)}
    ifDefWindowProc(Handle,WM—NCHitTest,0,Get
    MessagePos)ΚHTClientthen
    begin
    {發(fā)出鼠標(biāo)在用戶(hù)標(biāo)題欄內(nèi)被按下的消息}
    SendMessage(Handle,WM—NCLButtonDown,
    HTCaption,GetMessagePos);
    Handled:Κtrue;{消息處理完畢,窗體不再接受M
    ouseDown及Click事件,如果為false,程序的運(yùn)行稍微有
    些不正常。}
    end;
    end;
    end;
    end.
    程序在Delphi1.0、中文Windows3.2下運(yùn)行通過(guò)。