发信人: sodo()
整理人: cobe(1999-12-17 10:27:41), 站内信件
|
消息处理转入CWnd类了,
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);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如果没有处理,就调用DefWindowProc,
呵呵,和我们以前用C写Windows程序一样!!
return lResult;
}
BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESUL T* pResult)
{
LRESULT lResult = 0;
// special case for commands
if (message == WM_COMMAND)
{ ^^^^^^^^^^ WM_COMMAND消息?
if (OnCommand(wParam, lParam))
{ ^^^^^^^^^^^^^^^^^^^^^^^^^
调用OnCommand函数,这是一个虚函数
lResult = 1;
goto LReturnTrue;
}
return FALSE;
}
// special case for notifies
if (message == WM_NOTIFY)
{ ^^^^^^^^^ 通告消息?
NMHDR* pNMHDR = (NMHDR*)lParam;
if (pNMHDR->hwndFrom != NULL &&
OnNotify(wParam, lParam, &lResult))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
调用OnNotify函数,也是一个虚函数
goto LReturnTrue;
return FALSE;
}
// special case for activation
if (message == WM_ACTIVATE)
_AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));
// special case for set cursor HTERROR
if (message == WM_SETCURSOR &&
_AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
{
lResult = 1;
goto LReturnTrue;
}
const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
GetMessageMap返回当前类的消息映射表
UINT iHash; iHash = (LOWORD((DWORD)pMessageMap) ^ message) & (iHashMax -1);
AfxLockGlobals(CRIT_WINMSGCACHE);
AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
为了查找消息更快,微软实现了一个消息cache!
const AFX_MSGMAP_ENTRY* lpEntry;
if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMa p)
{
// 消息在cache里,命中
lpEntry = pMsgCache->lpEntry;
AfxUnlockGlobals(CRIT_WINMSGCACHE);
if (lpEntry == NULL)
return FALSE;
// cache hit, and it needs to be handled
if (message < 0xC000)
goto LDispatch;
else
goto LDispatchRegistered;
}
else
{
// 不在cache里面,只好查找整个消息映射表
pMsgCache->nMsg = message;
pMsgCache->pMessageMap = pMessageMap;
#ifdef _AFXDLL
for (/* pMessageMap already init'ed */; pMessageMap != NULL;
pMessageMap = (*pMessageMap->pfnGetBaseMap)())
#else
for (/* pMessageMap already init'ed */; pMessageMap != NULL;
pMessageMap = pMessageMap->pBaseMap)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
从最高层类一层一层往下找
#endif
{
// Note: catch not so common but fatal mistake!!
// BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)
#ifdef _AFXDLL
ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
#else
ASSERT(pMessageMap != pMessageMap->pBaseMap);
#endif
if (message < 0xC000)
{
// constant window message
if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
这是一个汇编写的查找消息处理入口的函数
message, 0, 0)) != NULL)
{
pMsgCache->lpEntry = lpEntry;
AfxUnlockGlobals(CRIT_WINMSGCACHE);
goto LDispatch;
}
}
else
{
// registered windows message
lpEntry = pMessageMap->lpEntries;
while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
{
UINT* pnID = (UINT*)(lpEntry->nSig);
ASSERT(*pnID >= 0xC000 || *pnID == 0);
// must be successfully registered
if (*pnID == message)
{
pMsgCache->lpEntry = lpEntry;
AfxUnlockGlobals(CRIT_WINMSGCACHE);
goto LDispatchRegistered;
}
lpEntry++; // keep looking past this one
}
}
}
pMsgCache->lpEntry = NULL;
AfxUnlockGlobals(CRIT_WINMSGCACHE);
return FALSE;
}
ASSERT(FALSE); // not reached
LDispatch: //消息处理函数找到了就转到此处了
ASSERT(message < 0xC000);
union MessageMapFunctions mmf;
mmf.pfn = lpEntry->pfn;
// if we've got WM_SETTINGCHANGE / WM_WININICHANGE, we need to
// decide if we're going to call OnWinIniChange() or OnSettingChange()
int nSig;
nSig = lpEntry->nSig;
^^^^^^^^^^^^^^^^^^^^
if (lpEntry->nID == WM_SETTINGCHANGE)
{
DWORD dwVersion = GetVersion();
if (LOBYTE(LOWORD(dwVersion)) >= 4)
nSig = AfxSig_vws;
else
nSig = AfxSig_vs;
}
switch (nSig)
{// nSig为消息参数类型,详细解释见后
default:
ASSERT(FALSE);
break;
case AfxSig_bD:
lResult = (this->*mmf.pfn_bD)(CDC::FromHandle((HDC)wParam));
^^^ mmf就是我们在Message Map里面设的消息处理函数
它是一个共用体(union),其中定义了
带有各种不同参数形式的函数。
break;
case AfxSig_bb: // AfxSig_bb, AfxSig_bw, AfxSig_bh
lResult = (this->*mmf.pfn_bb)((BOOL)wParam);
break;
case AfxSig_bWww: // really AfxSig_bWiw
lResult = (this->*mmf.pfn_bWww)(CWnd::FromHandle((HWND)wParam),
(short)LOWORD(lParam), HIWORD(lParam));
break;
case AfxSig_bWCDS:
lResult = (this->*mmf.pfn_bWCDS)(CWnd::FromHandle((HWND)lParam),
(COPYDATASTRUCT*) lParam);
break;
case AfxSig_bHELPINFO:
lResult = (this->*mmf.pfn_bHELPINFO)((HELPINFO*)lParam);
break;
case AfxSig_hDWw:
{
// special case for OnCtlColor to avoid too many temporary objects
ASSERT(message == WM_CTLCOLOR);
AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
CWnd wndTemp; wndTemp.m_hWnd = pCtl->hWnd;
UINT nCtlType = pCtl->nCtlType;
// if not coming from a permanent window, use stack temporary
CWnd* pWnd = CWnd::FromHandlePermanent(wndTemp.m_hWnd);
if (pWnd == NULL)
{
#ifndef _AFX_NO_OCC_SUPPORT
// determine the site of the OLE control if it is one
COleControlSite* pSite;
if (m_pCtrlCont != NULL && (pSite = (COleControlSite*)
m_pCtrlCont->m_siteMap.GetValueAt(wndTemp.m_hWnd)) != NULL)
{
wndTemp.m_pCtrlSite = pSite;
}
#endif
pWnd = &wndTemp;
}
HBRUSH hbr = (this->*mmf.pfn_hDWw)(&dcTemp, pWnd, nCtlType);
// fast detach of temporary objects
dcTemp.m_hDC = NULL;
wndTemp.m_hWnd = NULL;
lResult = (LRESULT)hbr;
}
break;
case AfxSig_hDw:
{
// special case for CtlColor to avoid too many temporary objects
ASSERT(message == WM_REFLECT_BASE+WM_CTLCOLOR);
AFX_CTLCOLOR* pCtl = (AFX_CTLCOLOR*)lParam;
CDC dcTemp; dcTemp.m_hDC = pCtl->hDC;
UINT nCtlType = pCtl->nCtlType;
HBRUSH hbr = (this->*mmf.pfn_hDw)(&dcTemp, nCtlType);
// fast detach of temporary objects
dcTemp.m_hDC = NULL;
lResult = (LRESULT)hbr;
}
break;
case AfxSig_iwWw:
lResult = (this->*mmf.pfn_iwWw)(LOWORD(wParam),
CWnd::FromHandle((HWND)lParam), HIWORD(wParam));
break;
case AfxSig_iww:
lResult = (this->*mmf.pfn_iww)(LOWORD(wParam), HIWORD(wParam));
break;
case AfxSig_iWww: // really AfxSig_iWiw
lResult = (this->*mmf.pfn_iWww)(CWnd::FromHandle((HWND)wParam),
(short)LOWORD(lParam), HIWORD(lParam));
break;
case AfxSig_is:
lResult = (this->*mmf.pfn_is)((LPTSTR)lParam);
break;
case AfxSig_lwl:
lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
break;
case AfxSig_lwwM:
lResult = (this->*mmf.pfn_lwwM)((UINT)LOWORD(wParam),
(UINT)HIWORD(wParam), (CMenu*)CMenu::FromHandle((HMENU)lParam));
break;
case AfxSig_vv:
(this->*mmf.pfn_vv)();
break;
case AfxSig_vw: // AfxSig_vb, AfxSig_vh
(this->*mmf.pfn_vw)(wParam);
break;
case AfxSig_vww:
(this->*mmf.pfn_vww)((UINT)wParam, (UINT)lParam);
break;
case AfxSig_vvii:
(this->*mmf.pfn_vvii)((short)LOWORD(lParam), (short)HIWORD(lParam));
break;
case AfxSig_vwww:
(this->*mmf.pfn_vwww)(wParam, LOWORD(lParam), HIWORD(lParam));
break;
case AfxSig_vwii:
(this->*mmf.pfn_vwii)(wParam, LOWORD(lParam), HIWORD(lParam));
break;
case AfxSig_vwl:
(this->*mmf.pfn_vwl)(wParam, lParam);
break;
case AfxSig_vbWW:
(this->*mmf.pfn_vbWW)(m_hWnd == (HWND)lParam,
CWnd::FromHandle((HWND)lParam),
CWnd::FromHandle((HWND)wParam));
break;
case AfxSig_vD:
(this->*mmf.pfn_vD)(CDC::FromHandle((HDC)wParam));
break;
case AfxSig_vM:
(this->*mmf.pfn_vM)(CMenu::FromHandle((HMENU)wParam));
break;
case AfxSig_vMwb:
(this->*mmf.pfn_vMwb)(CMenu::FromHandle((HMENU)wParam),
LOWORD(lParam), (BOOL)HIWORD(lParam));
break;
case AfxSig_vW:
(this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)wParam));
break;
case AfxSig_vW2:
(this->*mmf.pfn_vW)(CWnd::FromHandle((HWND)lParam));
break;
case AfxSig_vWww:
(this->*mmf.pfn_vWww)(CWnd::FromHandle((HWND)wParam), LOWORD(lParam),
HIWORD(lParam));
break;
case AfxSig_vWp:
{
CPoint point((DWORD)lParam);
(this->*mmf.pfn_vWp)(CWnd::FromHandle((HWND)wParam), point);
}
break;
case AfxSig_vWh:
(this->*mmf.pfn_vWh)(CWnd::FromHandle((HWND)wParam),
(HANDLE)lParam);
break;
case AfxSig_vwW:
(this->*mmf.pfn_vwW)(wParam, CWnd::FromHandle((HWND)lParam));
break;
case AfxSig_vwWb:
(this->*mmf.pfn_vwWb)((UINT)(LOWORD(wParam)),
CWnd::FromHandle((HWND)lParam), (BOOL)HIWORD(wParam));
break;
case AfxSig_vwwW:
case AfxSig_vwwx:
{
// special case for WM_VSCROLL and WM_HSCROLL
ASSERT(message == WM_VSCROLL || message == WM_HSCROLL ||
message == WM_VSCROLL+WM_REFLECT_BASE || message == WM_HSCROLL+WM_REFL ECT_BASE);
int nScrollCode = (short)LOWORD(wParam);
int nPos = (short)HIWORD(wParam);
if (lpEntry->nSig == AfxSig_vwwW)
(this->*mmf.pfn_vwwW)(nScrollCode, nPos,
CWnd::FromHandle((HWND)lParam));
else
(this->*mmf.pfn_vwwx)(nScrollCode, nPos);
}
break;
case AfxSig_vs:
(this->*mmf.pfn_vs)((LPTSTR)lParam);
break;
case AfxSig_vws:
(this->*mmf.pfn_vws)((UINT) wParam, (LPCTSTR)lParam);
break;
case AfxSig_vOWNER:
(this->*mmf.pfn_vOWNER)((int)wParam, (LPTSTR)lParam);
lResult = TRUE;
break;
case AfxSig_iis:
lResult = (this->*mmf.pfn_iis)((int)wParam, (LPTSTR)lParam);
break;
case AfxSig_wp:
{
CPoint point((DWORD)lParam);
lResult = (this->*mmf.pfn_wp)(point);
}
break;
case AfxSig_wv: // AfxSig_bv, AfxSig_wv
lResult = (this->*mmf.pfn_wv)();
break;
case AfxSig_vCALC:
(this->*mmf.pfn_vCALC)((BOOL)wParam, (NCCALCSIZE_PARAMS*)lParam);
break;
case AfxSig_vPOS:
(this->*mmf.pfn_vPOS)((WINDOWPOS*)lParam);
break;
case AfxSig_vwwh:
(this->*mmf.pfn_vwwh)(LOWORD(wParam), HIWORD(wParam), (HANDLE)lParam);
break;
case AfxSig_vwp:
{
CPoint point((DWORD)lParam);
(this->*mmf.pfn_vwp)(wParam, point);
break;
}
case AfxSig_vwSIZING:
(this->*mmf.pfn_vwl)(wParam, lParam);
lResult = TRUE;
break;
case AfxSig_bwsp:
lResult = (this->*mmf.pfn_bwsp)(LOWORD(wParam), (short) HIWORD(wParam) ,
CPoint(LOWORD(lParam), HIWORD(lParam)));
if (!lResult)
return FALSE;
}
goto LReturnTrue;
LDispatchRegistered: // for registered windows messages
ASSERT(message >= 0xC000);
mmf.pfn = lpEntry->pfn;
lResult = (this->*mmf.pfn_lwl)(wParam, lParam);
LReturnTrue:
if (pResult != NULL)
*pResult = lResult;
return TRUE;
}
LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
if (m_pfnSuper != NULL)
return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam);
WNDPROC pfnWndProc;
if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL)
return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam);
else
return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam);
}
enum AfxSig // 消息处理函数的参数类型
{
AfxSig_end = 0, // [marks end of message map]
AfxSig_bD, // BOOL (CDC*)
^^
|+--------------- D表示CDC*
+---------------- b表示返回值为bool型
AfxSig_bb, // BOOL (BOOL)
AfxSig_bWww, // BOOL (CWnd*, UINT, UINT)
AfxSig_hDWw, // HBRUSH (CDC*, CWnd*, UINT)
AfxSig_hDw, // HBRUSH (CDC*, UINT)
AfxSig_iwWw, // int (UINT, CWnd*, UINT)
AfxSig_iww, // int (UINT, UINT)
AfxSig_iWww, // int (CWnd*, UINT, UINT)
AfxSig_is, // int (LPTSTR)
AfxSig_lwl, // LRESULT (WPARAM, LPARAM)
AfxSig_lwwM, // LRESULT (UINT, UINT, CMenu*)
AfxSig_vv, // void (void)
^^^^^^^^^ 举个例子,如WM_PAINT消息,
在BEGIN_MESSAGE_MAP里面我们定义的消息处理函数为
ON_WM_PAINT()
察看我们前面剖析过程,知道
#define ON_WM_PAINT() \
{ WM_PAINT, 0, 0, 0, AfxSig_vv, \
所以处理函数的形式即为
OnPaint()
即没有参数,没有返回值。
采用这种方法,就可以避免把没用的wParam和lParam参数传给用户
AfxSig_vw, // void (UINT)
AfxSig_vww, // void (UINT, UINT)
AfxSig_vvii, // void (int, int) // wParam is ignored
AfxSig_vwww, // void (UINT, UINT, UINT)
AfxSig_vwii, // void (UINT, int, int)
AfxSig_vwl, // void (UINT, LPARAM)
AfxSig_vbWW, // void (BOOL, CWnd*, CWnd*)
AfxSig_vD, // void (CDC*)
AfxSig_vM, // void (CMenu*)
AfxSig_vMwb, // void (CMenu*, UINT, BOOL)
AfxSig_vW, // void (CWnd*)
AfxSig_vWww, // void (CWnd*, UINT, UINT)
AfxSig_vWp, // void (CWnd*, CPoint)
AfxSig_vWh, // void (CWnd*, HANDLE)
AfxSig_vwW, // void (UINT, CWnd*)
AfxSig_vwWb, // void (UINT, CWnd*, BOOL)
AfxSig_vwwW, // void (UINT, UINT, CWnd*)
AfxSig_vwwx, // void (UINT, UINT)
AfxSig_vs, // void (LPTSTR)
AfxSig_vOWNER, // void (int, LPTSTR), force return TRUE
AfxSig_iis, // int (int, LPTSTR)
AfxSig_wp, // UINT (CPoint)
AfxSig_wv, // UINT (void)
AfxSig_vPOS, // void (WINDOWPOS*)
AfxSig_vCALC, // void (BOOL, NCCALCSIZE_PARAMS*)
AfxSig_vNMHDRpl, // void (NMHDR*, LRESULT*)
AfxSig_bNMHDRpl, // BOOL (NMHDR*, LRESULT*)
AfxSig_vwNMHDRpl, // void (UINT, NMHDR*, LRESULT*)
AfxSig_bwNMHDRpl, // BOOL (UINT, NMHDR*, LRESULT*)
AfxSig_bHELPINFO, // BOOL (HELPINFO*)
AfxSig_vwSIZING, // void (UINT, LPRECT) -- return TRUE
// signatures specific to CCmdTarget
AfxSig_cmdui, // void (CCmdUI*)
AfxSig_cmduiw, // void (CCmdUI*, UINT)
AfxSig_vpv, // void (void*)
AfxSig_bpv, // BOOL (void*)
// Other aliases (based on implementation)
AfxSig_vwwh, // void (UINT, UINT, HANDLE)
AfxSig_vwp, // void (UINT, CPoint)
AfxSig_bw = AfxSig_bb, // BOOL (UINT)
AfxSig_bh = AfxSig_bb, // BOOL (HANDLE)
AfxSig_iw = AfxSig_bb, // int (UINT)
AfxSig_ww = AfxSig_bb, // UINT (UINT)
AfxSig_bv = AfxSig_wv, // BOOL (void)
AfxSig_hv = AfxSig_wv, // HANDLE (void)
AfxSig_vb = AfxSig_vw, // void (BOOL)
AfxSig_vbh = AfxSig_vww, // void (BOOL, HANDLE)
AfxSig_vbw = AfxSig_vww, // void (BOOL, UINT)
AfxSig_vhh = AfxSig_vww, // void (HANDLE, HANDLE)
AfxSig_vh = AfxSig_vw, // void (HANDLE)
AfxSig_viSS = AfxSig_vwl, // void (int, STYLESTRUCT*)
AfxSig_bwl = AfxSig_lwl,
AfxSig_vwMOVING = AfxSig_vwSIZING, // void (UINT, LPRECT) -- return TR UE
AfxSig_vW2, // void (CWnd*) (CWnd* comes from lParam)
AfxSig_bWCDS, // BOOL (CWnd*, COPYDATASTRUCT*)
AfxSig_bwsp, // BOOL (UINT, short, CPoint)
AfxSig_vws,
};
*** Finished ***
-- 十年磨一剑,霜寒未曾试;
今日拔剑问,谁有不平事?
----老猫
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.47.234]
|
|