国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
WM_NOTIFY與消息反射—耗費(fèi)我兩天時間才解決的問題
關(guān)于WM_NOTIFY與消息反射—耗費(fèi)我兩天時間才解決的問題
www.firnow.com 時間 : 2010-06-22 作者:佚名 編輯:壹枝雪糕 點(diǎn)擊: 1306 [ 評論 ]
綜合資源電子書社區(qū) 其實(shí),問題很簡單,我想在listctrl響應(yīng)NM_SETFOCUS的同時通知其父窗口(其實(shí)我這句話說錯了,listctrl只能響應(yīng)=NM_SETFOCUS,為什么有個“=”呢?稍后解釋),最幼稚的想法是讓在listctrl和父窗口中都添加對此消息的響應(yīng),很不幸,我在一開始就是這么想的-_-| 。。。很明顯我失敗了!
后來我又發(fā)現(xiàn),如果在listctrl中添加對=NM_SETFOCUS的響應(yīng),父窗口就無法響應(yīng)NM_SETFOCUS,反之就可以響應(yīng)。于是很容易想到在listctrl的消息響應(yīng)中SendMessage給父窗口,控件發(fā)送的消息有兩種:WM_COMMAND和WM_NOTIFY,像button,edit,combobox等控件,主要使用WM_COMMAND消息,而listctrl這類控件主要使用WM_NOTIFY消息,發(fā)送消息時有兩個很重要的參數(shù)wParam和lParam,MSDN說明如下:
lResult = SendMessage( // returns LRESULT in lResult
(HWND) hWndControl, // handle to destination control
(UINT) WM_NOTIFY, // message ID
(WPARAM) wParam, // = (WPARAM) (int) idCtrl;
(LPARAM) lParam // = (LPARAM) (LPNMHDR) pnmh;
);
結(jié)果我還是失敗了!折騰了一天一夜,直到晚上熄燈,我就不信我弄不出來,第二天上CSDN求救,有一個同志的回答提醒了我:消息反射。消息反射是個什么東西,我還是第一次聽到,看來我真是菜鳥。于是查閱了一下消息反射的資料,原來,控件根本無法直接給自己發(fā)送消息,這樣就導(dǎo)致控件無法控制自己,所有的控制必須在父窗口類中實(shí)現(xiàn),這樣不符合面向?qū)ο蟮乃枷耄谑浅霈F(xiàn)了消息反射;即子控件發(fā)送給父窗口的消息被父窗口馬上反射回來,如果子控件響應(yīng)了反射消息,父窗口就不響應(yīng),反之則響應(yīng)。這就和我剛才發(fā)現(xiàn)的現(xiàn)象吻合了。
 那么,消息反射是怎樣實(shí)現(xiàn)的呢?源代碼說明一切!父窗口在接收到子控件的通知消息時調(diào)用虛的消息響應(yīng)函數(shù)CWnd::OnNotify(),代碼如下:
