⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 03.2.2 mfc框架窗口(2).txt

📁 网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
💻 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 + -