【转】详解Windows消息分类以及WM_COMMAND与WM_NOTIFY的区别,以及模拟发送控件通知消息
轉自:http://blog.sina.com.cn/s/blog_4b3c1f950100nten.html
?
Windows消息的分類
1.?標準消息(隊列消息)
 ??除WM_COMMAND之外,所有以WM_開頭的消息都是標準消息,如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR。
?????從CWnd派生的類都可以接收到這類消息。
?????Windows每次從系統消息隊列移走一個消息,確定它是送給哪個窗口的和這個窗口是由哪個線程創建的,然后,把它放進窗口創建線程的線程消息隊列。線程消息隊列接收送給該線程所創建窗口的消息。線程從消息隊列取出消息,通過Windows?把它送給適當的窗口過程來處理。除了鍵盤、鼠標消息以外,隊列消息還有WM_PAINT、WM_TIMER?和WM_QUIT。
?
注意:標準消息并不需要我們指定處理函數名稱,是默認的對應關系。
例如:
???????宏名稱??????????????????????????對應消息????????????????????????消息處理函數
??????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形式呈現。在MFC中,通過菜單項的標識(ID)來區分不同的命令消息;在SDK中,通過消息的wParam參數識別。從CCmdTarget派生的類都可以接收到這類消息,其wParam?記錄著該消息來自哪一個菜單項目。
例如:ON_COMMAND(IDM_ABOUT,????OnAbout)
 ??????????ON_COMMAND(IDM_FILENEW,?OnFileNew)
 ??????????ON_COMMAND(IDM_FILEOPEN,?OnFileOpen)
 ??????????ON_COMMAND(IDM_FILESAVE,?OnFileSave)
??????????...........
3.通告消息
 ????由控件產生的消息,例如按鈕,列表框的選擇等都會產生通告消息,目的是為了向其父窗口(通常是對話框)通知事件的發生。
?????這類消息是以WM_COMMAND或WM_NOTIFY形式呈現的。從CCmdTarget派生的類(如CDocument可以接受命令消息和通告消息,但不能接收標準消息(隊列消息)),都可以接收到這類消息。
 ???注意:由于CWnd類派生于CCmdTarget類,所以凡是從CWnd派生的類,他們既可以接收標準消息,也可以接收命令消息和通告消息。而對于從CCmdTarget類派生的類只能接收命令消息和通告消息,不能接受標準消息。
例如:????控件??????????????宏?????????????????????????????????????????消息處理函數
??????????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
?????????.........??????????????......................?????????????...........
?
標準消息和非標準消息的區分:
????標準消息:?帶有有控制后后續操作;
????非標準消息:只是簡單提示。
?
MFC命令消息的路由:
AfxWndProc(替換了窗口過程函數)->AfxCallWndProc->WindowProc->OnWnddMsg->(如果是命令消息則調用Oncommand;如果是通告消息則調用OnNotify)->OnCmdMsg
?
那么通告消息到底是WM_COMMAND還是WM_NOTIFY呢?
解釋一:WM_NOTIFY比WM_COMMAND?功能更強大,可以存儲一些額外的信息,WM_COMMAND?并不被所有的控件所支持。
解釋二:Edit,Button,ListBox等發送WM_COMMAND消息,ListView,Toolbar,Tree等編譯時如果不聯接comctl32.lib就通不過的。Common,Controls發送WM_NOTIFY消息,因為需要提供的信息更多。
?
?
給對話框中的控件發送消息:
想要給CTreeCtrl控件模擬發送一個TCN_SELCHANGE消息。
想要給CButton控件模擬發送一個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確實是以呈現的,它包含以一個結構體指針的形式包含在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?=?(LPNwCtrlIdentifier?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
組裝參數:
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?);
?
★??向控件發消息我們可以使用以下兩個方法:?
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
);
?
 ★??實例,驗證成功:
?//模擬發送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));?
 //發送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)));
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【转】详解Windows消息分类以及WM_COMMAND与WM_NOTIFY的区别,以及模拟发送控件通知消息的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 业绩比较基准是年利率吗?区别很大!
- 下一篇: 交电费可以刷信用卡吗
