详解Windows消息分类以及WM_COMMAND与WM_NOTIFY的区别,以及模拟发送控件通知消息
Windows消息的分類
1.?標準消息(隊列消息)
??除WM_COMMAND之外,所有以WM_開頭的消息都是標準消息,如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR。
?????從CWnd派生的類都可以接收到這類消息。
?????Windows每次從系統(tǒng)消息隊列移走一個消息,確定它是送給哪個窗口的和這個窗口是由哪個線程創(chuàng)建的,然后,把它放進窗口創(chuàng)建線程的線程消息隊列。線程消息隊列接收送給該線程所創(chuàng)建窗口的消息。線程從消息隊列取出消息,通過Windows?把它送給適當?shù)拇翱谶^程來處理。除了鍵盤、鼠標消息以外,隊列消息還有WM_PAINT、WM_TIMER?和WM_QUIT。
注意:標準消息并不需要我們指定處理函數(shù)名稱,是默認的對應關系。例如:
???????宏名稱??????????????????????????對應消息????????????????????????消息處理函數(shù)
??????ON_WM_CHAR???????????????WM_CHAR?????????????????????????????OnChar
??????ON_WM_CLOSE?????????????WM_CLOSE??????????????????????????OnClose
???????ON_WM_CREATE???????????WM_CREATE????????????????????????OnCreate
??????ON_WM_DESTROY???????????WM_DESTROY?????????????????????OnDestroy
??????ON_WM_LBUTTONDO?????????WM_LBUTTONDOWN????????????OnLButtonDown
??????ON_WM_LBUTTONUP?????????WM_LBUTTONUP?????????????????????OnLButtonUp
??????ON_WM_MOUSEMOVE?????????WM_MOUSEMOVE?????????????????OnMouseMove
??????ON_WM_PAINT??????????????WM_PAINT??????????????????????????????????OnPaint????????
??????.........??????????????????????????????............????????????????????????????????????.......
2.命令消息
?????來自菜單、加速鍵或工具欄按鈕的消息均是命令消息。
?????這類消息都以WM_COMMAND形式呈現(xiàn)。在MFC中,通過菜單項的標識(ID)來區(qū)分不同的命令消息;在SDK中,通過消息的wParam參數(shù)識別。從CCmdTarget派生的類都可以接收到這類消息,其wParam?記錄著該消息來自哪一個菜單項目。
例如:ON_COMMAND(IDM_ABOUT,????OnAbout)
??????????ON_COMMAND(IDM_FILENEW,?OnFileNew)
??????????ON_COMMAND(IDM_FILEOPEN,?OnFileOpen)
??????????ON_COMMAND(IDM_FILESAVE,?OnFileSave)
??????????...........
3.通告消息
????由控件產生的消息,例如按鈕,列表框的選擇等都會產生通告消息,目的是為了向其父窗口(通常是對話框)通知事件的發(fā)生。
?????這類消息是以WM_COMMAND或WM_NOTIFY形式呈現(xiàn)的。從CCmdTarget派生的類(如CDocument可以接受命令消息和通告消息,但不能接收標準消息(隊列消息)),都可以接收到這類消息。
???注意:由于CWnd類派生于CCmdTarget類,所以凡是從CWnd派生的類,他們既可以接收標準消息,也可以接收命令消息和通告消息。而對于從CCmdTarget類派生的類只能接收命令消息和通告消息,不能接受標準消息。
例如:????控件??????????????宏?????????????????????????????????????????消息處理函數(shù)
??????????Button???????????ON_BN_CLICKED(<id>,<memberFxn>)???????????memberFxn
???????????ComboBox????????ON_CBN_DBLCLK(<id>,<memberFxn>)??????????memberFxn
???????????Edit???????????????ON_EN_SETFOCUS(<id>,<memberFxn>)???????memberFxn
??????????ListBox??????????ON_LBN_DBLCLK(<id>,<memberFxn>)??????????memberFxn
?????????.........??????????????......................?????????????...........
?
標準消息和非標準消息的區(qū)分:
????標準消息:?帶有有控制后后續(xù)操作;
????非標準消息:只是簡單提示。
?
MFC命令消息的路由:
AfxWndProc(替換了窗口過程函數(shù))->AfxCallWndProc->WindowProc->OnWnddMsg->(如果是命令消息則調用Oncommand;如果是通告消息則調用OnNotify)->OnCmdMsg
那么通告消息到底是WM_COMMAND還是WM_NOTIFY呢?
解釋一:WM_NOTIFY比WM_COMMAND?功能更強大,可以存儲一些額外的信息,WM_COMMAND?并不被所有的控件所支持。
解釋二:Edit,Button,ListBox等發(fā)送WM_COMMAND消息,ListView,Toolbar,Tree等編譯時如果不聯(lián)接comctl32.lib就通不過的。Common,Controls發(fā)送WM_NOTIFY消息,因為需要提供的信息更多。
?
?
給對話框中的控件發(fā)送消息:
想要給CTreeCtrl控件模擬發(fā)送一個TCN_SELCHANGE消息。
想要給CButton控件模擬發(fā)送一個BN_CLICKED消息。
?
★??由上面對windows消息的分類,我們得知,這兩個消息都是通告消息。那是用?WM_COMMAND還是WM_NOTIFY呢?
根據上面的解釋,我們使用?TCN_SELCHANGE--WM_NOTIFY?,BN_CLICKED--WM_COMMAND。
是不是這樣呢?咱們參看MSDN:
TCN_SELCHANGE
TCN_SELCHANGE
????lpnmhdr?=?(LPNMHDR)?lParam;
Notifies?a?tab?control's?parent?window?that?the?currently?selected?tab?has?changed.?This?message?is?sent?in?the?form?of?a??message.
-
No?return?value.
lpnmhdrAddress?of?an??structure.?The?hwndFrom?member?is?the?handle?to?the?tab?control.?The?idFrommember?is?the?child?window?identifier?of?the?tab?control.?The?code?member?is?TCN_SELCHANGE.
由上看出TCN_SELCHANGE確實是以呈現(xiàn)的,它包含以一個結構體指針的形式包含在lParam中。
typedef?struct?tagNMHDR?{?HWND?hwndFrom;?UINT?idFrom;?UINT?code;?}?NMHDR;
Contains?information?about?a?notification?message.
hwndFromWindow?handle?to?the?control?sending?a?message.idFromIdentifier?of?the?control?sending?a?message.codeNotification?code.?This?member?can?be?a?control-specific?notification?code?or?it?can?be?one?of?the?common?notification?codes.
?
BN_CLICKED
The?BN_CLICKED?notification?message?is?sent?when?the?user?clicks?a?button.?The?parent?window?of?the?button?receives?this?notification?message?through?the?WM_COMMAND?message.
BN_CLICKED?idButton?=?(int)?LOWORD(wParam);?//?identifier?of?button?hwndButton?=?(HWND)?lParam;?//?handle?to?button
由上看出BN_CLICKED確實是包含在WM_COMMAND?中的。
?
?
★??怎樣把通告消息溶到WM_COMMAND?和?中呢?
WM_NOTIFY
????idCtrl?=?(int)?wParam;
????pnmh?=?(LPNMHDR)?lParam;idCtrlIdentifier?of?the?common?control?sending?the?message.pnmhAddress?of?an??structure?that?contains?the?notification?code?and?additional?information.?
WM_COMMAND
wNotifyCode?=?HIWORD(wParam);?//?notification?code
wID?=?LOWORD(wParam);?????????//?item,?control,?or?accelerator?identifier
hwndCtl?=?(HWND)?lParam;??????//?handle?of?control
組裝參數(shù):
LPARAM?MAKELPARAM(
??WORD?wLow,??//?low-order?word
??WORD?wHigh??//?high-order?word
);
或者
DWORD?MAKELONG(
??WORD?wLow,??//?low-order?word?of?long?value
??WORD?wHigh??//?high-order?word?of?long?value?);
?
★??向控件發(fā)消息我們可以使用以下兩個方法:?
LONG?SendDlgItemMessage(
??HWND?hDlg,??????//?handle?of?dialog?box
??int?nIDDlgItem,?//?identifier?of?control
??UINT?Msg,???????//?message?to?send
??WPARAM?wParam,??//?first?message?parameter
??LPARAM?lParam???//?second?message?parameter
);
或者
LRESULT?SendMessage(
??HWND?hWnd,??????//?handle?of?destination?window
??UINT?Msg,???????//?message?to?send
??WPARAM?wParam,??//?first?message?parameter
??LPARAM?lParam???//?second?message?parameter
);
?
★??實例,驗證成功:
?//模擬發(fā)送TCN_SELCHANGE消息
?NMHDR??nmhdr;
?nmhdr.code?=?TCN_SELCHANGE;??????
?nmhdr.hwndFrom?=?g_pMainDlg->m_TabCtrl.GetSafeHwnd();??????
?nmhdr.idFrom=?g_pMainDlg->m_TabCtrl.GetDlgCtrlID();
?::SendDlgItemMessage(g_pMainDlg->m_hWnd,IDC_TAB1,WM_NOTIFY,MAKELONG(TCN_SELCHANGE,0),(LPARAM)(&nmhdr));?
//發(fā)送BN_CLICKED消息
::SendMessage(g_pMainDlg->m_VNOnLine.m_hWnd,WM_COMMAND,MAKELPARAM(IDC_RANG_OFF,BN_CLICKED),(LPARAM)(::GetDlgItem(g_pMainDlg->m_VNOnLine.m_hWnd,IDC_RANG_OFF)));
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的详解Windows消息分类以及WM_COMMAND与WM_NOTIFY的区别,以及模拟发送控件通知消息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么黑学校计算机室的电脑,大学计算机室变
- 下一篇: php可以支持代码重用技术的命令,Lin