MFC 消息响应与消息处理过程
生活随笔
收集整理的這篇文章主要介紹了
MFC 消息响应与消息处理过程
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
WPARAM 和 LPARAM,消息響應(yīng)機(jī)制
wParam和lParam 這兩個(gè)是Win16系統(tǒng)遺留下來的產(chǎn)物,在Win16API中WndProc有兩個(gè)參數(shù):
一個(gè)是WORD類型的16位整型變量;另一個(gè)是LONG類型的32位整型變量。因此根據(jù)匈牙利命名法,16位的變量就被命名為wParam, 32位的變量就被命名為lParam。 到了Win32API中,原來的16位變量也被擴(kuò)展為32位,因此此時(shí)wParam和lParam的大小完全相同。
在Win32API的早期,為了保證和Win16API的代碼可移植性MS定義了WPARAM和LPARAM兩個(gè)宏。
當(dāng)時(shí)保留了w前綴的原因一方面是由于WPARAM宏也已W開頭,還有也因?yàn)橐嵝殉绦騿T注意到可移植性,當(dāng)然到了現(xiàn)在Win16早已退出歷史舞臺,這個(gè)前綴也就約定俗成的沿用下來了。
例如:主程序MyDlg.cpp
1.自定義消息:#define WM_TRAY WM_USER 100
2.函數(shù)原形:afx_msg LRESULT OnTrayNotify(WPARAM wParam,LPARAM lParam);
3.消息映射:ON_MESSAGE(WM_TRAY,OnTrayNotify)
4.原函數(shù):
LRESULT CMyDlg::OnTrayNotify(WPARAM wParam,LPARAM lParam)
{
return m_tray.OnTrayNotify(wParam,lParam);
} 托盤類的實(shí)現(xiàn)程序Tray.cpp
成員函數(shù):
int OnTrayNotify(WPARAM wID,LPARAM lEvent)
{
if(wID == TRAYNOTIFYDATA.uID)
return 0;
if(lEvent == WM_LBUTTONDOWN){
處理代碼
}
else if(lEvent == WM_RBUTTONDOWN){
處理代碼
}
return 0;
}
WPARAM 和 LPARAM 本質(zhì)上沒有什么區(qū)別:都是32位數(shù),
但是區(qū)別也還是有的:除了上面幾位若仁兄說的關(guān)于16位的的歷史問題外,MICROSOFT在使用時(shí)兩種參數(shù)分別代表不同的含義和內(nèi)容,WPARAM常常代表一些控件的ID或者高位底位組合起來分別表示鼠標(biāo)的位置,如果消息的發(fā)送者需要將某種結(jié)構(gòu)的指針或者是某種類型的句柄時(shí),習(xí)慣上用LPARAM來傳遞,可以參考各種控件的通知消息:可以查看:EN_CHANGE (EDIT控件的一個(gè)通知消息),CBEM_INSERTITEM(可擴(kuò)展組合框的可接受消息)等等來加以領(lǐng)會。
理論上在使用自定義消息時(shí),WPARAM LPARAM的含義可以程序員任意指定的,但是最好遵從MFC中的習(xí)慣。在調(diào)用SendMessage()函數(shù)時(shí),第二個(gè)參數(shù)是WPARAM,第三個(gè)參數(shù)是這個(gè)消息的LPARAM,但是你在程序中某個(gè)類中寫下ON_MESSAGE()宏來處理這個(gè)消息時(shí),處理函數(shù)SomeHandler(WPARAM,LPRAM(默認(rèn)是0))中解釋這兩個(gè)參數(shù)時(shí)必須按照SendMessage調(diào)用中的意義來進(jìn)行。消息響應(yīng)機(jī)制
1、消息的組成:一個(gè)消息由一個(gè)消息名稱(UINT),和兩個(gè)參數(shù)(WPARAM,LPARAM)。當(dāng)用戶進(jìn)行了輸入或是窗口的狀態(tài)發(fā)生改變時(shí)系統(tǒng)都會發(fā)送消息到某一個(gè)窗口。例如當(dāng)菜單轉(zhuǎn)中之后會有WM_COMMAND消息發(fā)送,WPARAM的高字中(HIWORD(wParam))是命令的ID號,對菜單來講就是菜單ID。當(dāng)然用戶也可以定義自己的消息名稱,也可以利用自定義消息來發(fā)送通知和傳送數(shù)據(jù)。 2、誰將收到消息:一個(gè)消息必須由一個(gè)窗口接收。在窗口的過程(WNDPROC)中可以對消息進(jìn)行分析,對自己感興趣的消息進(jìn)行處理。例如你希望對菜單選擇進(jìn)行處理那么你可以定義對WM_COMMAND進(jìn)行處理的代碼,如果希望在窗口中進(jìn)行圖形輸出就必須對WM_PAINT進(jìn)行處理。 3、未處理的消息到那里去了:M$為窗口編寫了默認(rèn)的窗口過程,這個(gè)窗口過程將負(fù)責(zé)處理那些你不處理消息。正因?yàn)橛辛诉@個(gè)默認(rèn)窗口過程我們才可以利用Windows的窗口進(jìn)行開發(fā)而不必過多關(guān)注窗口各種消息的處理。例如窗口在被拖動時(shí)會有很多消息發(fā)送,而我們都可以不予理睬讓系統(tǒng)自己去處理。 4、窗口句柄:說到消息就不能不說窗口句柄,系統(tǒng)通過窗口句柄來在整個(gè)系統(tǒng)中唯一標(biāo)識一個(gè)窗口,發(fā)送一個(gè)消息時(shí)必須指定一個(gè)窗口句柄表明該消息由那個(gè)窗口接收。而每個(gè)窗口都會有自己的窗口過程,所以用戶的輸入就會被正確的處理。例如有兩個(gè)窗口共用一個(gè)窗口過程代碼,你在窗口一上按下鼠標(biāo)時(shí)消息就會通過窗口一的句柄被發(fā)送到窗口一而不是窗口二。 5、示例:下面有一段偽代碼演示如何在窗口過程中處理消息 LONG yourWndProc(HWND hWnd,UINT uMessageType,WPARAM wP,LPARAM)
{switch(uMessageType){//使用SWITCH語句將各種消息分開case(WM_PAINT):doYourWindow(...);//在窗口需要重新繪制時(shí)進(jìn)行輸出break;case(WM_LBUTTONDOWN):doYourWork(...);//在鼠標(biāo)左鍵被按下時(shí)進(jìn)行處理break;default:callDefaultWndProc(...);//對于其它情況就讓系統(tǒng)自己處理break;}
}接下來談?wù)勈裁词窍C(jī)制:系統(tǒng)將會維護(hù)一個(gè)或多個(gè)消息隊(duì)列,所有產(chǎn)生的消息都回被放入或是插入隊(duì)列中。系統(tǒng)會在隊(duì)列中取出每一條消息,根據(jù)消息的接收句柄而將該消息發(fā)送給擁有該窗口的程序的消息循環(huán)。每一個(gè)運(yùn)行的程序都有自己的消息循環(huán),在循環(huán)中得到屬于自己的消息并根據(jù)接收窗口的句柄調(diào)用相應(yīng)的窗口過程。而在沒有消息時(shí)消息循環(huán)就將控制權(quán)交給系統(tǒng)所以Windows可以同時(shí)進(jìn)行多個(gè)任務(wù)。下面的偽代碼演示了消息循環(huán)的用法: while(1)
{id=getMessage(...);if(id == quit)break;translateMessage(...);
}
當(dāng)該程序沒有消息通知時(shí)getMessage就不會返回,也就不會占用系統(tǒng)的CPU時(shí)間。
總結(jié)
以上是生活随笔為你收集整理的MFC 消息响应与消息处理过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设置 shell 脚本中 echo 显示
- 下一篇: Idea 同一工程根据不同配置文件启动、