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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

TranslateMessage ,GetMessage, DispatchMessage分析

發(fā)布時間:2023/12/18 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TranslateMessage ,GetMessage, DispatchMessage分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

TranslateMessage(&msg);

TranslateMessage是用來把快捷鍵消息轉(zhuǎn)換為字符消息,并將轉(zhuǎn)換后的新消息投遞到調(diào)用線程的消息隊列中。

由于Windows對所有鍵盤編碼都是采用虛擬鍵的定義,這樣當(dāng)按鍵按下時,并不得字符消息,需要鍵盤映射轉(zhuǎn)換為字符的消息。字符消息被投遞到調(diào)用線程的消息隊列中,當(dāng)下一次調(diào)用GetMessage函數(shù)時被取出。

LONG DispatchMessage(CONST MSG*lpmsg);

函數(shù)功能:該函數(shù)分發(fā)一個消息給窗口程序,即把消息推送到afxwndproc,最后流向pwnd->windowproc,而DispatchMessage是在cwinapp::run 調(diào)用pumpmessage,而pumpmessage又調(diào)用DispatchMessage。通常消息從GetMessage函數(shù)獲得或者TranslateMessage函數(shù)傳遞的。消息被分發(fā)到回調(diào)函數(shù)(過程函數(shù)),作用是消息傳遞給操作系統(tǒng),然后操作系統(tǒng)去調(diào)用我們的回調(diào)函數(shù),也就是說我們在窗體的過程函數(shù)中處理消息

在mfc2.5時代(九幾年代),所有窗口類共享同一個窗口函數(shù)(即afxwndproc)。

但現(xiàn)在使用的是鉤子技術(shù)(即hook),所以要關(guān)聯(lián)hook章節(jié)一起看。

hook操作是在每一個cwnd派生類之對象產(chǎn)生之際發(fā)生。

所以DispatchMessage把消息推送到hook技術(shù)中的afxwndproc.

?

HOOK(鉤子,掛鉤)是一種實現(xiàn)Windows平臺下類似于中斷的機制。HOOK機制允許應(yīng)用程序攔截并處理Windows消息或指定事件,當(dāng)指定的消息發(fā)出后,HOOK程序就可以在消息到達(dá)目標(biāo)窗口之前將其捕獲,從而得到對消息的控制權(quán),進(jìn)而可以對該消息進(jìn)行處理或修改,加入我們所需的功能。

定義鉤子函數(shù)

鉤子函數(shù)是一種特殊的回調(diào)函數(shù)。鉤子監(jiān)視的特定事件發(fā)生后,系統(tǒng)會調(diào)用鉤子函數(shù)進(jìn)行處理。不同事件的鉤子函數(shù)的形式是各不相同的。下面以鼠標(biāo)鉤子函數(shù)舉例說明鉤子函數(shù)的原型:

LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam)

參數(shù)wParam和 lParam包含所鉤消息的信息,比如鼠標(biāo)位置、狀態(tài),鍵盤按鍵等。

安裝鉤子

在程序初始化的時候,調(diào)用函數(shù)SetWindowsHookEx安裝鉤子。其函數(shù)原型為:

HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId )

參數(shù)idHook表示鉤子類型,它是和鉤子函數(shù)類型一一對應(yīng)的。比如,WH_KEYBOARD表示安裝的是鍵盤鉤子,WH_MOUSE表示是鼠標(biāo)鉤子等等。

卸載鉤子

當(dāng)不再使用鉤子時,必須及時卸載。簡單地調(diào)用函數(shù):

BOOL UnhookWindowsHookEx( HHOOK hhk)即可。

PeekMessage和GetMessage函數(shù)的主要區(qū)別有:

