当前位置:C++技术网 > 资讯 > MFC窗口的创建过程深入理解及实例示范

MFC窗口的创建过程深入理解及实例示范

更新时间:2016-01-06 10:58:06浏览次数:1+次

MFC中创建窗口分成两步:第一步是创建CWnd实例,第二步是创建窗口,并把该窗口句柄保存到CWnd实例的m_hWnd成员中。MFC中销毁窗口也要确保销毁窗口对象以及与之关联的C++对象-CWnd实例。
MFC的 CWnd类及其派生类为窗口或应用程序创建的窗口提供了面向对象的接口。
BOOL Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName,DWORD dwStyle = WS_OVERLAPPEDWINDOW,Const RECT& rect=rectDefault,CWnd *pParentWnd=NULL,LPCTSTR lpszMenuName=NULL,DWORD szStyle=0,CC
reateContext* pContext=NULL)
Create接受的8个参数中的六个有默认值定义。第一个参数为窗体类名,如果将其设为NULL,则表示使用CFrameWnd默认的类名(即MFC内部封装的);第二个参数表示窗体名,其他的参数可以省略。但如果要设置菜单,则传入菜单资源的字符串名字,如果不是字符串而是ID,需要用MAKEINRRESOURCE将其转化为字符串。

CWnd的Create内部调用了CreateEx来创建窗体,注意Create方法只能创建子窗体:

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)不能用来创建desktop或弹出窗口,此时用CreateEx
	ASSERT(pParentWnd != NULL);
	ASSERT((dwStyle & WS_POPUP) == 0);

	return CreateEx(0, lpszClassName, lpszWindowName,
		dwStyle | WS_CHILD,
		rect.left, rect.top,
		rect.right - rect.left, rect.bottom - rect.top,
		pParentWnd->GetSafeHwnd(), (HMENU)(UINT_PTR)nID, (LPVOID)pContext);
}
对于这个你可以试试,我们写入代码:
m_btn.Create(L"按钮",WS_VISIBLE | BS_DEFPUSHBUTTON, CRect(0,0,100,100),NULL,123);
对于这行代码,我们在WM_CREATE消息中进行响应。
注意哦,这个CButton变量需要是全局的,或者,你直接用类向导建立一个CButton类的变量,但绝对不能是局部的,笔者我就是吃了这样的亏。一开始老是没结果显示出来,搞到最后原来是局部变量的内存分配周期的问题。你运行之后试试,程序会跳出一个对话框,你点击"重试"就会跳转到Create函数的封装源代码中,由于某些原因,我就不贴出图片来了。
下面,我们来创建一个窗口,还是基于WM_CREATE消息:
int CReviewView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	//////在此处添加代码
	LPCTSTR pszWnd=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,LoadCursor(NULL,IDC_ARROW),0,
		LoadIcon(NULL,IDI_ERROR));
	m_wnd.Create(pszWnd,L"测试",WS_OVERLAPPEDWINDOW | WS_VISIBLE, CRect(50,50,300,200),this,123321);
	return 0;
}
之前,我就说过对于create函数的参数而言,第一个参数如果设为NULL,程序会自动调用底部的WNDCLASS结构体所注册的窗口类。在WNDCLASS结构体中,有一个字段是lpszClassName这个是指,我们引入写入的窗口类的名字。在上述代码中,我们改变了create第一个参数,不再是NULL,因此,程序会运行我们自己写入的窗口类。记住只能用于创建子窗口,也就是说,我们现在创建的这个窗口是子窗口,基于视图窗口(this)创建的。
AfxRegisterWndClass(UINT nClassStyle,HCURSOR hCursor, HBRUSH hbrBackground,HICON hIcon);
这是AfxRegisterWndClass函数的原型,也就是我们所能改变的窗口的样式。