我們以CListCtrl控制項為例來分析WM_NOTIFY訊息。
CListCtrl控制項在Report樣式下會包含CHeaderCtrl標題控制項,即CHeaderCtrl標題控制項為CListCtrl控制項的子控制項,所以不難理解,拖動CHeaderCtrl標題控制項的列分隔欄會投遞HDN_BEGINTRACK訊息(WM_NOTIFY訊息,通知碼為HDN_BEGINTRACK)給其父視窗CListCtrl控制項。
但是,我們在對話方塊視窗中也可以收到CHeaderCtrl標題控制項的HDN_BEGINTRACK訊息,這作何解釋呢?
如下所示:我們在對話方塊視窗中響應HDN_BEGINTRACK訊息,當開始拖動標題控制項時,彈出訊息框提示。
BEGIN_MESSAGE_MAP(CTestDlgDlg, CDialog) ......ON_NOTIFY(HDN_BEGINTRACK, 0, &CTestDlgDlg::OnHdnBegintrackList1) ......END_MESSAGE_MAP()void CTestDlgDlg::OnHdnBegintrackList1(NMHDR *pNMHDR, LRESULT *pResult){LPNMHEADER phdr = reinterpret_cast(pNMHDR);// TODO: Add your control notification handler code hereAfxMessageBox(TEXT("CHeaderCtrl HDN_BEGINTRACK訊息!"));*pResult = 0;}
效果如下:
在文章MFC訊息處理流程概述中可知,CListCtrl控制項視窗在接收到HDN_BEGINTRACK訊息時,會調用以下代碼處理:
LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // OnWndMsg does most of the work, except for DefWindowProc call LRESULT lResult = 0; if (!OnWndMsg(message, wParam, lParam, &lResult)) lResult = DefWindowProc(message, wParam, lParam); return lResult; }
很顯然,HDN_BEGINTRACK訊息在CListCtrl的訊息映射表中沒有對應的訊息處理函數處理,在CHeaderCtrl的訊息映射表也無對應的反射訊息處理函數處理,所以,以上代碼OnWndMsg(message, wParam, lParam, &lResult)會返回FALSE,所以會交由預設的訊息處理函數DefWindowProc(message, wParam, lParam)處理,該函數會將該訊息投遞給訊息對應視窗(message.hwnd)的父視窗處理,即對話方塊視窗(當然,對應的message.hwnd變為了對話方塊視窗),這樣對話方塊視窗才有機會處理該訊息而彈出訊息框。
如果在CListCtrl中處理了HDN_BEGINTRACK訊息,則就不會交由對話方塊視窗處理。
為此,我們增加CMyListCtrl,繼承自CListCtrl,在CMyListCtrl中處理HDN_BEGINTRACK訊息。
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)ON_NOTIFY(HDN_BEGINTRACKA, 0, &CMyListCtrl::OnHdnBegintrack)ON_NOTIFY(HDN_BEGINTRACKW, 0, &CMyListCtrl::OnHdnBegintrack)END_MESSAGE_MAP()void CMyListCtrl::OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult){LPNMHEADER phdr = reinterpret_cast(pNMHDR);// TODO: Add your control notification handler code hereAfxMessageBox(TEXT("CMyListCtrl處理了HDN_BEGINTRACK訊息"));*pResult = 0;}
同時將對話方塊中的CListCtrl m_list改為CMyListCtrl m_list。則效果如下:
執行個體代碼:http://download.csdn.net/detail/wangyao1052/4633804