深入剖析MFC的WinMain和消息机制

一、开篇引论

熟悉Win32开发的朋友,应该非常了解它的基本组成和流程

1. WinMain:书写窗口类(WNDCLASS) -> 注册窗口类 -> 创建窗口 -> 显示窗口和更新窗口 -> 消息循环

2. WndProc(回调函数):消息处理函数,由windows操作系统自行调用

而MFC呢,就是用c++面向对象的编程思想将这些主要成分封装到各个基本类中,由于封装得很隐蔽,所以学习它的难度就大大增加了。今儿,我就带着大家一起来剖析一下MFC的来龙去脉

 

在看后面两点之前,先上一份剖析MFC最简单的代码(MFC版的Hello):

1. Hello.h:

只有CMyApp和CMainWindow两个类,它们分别是CWinApp、CFrameWnd的子类,这两个基类有分别封装了WinMain和消息映射机制(相当于WndProc的消息处理)

//Hello.h

//封装了Win32的WinMain函数的处理过程
class CMyApp : public CWinApp
{
public:
    virtual BOOL InitInstance ();
};

//实现了MFC的消息机制
class CMainWindow : public CFrameWnd
{
public:
    CMainWindow ();

protected:
    afx_msg void OnPaint ();
    DECLARE_MESSAGE_MAP ()//消息映射的声明
};


2. Hello.cpp

//Hello.cpp

#include <afxwin.h>
#include "Hello.h"

CMyApp myApp;

/////////////////////////////////////////////////////////////////////////
// CMyApp member functions

BOOL CMyApp::InitInstance ()
{
    m_pMainWnd = new CMainWindow;
    m_pMainWnd->ShowWindow (m_nCmdShow);
    m_pMainWnd->UpdateWindow ();
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////
// CMainWindow message map and member functions

//消息映射
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
    ON_WM_PAINT ()
END_MESSAGE_MAP ()

CMainWindow::CMainWindow ()
{
    Create (NULL, _T ("The Hello Application"));
}

void CMainWindow::OnPaint ()
{
    CPaintDC dc (this);
    
    CRect rect;
    GetClientRect (&rect);

    dc.DrawText (_T ("Hello, MFC"), -1, &rect, DT_SINGLELINE |DT_CENTER |  DT_VCENTER);
}


今天主要利用这两份源代码来剖析MFC的"WinMain"和消息机制,下面进入主题(我就不说什么F话了,直接切入^_^)

二、MFC的"WinMain函数"跑哪儿去了呢?

要想找到它,我给大家介绍一种很有效的方式:

1. 如果你是VC++6.0,就用"Call Stack"(下图红色框圈住的按钮)

2. 如果是VS2008,就用"堆栈帧"(在调试模式下,会出现)

我这里使用的是vc++6.0:

1. 先在OnPaint函数(处理WM_PAINT消息)那儿设置一个端点

<MFC_1>深入剖析MFC的WinMain和消息机制_第1张图片

2. 键入F5进入调试模式,然后点击"Call Stack",得到的结果如下:

<MFC_1>深入剖析MFC的WinMain和消息机制_第2张图片

接下来需要做的工作就是一一跟踪这些函数,跟踪一会儿你就能很快了解到MFC中关于Win32的各个实现细节

在这里,由于篇幅的限制,我就直接明述跟踪结果(你可以自行按照上述方法跟踪,这样才有助于深入理解):

1.  全局变量CMyApp myApp;

2. _tWinMain

 <MFC_1>深入剖析MFC的WinMain和消息机制_第3张图片

3. 全局变量myApp的InitInstance()函数

<MFC_1>深入剖析MFC的WinMain和消息机制_第4张图片

4. 窗口类的注册

<MFC_1>深入剖析MFC的WinMain和消息机制_第5张图片

5. 创建窗口

<MFC_1>深入剖析MFC的WinMain和消息机制_第6张图片

6.  显示、更新窗口(还是调用myApp的InitInstance()函数)

<MFC_1>深入剖析MFC的WinMain和消息机制_第7张图片

7. 进入WndProc,处理消息响应

<MFC_1>深入剖析MFC的WinMain和消息机制_第8张图片

 

这里我仅仅将大致的过程贴出来,给你一个大致思路,具体的需要你自己去调试、探究,这样的难度应该就小很多了

三、MFC的消息映射机制

这是MFC的精华所在,它将Win32的消息处理(以WM_开头的消息)过程 映射为 类函数成员函数的处理过程,这样才能符合面向对象的编程思想。其实,它就是使用一大堆宏来实现一种类似于c++的多态机制,因此,要想深入了解这个消息机制,我们必须剖析这些宏:

DECLARE_MESSAGE_MAP ()//消息映射的声明

//消息映射
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
    ON_WM_PAINT ()
END_MESSAGE_MAP ()

 

下面我们一一展开这些宏:(方法很简单,就是在IDE(集成编译环境  就是编译器)中右键对应的宏,然后选择" Go To Definition Of *** " )

1. 首先展开DECLARE_MESSAGE_MAP

1)未展开的

<MFC_1>深入剖析MFC的WinMain和消息机制_第9张图片

2)展开后

<MFC_1>深入剖析MFC的WinMain和消息机制_第10张图片

 

2. 展开
{

BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
    ON_WM_PAINT ()
END_MESSAGE_MAP ()

}

1)未展开的

2)展开后

 

<MFC_1>深入剖析MFC的WinMain和消息机制_第11张图片

 

看到这里,你也许有一点儿蒙,为此,我自行绘制了一张图,它能很好的诠释消息机制的流程关系

<MFC_1>深入剖析MFC的WinMain和消息机制_第12张图片

 

 

好了,现在你应该能明白了吧,可能你还会有一个问题:

MFC本身使用c++封装的,又用一些宏来实现一个类似c++多态的消息映射机制,这不是有些多余吗?

表面上看似是这么回事儿,其实,据我了解到,当时微软的MFC的架构师们测试过,如果用c++的多态性实现,基本上每一个类的对象的储存空间要多那么几十到几百K,它们觉得这样很浪费内存,所以想出了这么一个类似于多态的消息消息映射机制

 

你可能感兴趣的:(main)