日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ BUILDER 消息处理的深入探索

發(fā)布時間:2025/3/15 c/c++ 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ BUILDER 消息处理的深入探索 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

C++ BUILDER 消息處理的深入探索

在本文中我將告訴你如何以C++Builder來處理Windows訊息,並透過此一能力,來達成在一般VCL元件所無法做到的功能。


何謂Window訊息(Message)


?大家都知道 Windows是一套以訊息驅(qū)動(Message Driven)的作業(yè)系統(tǒng)。然而對於訊息本身卻諱莫如深,只知其然而不知其所以然,雖然C++Builder將某些Windows訊息封裝於事件(Event)系統(tǒng)中,但身為一個Windows程式設(shè)計師,實有必要瞭解Windows的訊息系統(tǒng)。


所謂訊息是由Windows作業(yè)系統(tǒng)送往程式的事件。它是系統(tǒng)中各個物件溝通的方式,舉例來說,當(dāng)移動滑鼠、按下滑鼠鍵、改變視窗大小時,Windows都會送出訊息以通知程式。當(dāng)然,為了要辨別事件的內(nèi)容,Windows系統(tǒng)中定義了許多的訊息,如WM_PAINT,WM_CHAR等等。


當(dāng)事件發(fā)生時,Windows會判斷該事件必須由那個程式接收,然後將事件以訊息的方式送往程式的視窗中。雖然在Windows系統(tǒng)中包含了數(shù)以百計的事件,但是作業(yè)系統(tǒng)並沒有為各個事件設(shè)計不同的訊息結(jié)構(gòu),而是以一個一般性的結(jié)構(gòu)來描述訊息,這個結(jié)構(gòu)在C++Builder就稱是TMessage。


當(dāng)然,隨著事件的不同,對於訊息的解釋也有所不同,在C++Builder中也為各種常用的訊息定義了專屬的結(jié)構(gòu),你可以直接使用它們來解釋訊息。這些訊息定義在C++Builder目錄下的Include\vcl\messages.hpp中,你可以決定要自行解釋TMessage參數(shù)或是直接將其轉(zhuǎn)換成專屬的結(jié)構(gòu)。很抽象嗎?我舉個例子吧,以WM_NCHITTEST訊息來說,C++Builder為它定義了TWMNCHitTest的專屬結(jié)構(gòu),所以你可以直接經(jīng)由它來得到XPos、YPos等值。或者你也可以直接由TMessage的LParam取得其值,端看你使用的方便。仔細觀察TMessage及TWMNCHitTest兩個結(jié)構(gòu),你會發(fā)現(xiàn)它們是等價的,也就是說它們的大小是一致的,因此你可以直接用強制轉(zhuǎn)型互相轉(zhuǎn)換(這有點類似union的方法)。


struct TMessage

{

Cardinal Msg;

union

{

struct

{

Word WParamLo;

Word WParamHi;

Word LParamLo;

Word LParamHi;

Word ResultLo;

Word ResultHi;

};

struct

{

long WParam;

long LParam;

long Result;

};

};

};

struct TWMNCHitTest

{

Cardinal Msg;

long Unused;

union

{

struct

{

Windows::TSmallPoint Pos;

long Result;

};

struct

{

short XPos;

short YPos;

};

};

} ;


在收到訊息後,程式必須處理該訊息,若是不處理,則可直接將它交給Windows的內(nèi)定處理程序來處理之,若是程式需要傳回值,也可以在此時傳回,Windows會將該值傳回給呼叫方。如此就完成了訊息傳遞的程序。

WM_NCHITTEST訊息的奧秘


WM_NCHITTEST訊息是一個很特殊的訊息。它是用來決定目前滑鼠所在位置屬性的訊息,因此我們可以利用此特性,當(dāng)滑鼠移至指定的位置時,傳回 HTCAPTION,使得系統(tǒng)以為滑鼠目前位於標(biāo)題棒,如此你就可以移動視窗了。如何?是不是很神奇呢?


由上可知,只要我們適時地攔截WM_NCHITTEST訊息,然後傳回HTCAPTION,就可以順利地欺騙系統(tǒng),達成在任何位置模擬出標(biāo)題棒的效果。


C++ Builder的處理訊息的巨集


在C++Builder為了處理訊息的方便,因此定義了三個處理訊息的巨集(Macro)。


BEGIN_MESSAGE_MAP

MESSAGE_HANDLER(WM_NCHITTEST,TMessage,OnNcHitTest)

END_MESSAGE_MAP(TForm)


以上的三個巨集BEGIN_MESSAGE_MAP、MESSAGE_HANDLER及END_MESSAGE就是C++ Builder定義的巨集,其中比較重要的是MESSAGE_HANDLER;它共需要三個參數(shù),第一個參數(shù)代表訊息的ID,第二個代表參數(shù)型態(tài),最後一個則是訊息事件處理函數(shù)。


乍看之下,這個巨集似乎和MFC及OWL所使用的巨集有幾分神似,沒錯,不過其機制卻更為簡單及簡潔,我們可以看看C++Builder對於這三個巨集的原始定義:


#define BEGIN_MESSAGE_MAP virtual void __fastcall Dispatch(void *Message) \

{ \

switch (((PMessage)Message)->Msg) \

{

#define MESSAGE_HANDLER(msg,type,meth) \

case msg: \

meth(*((type *)Message)); \

break;

#define END_MESSAGE_MAP(base) default: \

base::Dispatch(Message); \

break; \

} \

}


相較於MFC或 OWL的可怕巨集,它實在是簡單多了,這是因為C++Builder已替你完成了大部份的工作。其實若我們把以上的巨集展開後,可以得到以下的結(jié)果:


virtual void __fastcall Dispatch(void *Message)

{

switch (((PMessage)Message)->Msg)

{

case WM_NCHITTEST:

OnNcHitTest(*((TMessage *)Message));

break;

default:

TForm::Dispatch(Message);

break;

}

}


怎麼樣?展開之後是不是有恍然大悟的感覺,要弄清楚這個巨集在賣啥膏藥是很容易的,如果你玩過MFC的訊息處理機制,再看到以上的巨集,相較之下,實在是小兒科,不過也就因其簡單,所以C++Builder的優(yōu)勢益加彰顯。


我簡單地說明以上的程式:在每個TForm中都定義一個名為Dispatch的虛擬函式,它就是用來處理Windows的訊息的,在大部份情況下,訊息都是呼叫C++Builder所提供的處理函式,因此你不需要修改它。


換句話說,我們只要改寫Dispatch函式,就可以藉以處理指定的訊息了。前面提到的三個巨集只是將這個程序簡化而已,沒什麼大不了。

?

?

總結(jié)

以上是生活随笔為你收集整理的C++ BUILDER 消息处理的深入探索的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。