VC++MFC框架窗口(一)AfxEndDeferRegisterClass AfxRegisterClass PreCreateWindow AfxDeferRegisterClass

目录

MFC框架窗口

1.设计和注册窗口

AfxEndDeferRegisterClass 函数,窗口类的注册(wincore.cpp):

AfxRegisterClass函数,注册窗口类:

PreCreateWindow函数(MainFrm.cpp):

AfxDeferRegisterClass函数(afximpl.h):

接上:VC++MFC程序中的WinMain函数(五)InitInstance函数

接下:MFC框架窗口(二)AfxEndDeferRegisterClass 函数(wincore.cpp)


MFC框架窗口

1.设计和注册窗口

有了 WinMain 函数,根据创建 Win32应用程序的步骤,接下来设计窗口类注册窗口类。MFC已经为我们预定义了一些默认的标准窗口类,只需要选择所需的窗口类,然后注册就可以了。窗口类的注册是由 AfxEndDeferRegisterClass 函数完成的,该函数的定义位于 wincore.cpp 文件中,如下。

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 函数

从以上代码可知,AfxEndDeferRegisterClass函数首先判断窗口类的类型,然后赋予其相应的类名(wndcls.lpszClassName变量),这些类名都是MFC预定义的。之后调用AfxRegisterClass函数注册窗口类,后者的定义也位于wincore.cpp 文件中,代码如下。

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函数注册该窗口类。

小技巧: 如果在当前文件中查找某个函数或字符串,那么可以使用“Ctrl+F”快捷键。

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;
}

该函数首先调用CFrameWndPreCreateWindow函数。后者的定义位于源文件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)

AfxDeferRegisterClass 实际上是一个宏,真正指向的是AfxEndDeferRegisterClass函数。这里完成的功能就是注册窗口类。在CMainFrame类PreCreateWindow函数处设置一个断点,调试运行Test程序,将会发现程序在调用theApp全局对象和WinMain函数之后,到达此函数处。由此知道MFC程序执行的脉络也是在WinMain函数之后、窗口产生之前注册窗口类的。

接上:VC++MFC程序中的WinMain函数(五)InitInstance函数

接下:MFC框架窗口(二)AfxEndDeferRegisterClass 函数(wincore.cpp)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

米酒馆

鼓励鼓励,鼓励很重要啦~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值