MFC框架的一种理解方法

MFC的水很深,如果你想搞清楚所有的的细枝末节,恐怕我这里就帮不到你了,需要看侯捷的《深入浅出MFC》之类的书籍,一般而言,我们没必要知道所有的底层技术,但是知道一点基本的框架,对于编程还是很有用的。

一个简单的MFC程序

通常而言,我们在生成MFC程序的时候都是直接用类向导(class Wizard)生成好一个框架,你若想通过这个框架去分析MFC的机制,就会发现越深入,越难懂。
我们不利用MFC类向导生成一个基于MFC的程序,简而言之就是利用win32和MFC库来实现。
首先利用win32建立一个空项目,什么也没有,只有一个resource.h的头文件。然后添加一个头文件(我取名为hello.h),然后添加如下代码:

//#include<afxwin.h>
class CMyMFC_1:public CWinApp
{
public:
    virtual BOOL InitInstance();
};
class CMainWindow:public CFrameWnd
{
public:
    CMainWindow();
protected:
    afx_msg void OnPaint();//WM_PAINT消息响应
    DECLARE_MESSAGE_MAP()//声明消息映射
};

同样的在添加一个源文件(我取名为hello.cpp),源文件代码如下:

#include<afxwin.h>
#include"hello.h"
CMyMFC_1 TheApp;//由应用程序类实例化一个对象
BOOL CMyMFC_1::InitInstance()
{
    m_pMainWnd=new CMainWindow;//公有数据成员
    m_pMainWnd->ShowWindow(m_nCmdShow);
    m_pMainWnd->UpdateWindow();
    return true;
}
BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd)//开始消息映射
    ON_WM_PAINT()
END_MESSAGE_MAP()
CMainWindow::CMainWindow()
{
    Create(NULL,L"The First MFC Application");//创建窗口
}

void CMainWindow::OnPaint()
{
    CPaintDC dc(this);
    CRect rect;
    GetClientRect(&rect);
    dc.DrawText(L"你好,欢迎使用MFC程序",-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
}

输入完成后,在属性->常规->MFC的使用 改为在共享DLL中使用MFC。
编译运行就可以看到下面的框架:

分析

下面我们开始分析一下:
- 1.WinMain函数。一般而言每个window程序都需要一个WinMain函数作为程序的入口,我们在这里没有看到这个函数,是因为它被封装在了CWinApp类中,虽然程序的入口是WinMain,但是并不是说,程序的执行是从WinMain开始的,对于MFC程序,都是先构造一个静态对象,在构造的时候进入WinMain.
- 2-.程序启动。 源程序的第三行就声明了一个静态对象TheApp,该对象属于CMyMFC_1类,程序会使用默认的构造函数,这个构造函数在CWinApp类中,在构造函数过程中,会进入WinMain,并且WinMain寻找一个由CWinApp派生出的全局应用程序对象。
- 3.CMyMFC_1::InitInstance().这是一个虚函数,CWinApp类有这个函数,但是我们重载了CWinApp类的构造函数,当WinMain函数找到应用程序对象theApp时,就调用它的虚拟成员函数InitInstance,所以会调用CMyMFC_1::InitInstance()。这个函数就调用所需要的构造和显示应用程序的主窗口。派生的应用程序类(CMyApp)中必须覆盖InitInstance函数,因为基类(CWinApp)中的函数不知道我们要什么样的主窗口。
- 4.CWinApp::Run。这个函数是CWinApp类的成员,它就是发送应用程序的消息到它的窗口,这样就保证了应用程序一直运行。在WinMain调用InitInstance后就调用Run函数。
- 5.CMainWindow.这个类的一个对象就代表了应用程序的主框架窗口。构造函数调用基类CFrameWnd的成员函数Create的时候,Windows创建实际窗口结构。 ShowWindow和UpdateWindow函数也是基类的成员函数,调用来显示窗口。简而言之你的窗口长什么样就是由这个类决定的。
- 6.CMainFrame::OnPaint函数:每次需要重绘窗口的时候,应用程序框架就调用CMyFrame的成员函数OnPaint。CPaintDC是与GDI有关的一个类。最后显示Hello World!。也就是说当窗口需要重绘的时候,系统会产生WM_PAINT消息,但是我们在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP中没有看到类似于ON_MESSAGE(WM_MYMSG,OnMyMsgHandler)的结构,因为WM_PAINT是一个很重要的消息,在CFrameWnd中,这个消息和OnPaint函数关联(默认的),所以会调用CMyFrame::OnPaint函数。读者可以将OnPaint()函数改为Onpaint,你就会发现不会出现中间哪行字,系统会默认调用CFrameWnd::OnPaint()消息响应函数。
- 7. CMyMFC_1类。这个类的对象代表了这个应用程序,定义了全局对象theApp。基类CWinApp决定了theApp的主要行为。
- 8. 程序结束。 关闭主窗口就关闭了程序。相关事件的顺序:CMyFrame的析构,Run函数退出,WinMain函数退出,CMyApp对象析构。

参考书籍:Visual C++程序设计实用案例教程。于永彦,北京大学出版社。

你可能感兴趣的:(编程)