发信人: sodo()
整理人: cobe(1999-12-17 10:27:11), 站内信件
|
先看一下窗口的建立过程:
BOOL CWnd::Create(LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd, UINT nID,
CCreateContext* pContext)
{
// can't use for desktop or pop-up windows (use CreateEx instead)
ASSERT(pParentWnd != NULL);
ASSERT((dwStyle & WS_POPUP) == 0);
return CreateEx(0, lpszClassName, lpszWindowName,
dwStyle | WS_CHILD,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
pParentWnd->GetSafeHwnd(), (HMENU)nID, (LPVOID)pContext);
}
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
{
// allow modification of several common create parameters
CREATESTRUCT cs;
cs.dwExStyle = dwExStyle;
cs.lpszClass = lpszClassName;
cs.lpszName = lpszWindowName;
cs.style = dwStyle;
cs.x = x;
cs.y = y;
cs.cx = nWidth;
cs.cy = nHeight;
cs.hwndParent = hWndParent;
cs.hMenu = nIDorHMenu;
cs.hInstance = AfxGetInstanceHandle();
cs.lpCreateParams = lpParam;
if (!PreCreateWindow(cs))
{
PostNcDestroy();
return FALSE;
}
AfxHookWindowCreate(this);
^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数见后
HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,
cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);
if (!AfxUnhookWindowCreate())
PostNcDestroy(); // cleanup if CreateWindowEx fails too soon
if (hWnd == NULL)
return FALSE;
ASSERT(hWnd == m_hWnd); // should have been set in send msg hook
return TRUE;
}
// for child windows
BOOL CWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
// make sure the default window class is registered
if (!AfxDeferRegisterClass(AFX_WND_REG))
return FALSE;
// no WNDCLASS provided - use child window default
ASSERT(cs.style & WS_CHILD);
cs.lpszClass = _afxWnd;
}
return TRUE;
}
void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
if (pThreadState->m_pWndInit == pWnd)
return;
if (pThreadState->m_hHookOldCbtFilter == NULL)
{
pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,
^^^^^^
Computer-based Training,当建立、删除、移动、最大化、最小化
窗口时,将会调用钩子函数。
_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
^^^^^^^^^^^^^^^^^ 钩子函数
if (pThreadState->m_hHookOldCbtFilter == NULL)
AfxThrowMemoryException();
}
ASSERT(pThreadState->m_hHookOldCbtFilter != NULL);
ASSERT(pWnd != NULL);
ASSERT(pWnd->m_hWnd == NULL); // only do once
ASSERT(pThreadState->m_pWndInit == NULL); // hook not already in progr ess
pThreadState->m_pWndInit = pWnd;
}
BOOL AFXAPI AfxUnhookWindowCreate()
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
#ifndef _AFXDLL
if (afxContextIsDLL && pThreadState->m_hHookOldCbtFilter != NULL)
{
::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
删除钩子函数
pThreadState->m_hHookOldCbtFilter = NULL;
}
#endif
if (pThreadState->m_pWndInit != NULL)
{
pThreadState->m_pWndInit = NULL;
return FALSE; // was not successfully hooked
}
return TRUE;
}
// Window creation hooks
LRESULT CALLBACK
_AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
if (code != HCBT_CREATEWND)
{ ^^^^^^^^^^^^^^^^^^^^^^ 是要建立窗口吗?
// wait for HCBT_CREATEWND just pass others on...
return CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
wParam, lParam);
}
ASSERT(lParam != NULL);
LPCREATESTRUCT lpcs = ((LPCBT_CREATEWND)lParam)->lpcs;
ASSERT(lpcs != NULL);
// this hook exists to set the SendMessage hook on window creations
// (but this is only done for MFC windows or non-child windows)
// the subclassing cannot be done at this point because on Win32s
// the window does not have the WNDPROC set yet
CWnd* pWndInit = pThreadState->m_pWndInit;
if (pWndInit != NULL || (!(lpcs->style & WS_CHILD) && !afxContextIsDLL ))
{
ASSERT(wParam != NULL); // should be non-NULL HWND
HWND hWnd = (HWND)wParam;
WNDPROC oldWndProc;
if (pWndInit != NULL)
{ ^^^^^^^^^^^^^^^^ 窗口建立来自一个CWnd?
// the window should not be in the permanent map at this time
ASSERT(CWnd::FromHandlePermanent(hWnd) == NULL);
// connect the HWND to pWndInit...
pWndInit->Attach(hWnd);
// allow other subclassing to occur first
pWndInit->PreSubclassWindow();
WNDPROC *pOldWndProc = pWndInit->GetSuperWndProcAddr();
ASSERT(pOldWndProc != NULL);
#ifndef _MAC
_AFX_CTL3D_STATE* pCtl3dState;
DWORD dwFlags;
if (!afxData.bWin4 && !afxContextIsDLL &&
(pCtl3dState = _afxCtl3dState.GetDataNA()) != NULL &&
pCtl3dState->m_pfnSubclassDlgEx != NULL &&
(dwFlags = AfxCallWndProc(pWndInit, hWnd, WM_QUERY3DCONTROLS)) != 0)
{
// was the class registered with AfxWndProc?
WNDPROC afxWndProc = AfxGetAfxWndProc();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
函数见后
BOOL bAfxWndProc = ((WNDPROC)
GetWindowLong(hWnd, GWL_WNDPROC) == afxWndProc);
pCtl3dState->m_pfnSubclassDlgEx(hWnd, dwFlags);
// subclass the window if not already wired to AfxWndProc
if (!bAfxWndProc)
{
// subclass the window with standard AfxWndProc
oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
(DWORD)afxWndProc); // 修改窗口的WndProc!!!
ASSERT(oldWndProc != NULL);
*pOldWndProc = oldWndProc;
}
}
else
#endif
{
// subclass the window with standard AfxWndProc
WNDPROC afxWndProc = AfxGetAfxWndProc();
oldWndProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC,
(DWORD)afxWndProc);
ASSERT(oldWndProc != NULL);
if (oldWndProc != afxWndProc)
*pOldWndProc = oldWndProc;
}
pThreadState->m_pWndInit = NULL;
}
else
{
ASSERT(!afxContextIsDLL); // should never get here
// subclass the window with the proc which does gray backgrounds
oldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
if (oldWndProc != NULL)
{
ASSERT(GetProp(hWnd, szAfxOldWndProc) == NULL);
SetProp(hWnd, szAfxOldWndProc, oldWndProc);
if ((WNDPROC)GetProp(hWnd, szAfxOldWndProc) == oldWndProc)
{
SetWindowLong(hWnd, GWL_WNDPROC,
(DWORD)(pThreadState->m_bDlgCreate ?
_AfxGrayBackgroundWndProc : _AfxActivationWndProc));
ASSERT(oldWndProc != NULL);
}
}
}
}
LRESULT lResult = CallNextHookEx(pThreadState->m_hHookOldCbtFilter, co de,
wParam, lParam);
#ifndef _AFXDLL
if (afxContextIsDLL)
{
::UnhookWindowsHookEx(pThreadState->m_hHookOldCbtFilter);
pThreadState->m_hHookOldCbtFilter = NULL;
}
#endif
return lResult;
}
// always indirectly accessed via AfxGetAfxWndProc
WNDPROC AFXAPI AfxGetAfxWndProc()
{
#ifdef _AFXDLL
return AfxGetModuleState()->m_pfnAfxWndProc;
// 如果MFC是动态连入,返回的地址是AfxWndProcBase
#else
return &AfxWndProc; // 否则返回AfxWndProc
#endif
}
// The WndProc for all CWnd's and derived classes
LRESULT CALLBACK
AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
// special message which identifies the window as using AfxWndProc
if (nMsg == WM_QUERYAFXWNDPROC)
^^^^^^^^^^^^^^^^^^ 查询是否为AFX的窗口过程
return 1;
// all other messages route through message map
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FromHandlePermanent函数用于返回一个和hWnd句柄对应的
永久的CWnd类,所谓永久的,就是CWnd调用了Attach函数
连上了一个窗口句柄。
ASSERT(pWnd != NULL);
ASSERT(pWnd->m_hWnd == hWnd);
return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数见后
}
#ifdef _AFXDLL
#undef AfxWndProc
LRESULT CALLBACK
AfxWndProcBase(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
AFX_MANAGE_STATE(_afxBaseModuleState.GetData());
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 由于MFC是动态连入的,所以必须要这条语句!
return AfxWndProc(hWnd, nMsg, wParam, lParam);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
调用MFC静态连入时使用的函数
}
#endif
// 微软官方规定的发送消息给CWnd的函数
LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,
WPARAM wParam = 0, LPARAM lParam = 0)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
MSG oldState = pThreadState->m_lastSentMsg; // save for nesting
pThreadState->m_lastSentMsg.hwnd = hWnd;
pThreadState->m_lastSentMsg.message = nMsg;
pThreadState->m_lastSentMsg.wParam = wParam;
pThreadState->m_lastSentMsg.lParam = lParam;
#ifdef _DEBUG
if (afxTraceFlags & traceWinMsg)
_AfxTraceMsg(_T("WndProc"), &pThreadState->m_lastSentMsg);
#endif
// Catch exceptions thrown outside the scope of a callback
// in debug builds and warn the user.
LRESULT lResult;
TRY
{
#ifndef _AFX_NO_OCC_SUPPORT
// special case for WM_DESTROY
if ((nMsg == WM_DESTROY) && (pWnd->m_pCtrlCont != NULL))
pWnd->m_pCtrlCont->OnUIActivate(NULL);
#endif
// special case for WM_INITDIALOG
CRect rectOld;
DWORD dwStyle;
if (nMsg == WM_INITDIALOG)
_AfxPreInitDialog(pWnd, &rectOld, &dwStyle);
// delegate to object's WindowProc
lResult = pWnd->WindowProc(nMsg, wParam, lParam);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
调用CWnd类的WindowProc函数,函数见后
// more special case for WM_INITDIALOG
if (nMsg == WM_INITDIALOG)
_AfxPostInitDialog(pWnd, rectOld, dwStyle);
}
CATCH_ALL(e)
{
lResult = AfxGetThread()->ProcessWndProcException(e, &pThreadState->m_ lastSentMsg);
TRACE1("Warning: Uncaught exception in WindowProc (returning %ld).\n",
lResult);
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
pThreadState->m_lastSentMsg = oldState;
return lResult;
}
-- 十年磨一剑,霜寒未曾试;
今日拔剑问,谁有不平事?
----老猫
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.47.234]
|
|