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