BOOL CWnd::OnNotify(WPARAM, LPARAM lParam, LRESULT* pResult)
{
 ASSERT(pResult != NULL);
 NMHDR* pNMHDR = (NMHDR*)lParam;
 HWND hWndCtrl = pNMHDR->hwndFrom;
 // get the child ID from the window itself
 UINT nID = _AfxGetDlgCtrlID(hWndCtrl);
 int nCode = pNMHDR->code;
 ASSERT(hWndCtrl != NULL);
 ASSERT(::IsWindow(hWndCtrl));
 if (_afxThreadState->m_hLockoutNotifyWindow == m_hWnd)
 return TRUE; // locked out - ignore control notification
 // reflect notification to child window control
 if (ReflectLastMsg(hWndCtrl, pResult))
 return TRUE; // eaten by child
 AFX_NOTIFY notify;
 notify.pResult = pResult;
 notify.pNMHDR = pNMHDR;
 return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY), &notify, NULL);
}
接著看ReflectLastMsg()函數(shù):
BOOL PASCAL CWnd::ReflectLastMsg(HWND hWndChild, LRESULT* pResult)
{
 // get the map, and if no map, then this message does not need reflection
 CHandleMap* pMap = afxMapHWND();
 if (pMap == NULL)
 return FALSE;
 // check if in permanent map, if it is reflect it (could be OLE control)
 CWnd* pWnd = (CWnd*)pMap->LookupPermanent(hWndChild);
 ASSERT(pWnd == NULL || pWnd->m_hWnd == hWndChild);
 if (pWnd == NULL)
 {
#ifndef _AFX_NO_OCC_SUPPORT
 // check if the window is an OLE control
 CWnd* pWndParent = (CWnd*)pMap->LookupPermanent(::GetParent(hWndChild));
 if (pWndParent != NULL && pWndParent->m_pCtrlCont != NULL)
 {
 // If a matching control site exists, it''s an OLE control
 COleControlSite* pSite = (COleControlSite*)pWndParent->
 m_pCtrlCont->m_siteMap.GetValueAt(hWndChild);
 if (pSite != NULL)
 {
 CWnd wndTemp(hWndChild);
 wndTemp.m_pCtrlSite = pSite;
 LRESULT lResult = wndTemp.SendChildNotifyLastMsg(pResult);
 wndTemp.m_hWnd = NULL;
 return lResult;
 }
 }
#endif //!_AFX_NO_OCC_SUPPORT
 return FALSE;
 }
 // only OLE controls and permanent windows will get reflected msgs
 ASSERT(pWnd != NULL);
 return pWnd->SendChildNotifyLastMsg(pResult);
}
注意紅色代碼!此時調(diào)用的是子控件的SendChildNotifyLastMsg() 。繼續(xù)看SendChildNotifyLastMsg():
BOOL CWnd::SendChildNotifyLastMsg(LRESULT* pResult)
{
 _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
 return OnChildNotify(pThreadState->m_lastSentMsg.message,
 pThreadState->m_lastSentMsg.wParam, pThreadState->m_lastSentMsg.lParam, pResult);
}
調(diào)用子控件的虛函數(shù)OnChildNotify函數(shù),進(jìn)行處理。 如果沒有處理,則調(diào)用ReflectChildNotify(...)函數(shù)進(jìn)行標(biāo)準(zhǔn)的反射消息的消息映射處理。 如果在ReflectChildNotify(...)中此消息還沒被處理,就返回到CWnd::OnNotify(...)中調(diào)用OnCmdMsg(...)處理,這樣,父窗口就可以響應(yīng)此消息了。
 下面回到我最初的問題中來,我想在listctrl和父窗口中都處理此消息,因此我們可以重載OnNotify(...)如下:
BOOL CWellListView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
 // TODO: Add your specialized code here and/or call the base class
 ASSERT(pResult != NULL);
 NMHDR* pNMHDR = (NMHDR*)lParam;
 HWND hWndCtrl = pNMHDR->hwndFrom;
 
ReflectLastMsg(hWndCtrl, pResult);
 
UINT nID = _AfxGetDlgCtrlID(hWndCtrl);
 int nCode = pNMHDR->code;
 
AFX_NOTIFY notify;
 notify.pResult = pResult;
 notify.pNMHDR = pNMHDR;
 return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY), &notify, NULL);
 }//CWellListView繼承子CFormView,相當(dāng)與對話框
還要添加兩個頭文件:
#include "AFXPRIV.H"
#include "C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\AFXIMPL.H"
看到它和CWnd::OnNotify(...)的區(qū)別了沒?恩,就是這樣!
 但是,很不幸,我最終沒有采取這種辦法,因?yàn)槲以谝婚_始就沒有想到最佳方案,我完全可以用指針來實(shí)現(xiàn)我的需求,在子控件類中需要的地方添加如下代碼就可以操作父窗口了:
CWellListView* listview=(CWellListView*)GetParent();
 因此,在以后的編程學(xué)習(xí)中,我們應(yīng)該盡量用指針操作來代替發(fā)送消息來實(shí)現(xiàn)我們的需求!
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
深度剖析消息反射機(jī)制
MFC淺析(7) CWnd類虛函數(shù)的調(diào)用時機(jī)、缺省實(shí)現(xiàn)
自定義WM_NOTIFY消息
VC 分割窗口效果
VC實(shí)現(xiàn)窗口的任意分割
MFC 如何添加自定義消息(轉(zhuǎn))
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服