GetMessage的主要功能是從消息隊列中“取出”消息,消息被取出以后,就從消息隊列中將其刪除;而PeekMessage的主要功能是“窺視”消息,如果有消息,就返回true,否則返回false。也可以使用PeekMessage從消息隊列中取出消息,這要用到它的一個參數(shù)(UINT wRemoveMsg),如果設(shè)置為PM_REMOVE,消息則被取出并從消息隊列中刪除;如果設(shè)置為PM_NOREMOVE,消息就不會從消息隊列中取出。
如果GetMessage從消息隊列中取不到消息,則線程就會被操作系統(tǒng)掛起,等到OS重新調(diào)度該線程時,兩者的性質(zhì)不同:使用GetMessage線程仍會被掛起,使用PeekMessage線程會得到CPU的控制權(quán),運行一段時間。
GetMessage每次都會等待消息,直到取到消息才返回;而PeekMessage只是查詢消息隊列,沒有消息就立即返回,從返回值判斷是否取到了消息
PeekMessage是一個具有線程異步行為的函數(shù),不管消息隊列中是否有消息,函數(shù)都會立即返回。而GetMessage則是一個具有線程同步行為的函數(shù),如果消息隊列中沒有消息的話,函數(shù)就會一直等待,直到消息隊列中至少有一條消息時才返回。
另外:PumpMessage起到消息泵的作用,其原理就是使用GetMessage或PeekMessage函數(shù)從消息隊列中逐個讀取消息,然后進(jìn)行必要處理之后再發(fā)送出去。我們可以使用PumpMessage默認(rèn)處理過程,當(dāng)然也可以自己修改消息處理的方式。通常我們在我們自己設(shè)計窗口時也會自己設(shè)計消息循環(huán)方式。即PumpMessage函數(shù)會調(diào)用GetMessage、TranslateMessage、DispatchMessage

一般wm_xx消息

?

wm_command

