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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

TranslateMessage ,GetMessage, DispatchMessage分析

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

TranslateMessage(&msg);

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

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

LONG DispatchMessage(CONST MSG*lpmsg);

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

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

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

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

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

?

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

定義鉤子函數(shù)

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

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

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

安裝鉤子

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

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

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

卸載鉤子

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

BOOL UnhookWindowsHookEx( HHOOK hhk)即可。

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

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

執(zhí)行過(guò)程:

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

GetMessage 函數(shù)的作用是從當(dāng)前線程的消息隊(duì)列里獲取一個(gè)消息并填入 MSG 結(jié)構(gòu) 中。
該函數(shù)只能獲取調(diào)用線程的消息,不能獲得其他線程的消息。成功獲取消息后,線程將從消息隊(duì)列中刪除該消息。
使用 GetMessage 函數(shù),如果消息隊(duì)列為空,函數(shù)會(huì)一直等待直到有消息到來(lái)才有返回值。
2.2 TranslateMessage
//BOOL TranslateMessage(CONST MSG *lpMsg);
1
參數(shù):lpMsg
指向一個(gè)含有用GetMessage或PeekMessage函數(shù)從調(diào)用線程的消息隊(duì)列中取得消息信息的MSG結(jié)構(gòu)的指針
函數(shù)功能描述:
將虛擬鍵消息轉(zhuǎn)換為字符消息。字符消息被送到調(diào)用線程的消息隊(duì)列中,在下一次線程調(diào)用函數(shù)GetMessage或PeekMessage時(shí)被讀出。
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指向一個(gè)WM_TIMER消息,并且WM_TIMER消息的參數(shù)IParam不為NULL,則調(diào)用IPa1ram指向的函數(shù),而不是調(diào)用窗口程序。

3. 程序?qū)嵗?br /> 如果處理時(shí)間大于定時(shí)器時(shí)間,按照處理時(shí)間循環(huán)。
如果處理時(shí)間小于定時(shí)器時(shí)間,按照定時(shí)器時(shí)間。
#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ù)在窗口注冊(cè)時(shí)已經(jīng)指定
?}
?}
? return 0;
}

?

總結(jié)

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

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