打怪升级之CFrameWnd类

文章详细解析了CFrameWnd类在MFC中的作用,特别是窗口的创建过程,包括CFrameWnd的Create函数和CWnd的Create函数。通过源码分析,阐述了窗口类的构造及重要函数,并强调了在不同窗口类型(如frame类和dialog类)中CWnd子类的应用。同时,指出了在创建窗口时需要注意的参数如lpszClassName,lpszWindowName和dwStyle等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

按惯例,这一篇文章主要还是作者读《深入浅出MFC》整理的一些笔记。

CFrameWnd产生、注册窗口

CFrameWnd类作为最常用的窗口类,其定义在“…\VS\IDE\VC\Tools\MSVC\14.34.31933\atlmfc\src\mfc\winfrm.cpp”中。

这里说一些我个人的看法,为什么通过头文件总会绕的云里雾里,就比如说这个CMyWinApp类,内部各函数、各变量,最终都会由头文件统一汇总的,以至于从头文件的角度看CMyWinApp足足由5000行代码之多,代码量达到一篇文献的水平,读懂它就会变得很困难。看山看不全,那么我们就只好沿一条上山的路,看一路的风景,而最简单最基础的一路,就是被MFC所雪藏的winmain函数这一路径(参考之前的博客)。

BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
	LPCTSTR lpszWindowName,
	DWORD dwStyle,
	const RECT& rect,
	CWnd* pParentWnd,
	LPCTSTR lpszMenuName,
	DWORD dwExStyle,
	CCreateContext* pContext)
{
	HMENU hMenu = NULL;
	if (lpszMenuName != NULL)
	{
		// load in a menu that will get destroyed when window gets destroyed
		HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, ATL_RT_MENU);
		if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)
		{
			TRACE(traceAppMsg, 0, "Warning: failed to load menu for CFrameWnd.\n");
			PostNcDestroy();            // perhaps delete the C++ object
			return FALSE;
		}
	}

	m_strTitle = lpszWindowName;    // save title for later

	if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
		rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
		pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))
	{
		TRACE(traceAppMsg, 0, "Warning: failed to create CFrameWnd.\n");
		if (hMenu != NULL)
			DestroyMenu(hMenu);
		return FALSE;
	}

	return TRUE;
}

类的构造函数,类的一些重要函数,都在这个文件之中。如果你在新版本的VS中使用的是dialog对话框作为你的起始窗口的话,那么久不是frame类了,不论是frame类还是dialog类,都是CWnd的子类,我们可以观察CWnd的内容:“wincore.cpp”。这里我们重点就说标准构造函数:

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

	if (((dwStyle & WS_TABSTOP) == WS_TABSTOP) && (nID == 0))
	{
		// Warn about nID == 0.  A zero ID will be overridden in CWnd::PreCreateWindow when the
		// check is done for (cs.hMenu == NULL).  This will cause the dialog control ID to be
		// different than passed in, so ::GetDlgItem(nID) will not return the control HWND.
		TRACE(traceAppMsg, 0, _T("Warning: creating a dialog control with nID == 0; ")
			_T("nID will overridden in CWnd::PreCreateWindow and GetDlgItem with nID == 0 will fail.\n"));
	}

	// About nID: In x64 HMENU is 64 bits while UINT is 32 bits (unfortunately).
	// HMENU only actually uses 32 bits, sign extended to 64 bits.
	// Those bits are getting dropped in UINT, so sign extend here to restore them.
	return CreateEx(0, lpszClassName, lpszWindowName,
		dwStyle | WS_CHILD,
		rect.left, rect.top,
		rect.right - rect.left, rect.bottom - rect.top,
		pParentWnd->GetSafeHwnd(), reinterpret_cast<HMENU>(static_cast<INT_PTR>(nID)), (LPVOID)pContext);
}
}

这是原文的标准构造函数,不论你创立的是何种类型的窗口,都应该走上面这段代码。CWnd的具体内容在文档

lpszClassName:指向以 null 结尾的字符串的指针,该字符串包含已注册的系统窗口类的名称;或者为预定义的系统窗口类的名称。

lpszWindowName:指向以 null 结尾的字符串的指针,该字符串包含窗口显示名称;否则为 NULL,表示没有窗口显示名称。

dwStyle:窗口样式的按位组合 (OR)。 WS_POPUP 选项不是有效样式。

rect:窗口相对于父窗口左上角的大小和位置。

pParentWnd:指向父窗口的指针。

nID:窗口的 ID。

pContext:指向 CCreateContext 结构的指针,该结构用于自定义应用程序的文档视图体系结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

考琪

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值