////////////////////////////////////////////////////////////////
// AfxEndDeferRegisterClass -- This is where MFC registers
// various window classes for views, frames, control bars, and
// so on. This is NOT where MFC sets the window proc to AfxWndProc.
// Here, MFC sets the window proc to the Windows default proc,
// DefWindowProc.
//
// -PD
//
BOOL AFXAPI AfxEndDeferRegisterClass(short fClass)
{
BOOL bResult = FALSE;
// common initialization
WNDCLASS wndcls;
memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults
wndcls.lpfnWndProc = DefWindowProc; // <<*** default window proc
wndcls.hInstance = AfxGetInstanceHandle();
wndcls.hCursor = afxData.hcurArrow;
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
if (fClass & AFX_WND_REG)
{
// Child windows - no brush, no icon, safest default class styles
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpszClassName = _afxWnd;
bResult = AfxRegisterClass(&wndcls);
if (bResult)
pModuleState->m_fRegisteredClasses |= AFX_WND_REG;
}
else if (fClass & AFX_WNDOLECONTROL_REG)
{
// OLE Control windows - use parent DC for speed
wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpszClassName = _afxWndOleControl;
bResult = AfxRegisterClass(&wndcls);
if (bResult)
pModuleState->m_fRegisteredClasses |= AFX_WNDOLECONTROL_REG;
}
else if (fClass & AFX_WNDCONTROLBAR_REG)
{
// Control bar windows
wndcls.style = 0; // control bars don't handle double click
wndcls.lpszClassName = _afxWndControlBar;
wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
bResult = AfxRegisterClass(&wndcls);
if (bResult)
pModuleState->m_fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;
}
else if (fClass & AFX_WNDMDIFRAME_REG)
{
// MDI Frame window (also used for splitter window)
wndcls.style = CS_DBLCLKS;
wndcls.hbrBackground = NULL;
bResult = RegisterWithIcon(&wndcls, _afxWndMDIFrame,
AFX_IDI_STD_MDIFRAME);
if (bResult)
pModuleState->m_fRegisteredClasses |= AFX_WNDMDIFRAME_REG;
}
else if (fClass & AFX_WNDFRAMEORVIEW_REG)
{
// SDI Frame or MDI Child windows or views - normal colors
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
bResult = RegisterWithIcon(&wndcls, _afxWndFrameOrView,
AFX_IDI_STD_FRAME);
if (bResult)
pModuleState->m_fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
}
else if (fClass & AFX_WNDCOMMCTLS_REG)
{
InitCommonControls();
bResult = TRUE;
pModuleState->m_fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;
}
return bResult;
}
Figure 2
MFC Signature Codes
////////////////////////////////////////////////////////////////
// MFC signature codes, from afxmsg_.h.
//
enum AfxSig
{
AfxSig_end = 0, // [marks end of message map]
AfxSig_bD, // BOOL (CDC*)
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)
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 TRUE
AfxSig_vW2, // void (CWnd*) (CWnd* comes from lParam)
AfxSig_bWCDS, // BOOL (CWnd*, COPYDATASTRUCT*)
AfxSig_bwsp, // BOOL (UINT, short, CPoint)
AfxSig_vws,
};
Figure 3
AfxHookWindowCreate
/////////////////////////////////////////////////////////////////
// MFC generic window creation hook function.
// Comments are mine--Paul DiLascia
//
void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
{
// MFC sets a thread-global m_pWndInit, which points
// to the window being created. This is the only way
// CWnd::CreateEx and AfxHookWindowCreate can communicate
// with the hook function, SetWindowsHookEx does not let
// you pass an argument for the hook function.
//
_AFX_THREAD_STATE* pThreadState =
_afxThreadState.GetData();
// If this window is already hooked for creation, ignore.
// In theory, this should not happen.
if (pThreadState->m_pWndInit == pWnd)
return;
if (pThreadState->m_hHookOldCbtFilter == NULL) {
// Create the hook:
pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,
_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
if (pThreadState->m_hHookOldCbtFilter == NULL)
AfxThrowMemoryException();
}
// Below are sanity checks
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 progress
pThreadState->m_pWndInit = pWnd; // set the m_pWndInit global !!
}
Figure 4
_AfxCbtFilterHook
// simplified (!)
LRESULT _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
if (code != HCBT_CREATEWND)
// ignore
// subclass the window with AfxWndProc
CWnd* pWndInit = pThreadState->m_pWndInit;
pWndInit->Attach((HWND)wParam);
pWndInit->PreSubclassWindow(); // virtual
WNDPROC *pOldWndProc = pWndInit->GetSuperWndProcAddr();
ASSERT(pOldWndProc != NULL);
WNDPROC afxWndProc = AfxGetAfxWndProc();
oldWndProc = (WNDPROC)SetWindowLong(hWnd,
GWL_WNDPROC, (DWORD)afxWndProc);
if (oldWndProc != afxWndProc)
*pOldWndProc = oldWndProc;
pThreadState->m_pWndInit = NULL;
return lResult;
}