?/*********************

1.windows消息循環(huán)
if (GetMessage(&msg, NULL, 0, 0)) {
? ?TranslateMessage(&msg); //消息轉(zhuǎn)化
? ?DispatchMessage(&msg); ?//消息派遣. ?把TranslateMessage轉(zhuǎn)換的消息發(fā)送到窗口的消息處理函數(shù),此函數(shù)在窗口注冊時已經(jīng)指定
? }

執(zhí)行過程:

消息循環(huán)調(diào)用GetMessage()從消息隊列中查找消息進(jìn)行處理,如果消息隊列為空,程序?qū)⑼V箞?zhí)行并等待(程序阻塞)。
事件發(fā)生時導(dǎo)致一個消息加入到消息隊列(例如系統(tǒng)注冊了一個鼠標(biāo)點擊事件),GetMessage()將返回一個正值,這表明有消息需要被處理,并且消息已經(jīng)填充到傳入的MSG參數(shù)中;當(dāng)傳入WM_QUIT消息時返回0;如果返回值為負(fù)表明發(fā)生了錯誤。
取出消息(在Msg變量中)并將其傳遞給TranslateMessage()函數(shù),這個函數(shù)做一些額外的處理:將虛擬鍵值信息轉(zhuǎn)換為字符信息。這一步實際上是可選的,但有些地方需要用到這一步。
DispatchMessage()函數(shù)將消息分發(fā)到消息的目標(biāo)窗口,并且查找目標(biāo)窗口過程函數(shù),給窗口過程函數(shù)傳遞窗口句柄、消息、wParam、lParam等參數(shù)然后調(diào)用該函數(shù)。
在窗口過程函數(shù)中,檢查消息和其他參數(shù),你可以用它來實現(xiàn)你想要的操作。如果不想處理某些特殊的消息,你應(yīng)該總是調(diào)用DefWindowProc()函數(shù),系統(tǒng)將按按默認(rèn)的方式處理這些消息(通常認(rèn)為是不做任何操作)。
一旦一個消息處理完成,窗口過程函數(shù)返回,DispatchMessage()函數(shù)返回,繼續(xù)循環(huán)處理下一個消息。
2. 函數(shù)定義
2.1GetMessage
BOOL WINAPI GetMessage(
?_Out_ ? ? LPMSG lpMsg,
?_In_opt_ ?HWND hWnd,
?_In_ ? ? ?UINT wMsgFilterMin,
?_In_ ? ? ?UINT wMsgFilterMax
);

GetMessage 函數(shù)的作用是從當(dāng)前線程的消息隊列里獲取一個消息并填入 MSG 結(jié)構(gòu) 中。
該函數(shù)只能獲取調(diào)用線程的消息,不能獲得其他線程的消息。成功獲取消息后,線程將從消息隊列中刪除該消息。
使用 GetMessage 函數(shù),如果消息隊列為空,函數(shù)會一直等待直到有消息到來才有返回值。
2.2 TranslateMessage
//BOOL TranslateMessage(CONST MSG *lpMsg);
1
參數(shù):lpMsg
指向一個含有用GetMessage或PeekMessage函數(shù)從調(diào)用線程的消息隊列中取得消息信息的MSG結(jié)構(gòu)的指針
函數(shù)功能描述:
將虛擬鍵消息轉(zhuǎn)換為字符消息。字符消息被送到調(diào)用線程的消息隊列中,在下一次線程調(diào)用函數(shù)GetMessage或PeekMessage時被讀出。
TranslateMessage函數(shù)不修改由參數(shù)lpMsg指向的消息。
2.3 DispatchMessage
函數(shù)原型:LONG DispatchMessage(CONST MSG*lpmsg);
1
參數(shù):
lpmsg:指向含有消息的MSG結(jié)構(gòu)的指針。

返回值:
返回值是窗口程序返回的值。盡管返回值的含義依賴于被調(diào)度的消息,但返回值通常被忽略。

備注:
MSG結(jié)構(gòu)必須包含有效的消息值。如果參數(shù)lpmsg指向一個WM_TIMER消息,并且WM_TIMER消息的參數(shù)IParam不為NULL,則調(diào)用IPa1ram指向的函數(shù),而不是調(diào)用窗口程序。

3. 程序?qū)嵗?br /> 如果處理時間大于定時器時間,按照處理時間循環(huán)。
如果處理時間小于定時器時間,按照定時器時間。
#pragma comment(lib,"user32")
#include <stdio.h>
#include <time.h>
#include <sys/timeb.h>
#include <windows.h>
char datestr[16];
char timestr[16];
char mss[4];
void log(char *s) {
?struct tm *now;
?struct timeb tb;
?ftime(&tb);
?now = localtime(&tb.time);
?sprintf(datestr, "%04d-%02d-%02d", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);
?sprintf(timestr, "%02d:%02d:%02d", now->tm_hour, now->tm_min, now->tm_sec);
?sprintf(mss, "%03d", tb.millitm);
?printf("%s %s.%s %s", datestr, timestr, mss, s);
}
VOID CALLBACK myTimerProc1(
?HWND hwnd, // handle of window for timer messages
?UINT uMsg, // WM_TIMER message ************
?UINT idEvent, // timer identifier
?DWORD dwTime // current system time)
?{
?log("In myTimerProc1\n");
}
VOID CALLBACK myTimerProc2(
?HWND hwnd, // handle of window for timer messages
?UINT uMsg, // WM_TIMER message
?UINT idEvent, // timer identifier
?DWORD dwTime // current system time)?
?{
?log("In myTimerProc2\n");
}

int main()?
{
?MSG msg;
?SetTimer(NULL, 0, 4000, myTimerProc1);
?SetTimer(NULL, 1, 2000, myTimerProc2);
?for (int i = 0; i<20; i++)?
?{
? Sleep(1000);
? log("In main\n");
? if (GetMessage(&msg, NULL, 0, 0))?
? {
? ?TranslateMessage(&msg); //消息處理
? ?DispatchMessage(&msg); ?//消息派遣. ?把TranslateMessage轉(zhuǎn)換的消息發(fā)送到窗口的消息處理函數(shù),此函數(shù)在窗口注冊時已經(jīng)指定
?}
?}
? return 0;
}

?

總結(jié)

以上是生活随笔為你收集整理的TranslateMessage ,GetMessage, DispatchMessage分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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