📄 03.2.2 mfc框架窗口(2).txt
字号:
.创建窗口
按照Win32程序编写步骤,设计窗口类并注册窗口类之后,应该是创建窗口了。在MFC程序中,窗口的创建功能是由CWnd类的CreateEx函数实现的,该函数的声明位于AFXWin.h文件中,具体代码如下所示。
BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,
LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam = NULL);
其实现代码位于WINCORE.CPP文件中,部分代码如例3-14所示。
例3-14
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)
{
// allow modification of several common create parameters
CREATESTRUCT cs;
cs.dwExStyle = dwExStyle;
cs.lpszClass = lpszClassName;
cs.lpszName = lpszWindowName;
cs.style = dwStyle;
……
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);
……
}
在MFC底层代码中,CFrameWnd类的Create函数内部调用了上述CreateEx函数。而前者又由CFrameWnd类的LoadFrame函数调用。读者可以自行跟踪这一调用过程。
CFrameWnd类的Create函数的声明也位于AFXWin.h文件中,具体代码如下所示。
BOOL Create(LPCTSTR lpszClassName,
LPCTSTR lpszWindowName,
DWORD dwStyle = WS_OVERLAPPEDWINDOW,
const RECT& rect = rectDefault,
CWnd* pParentWnd = NULL, // != NULL for popups
LPCTSTR lpszMenuName = NULL,
DWORD dwExStyle = 0,
CCreateContext* pContext = NULL);
其定义位于在WINFRM.CPP文件中,部分代码如例3-15所示。
例3-15
BOOL CFrameWnd::Create(LPCTSTR lpszClassName,
LPCTSTR lpszWindowName,
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
LPCTSTR lpszMenuName,
DWORD dwExStyle,
CCreateContext* pContext)
{
……
if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))
{
TRACE0("Warning: failed to create CFrameWnd.\n");
if (hMenu != NULL)
DestroyMenu(hMenu);
return FALSE;
}
……
}
CFrameWnd类派生于CWnd类。从上述声明代码可知,CWnd类的CreateEx函数不是虚函数。另外,CFrameWnd类中也没有重写这个函数。根据类的继承性原理,CFrameWnd类就继承了CWnd类的CreateEx函数。因此,例3-15所示CFrameWnd类的Create函数内调用的实际上就是CWnd类的CreateEx函数。读者可以在这两个函数的定义处都设置断点,然后调试运行Test程序以验证这一点。
再回到例3-14所示CWnd类的CreateEx函数实现代码中,可以发现该函数中又调用了PreCreateWindow函数,后者是一个虚函数。因此,这里实际上调用的是子类,即CMainFrame类的PreCreateWindow函数。之所以在这里再次调用这个函数,主要是为了在产生窗口之前让程序员有机会修改窗口外观,例如,去掉窗口的最大化按钮等,PreCreateWindow函数的参数就是为了实现这个功能而提供的。该参数的类型是CREATETRUCT结构,我们可以把这个结构体与CreateWindowEx函数的参数作一个比较,图3.19是CREATETRUCT结构和CreateWindowEx函数声明的一个对比,注意左边结构体成员与右边函数参数的对应关系。
图3.19 CREATETRUCT结构和CreateWindowEx函数定义的对比
可以发现,CREATETRUCT结构体中的字段与CreateWindowEx函数的参数是一致的,只是先后顺序相反而已。同时,可以看到PreCreateWindow函数的这个参数是引用类型。这样,在子类中对此参数所做的修改,在其基类中是可以体现出来的。再看看前面例3-14所示CWnd类的CreateEx函数代码,如果在子类的PreCreateWindow函数中修改了CREATESTRUCT结构体的值,那么,接下来调用CreateWindowEx函数时,其参数就会发生相应的改变,从而就会创建一个符合我们要求的窗口。
知识点 MFC中后缀名为Ex的函数都是扩展函数。
3.显示窗口和更新窗口
在Test程序的应用程序类(CTestApp)中有一个名为m_pMainWnd的成员变量。该变量是一个CWnd类型的指针,它保存了应用程序框架窗口对象的指针。也就是说,是指向CMainFrame对象的指针。在CTestApp类的InitInstance函数实现内部有如下两句代码。
// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
这两行代码的功能是显示应用程序框架窗口和更新这个窗口。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -