目录
AfxEndDeferRegisterClass 函数,窗口类的注册(wincore.cpp):
PreCreateWindow函数(MainFrm.cpp):
AfxDeferRegisterClass函数(afximpl.h):
接上:VC++MFC程序中的WinMain函数(五)InitInstance函数
接下:MFC框架窗口(二)AfxEndDeferRegisterClass 函数(wincore.cpp)
MFC框架窗口
1.设计和注册窗口
AfxEndDeferRegisterClass 函数,窗口类的注册(wincore.cpp):
BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)
{
...
// common initialization
WNDCLASS wndcls;
memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults
wndcls.lpfnWndProc = DefWindowProc;
wndcls.hInstance = AfxGetInstanceHandle();
wndcls.hCursor = afxData.hcurArrow;
...
// work to register classes as specified by fToRegister, populate fRegisteredClasses as we go
if (fToRegister & AFX_WND_REG)
{
// Child windows - no brush, no icon, safest default class styles
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpszClassName = _afxWnd;
if (AfxRegisterClass(&wndcls))
fRegisteredClasses |= AFX_WND_REG;
}
if (fToRegister & AFX_WNDOLECONTROL_REG)
{
// OLE Control windows - use parent DC for speed
wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpszClassName = _afxWndOleControl;
if (AfxRegisterClass(&wndcls))
fRegisteredClasses |= AFX_WNDOLECONTROL_REG;
}
...
if (fToRegister & AFX_WNDMDIFRAME_REG)
{
// MDI Frame window (also used for splitter window)
wndcls.style = CS_DBLCLKS;
wndcls.hbrBackground = NULL;
if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIFRAME))
fRegisteredClasses |= AFX_WNDMDIFRAME_REG;
}
if (fToRegister & 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);
if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_FRAME))
fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;
}
...
}
连接:MFC框架窗口(二)AfxEndDeferRegisterClass 函数
AfxRegisterClass函数,注册窗口类:
// like RegisterClass, except will automatically call UnregisterClass
// 和RegisterClass一样,except会自动调用UnregisterClass
BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)
{
WNDCLASS wndcls;//获得窗口类信息
if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,
&wndcls))
{
// class already registered
return TRUE;//如果该窗口类已经注册,则直接返回一个真值
}
if (!RegisterClass(lpWndClass))//如果尚未注册,就调用RegisterClass函数注册该窗口类
{
TRACE(traceAppMsg, 0, _T("Can't register window class named %Ts\n"),
lpWndClass->lpszClassName);
return FALSE;
}
BOOL bRet = TRUE;
if (afxContextIsDLL)
{
AfxLockGlobals(CRIT_REGCLASSLIST);
TRY
{
// class registered successfully, add to registered list
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
pModuleState->m_strUnregisterList+=lpWndClass->lpszClassName;
pModuleState->m_strUnregisterList+='\n';
}
CATCH_ALL(e)
{
AfxUnlockGlobals(CRIT_REGCLASSLIST);
THROW_LAST();
// Note: DELETE_EXCEPTION not required.
}
END_CATCH_ALL
AfxUnlockGlobals(CRIT_REGCLASSLIST);
}
return bRet;
}
AfxRegisterClass函数首先获得窗口类信息。如果该窗口类已经注册,则直接返回一个真值;如果尚未注册,就调用RegisterClass函数注册该窗口类。
MFC 应用程序 Test,实际上有两个窗口。其中一个是CMainFrame类(MainFrm.h)的对象所代表的应用程序框架窗口,该类有一个PreCreateWindow函数,这是在窗口产生之前被调用的。该函数的默认实现代码如下所示。
PreCreateWindow函数(MainFrm.cpp):
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return TRUE;
}
该函数首先调用CFrameWnd的PreCreateWindow函数。后者的定义位于源文件winfrm.cpp中,代码下。
/
// CFrameWnd second phase creation
// CFrameWnd第二阶段创建
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background
}
if (cs.style & FWS_ADDTOTITLE)
cs.style |= FWS_PREFIXTITLE;
cs.dwExStyle |= WS_EX_CLIENTEDGE;
return TRUE;
}
该函数中调用了AfxDeferRegisterClass函数,读者可以在afximpl.h文件中找到后者的定义,定义代码如下:
AfxDeferRegisterClass函数(afximpl.h):
#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)