打怪升级之CWnd类构建函数与注册函数

文章详细介绍了CWnd类的两个构造函数,包括默认构造和接受HWND参数的构造,并指出CWnd作为一个基础窗口类,通常需要额外参数来实例化。此外,还讨论了CDialog类的构造及其创建过程,强调了窗口在使用前需要在操作系统中注册。文章提供了Windows文档和VS库的源代码路径,帮助读者深入学习MFC类库。
摘要由CSDN通过智能技术生成

按惯例,这一篇文章主要还是作者读《深入浅出MFC》整理的一些笔记。除此之外,你还可以在Windows文档或者在你的VS库中找到对应的源代码来读一读。Windows文档主要为:https://learn.microsoft.com/zh-cn/cpp/mfc/reference/mfc-classes?view=msvc-160。VS库路径主要为(如果你是找MFC的话)“…\VS\IDE\VC\Tools\MSVC\14.34.31933\atlmfc\src\mfc”。

CWnd构造函数

如上面所说,你应该在“…\VS\IDE\VC\Tools\MSVC\14.34.31933\atlmfc\src\mfc”里搜索CWnd的构造函数,这很简单,一般类的构造函数就是类名本身,所以你只需要在src文件夹中批量搜索以下关键字就行:“CWnd::CWnd”,具体搜索方法可以用notepad++。下面是找到的在路径\wincore.cpp中描述的CWnd构造函数

CWnd::CWnd() : CWnd(NULL)
{
}

CWnd::CWnd(HWND hWnd)
{
	m_hWnd = hWnd;
	m_pStdObject = NULL;
	m_bEnableActiveAccessibility = false;
	m_bIsTouchWindowRegistered = FALSE;
	m_pProxy = NULL;
	m_hWndOwner = NULL;
	m_nFlags = 0;
	m_pfnSuper = NULL;
	m_nModalResult = 0;
	m_pDropTarget = NULL;
	m_pCtrlCont = NULL;
	m_pCtrlSite = NULL;
	m_pMFCCtrlContainer = NULL;

	m_ptGestureFrom = CPoint(-1, -1);
	m_ulGestureArg = 0;
	m_bGestureInited = FALSE;
	m_pCurrentGestureInfo = NULL;
	m_pRenderTarget = NULL;
	m_pDynamicLayout = NULL;
}

意料之外情理之中吧,本身CWnd就是一个很虚的类,想从这里捏造一个实际用的东西还有很多参数要填充,下面那个HWND意思是,如果你new一个CWnd这么写:

CWnd Cw;//会自动执行CWnd()函数
CWnd Cw(HWND hWnd);//会自动执行CWnd(HWND hWnd)函数

CWnd子类主要分为四种:Frame(框架)、Dialog(对话框)、View(视图)、Control(控件)。

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);
}
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
		LPCTSTR lpszWindowName, DWORD dwStyle,
		const RECT& rect, CWnd* pParentWnd, UINT nID,
		LPVOID lpParam /* = NULL */)
{
	// 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(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
		rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
		pParentWnd->GetSafeHwnd(), reinterpret_cast<HMENU>(static_cast<INT_PTR>(nID)), lpParam);
}
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)
{
	ASSERT(lpszClassName == NULL || AfxIsValidString(lpszClassName) ||
		AfxIsValidAtom(lpszClassName));
	ENSURE_ARG(lpszWindowName == NULL || AfxIsValidString(lpszWindowName));

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

#ifdef _DEBUG
	if (hWnd == NULL)
	{
		TRACE(traceAppMsg, 0, "Warning: Window creation failed: GetLastError returns 0x%8.8X\n",
			GetLastError());
	}
#endif

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

CDialog构造函数

在“…\VS\IDE\VC\Tools\MSVC\14.34.31933\atlmfc\src\mfc”里可以找到CWnd的一个常见子类CDialog

CDialog::CDialog()
{
	ASSERT(m_hWnd == NULL);

	Initialize();
}
void CDialog::Initialize()
{
	m_nIDHelp = 0;
	m_lpszTemplateName = NULL;
	m_hDialogTemplate = NULL;
	m_lpDialogTemplate = NULL;
	m_lpDialogInit = NULL;
	m_pParentWnd = NULL;
	m_hWndTop = NULL;
	m_pOccDialogInfo = NULL;
	m_bClosedByEndDialog = FALSE;
}
BOOL CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
{
	ASSERT(IS_INTRESOURCE(lpszTemplateName) ||
		AfxIsValidString(lpszTemplateName));

	m_lpszTemplateName = lpszTemplateName;  // used for help
	if (IS_INTRESOURCE(m_lpszTemplateName) && m_nIDHelp == 0)
		m_nIDHelp = LOWORD((DWORD_PTR)m_lpszTemplateName);

#ifdef _DEBUG
	if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE))
	{
		ASSERT(FALSE);          // invalid dialog template name
		PostNcDestroy();        // cleanup if Create fails too soon
		return FALSE;
	}
#endif //_DEBUG

	HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);
	HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG);
	if(hResource == NULL)
	{
		return FALSE;
	}
	HGLOBAL hTemplate = LoadResource(hInst, hResource);
	if(hTemplate == NULL)
	{
		return FALSE;
	}
	BOOL bResult = CreateIndirect(hTemplate, pParentWnd, hInst);
	FreeResource(hTemplate);

	return bResult;
}

本质上,CWnd类是在跟操作系统打交道,窗口在使用前需要去操作系统注册报道,构造CWnd的时候需要定义类自身变量,等到了使用CWnd的时候,如果没有WinApp之类的其他类帮忙,是需要主动去操作系统注册的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

考琪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值