深入剖析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"(下图红色框圈住的按钮)

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

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

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

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

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

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

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

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

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

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

1.  全局变量CMyApp myApp;

2. _tWinMain

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

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

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

4. 窗口类的注册

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

5. 创建窗口

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

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

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

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

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

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

三、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和消息机制

2)展开后

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

2. 展开
{

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

}

1)未展开的

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

2)展开后

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

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

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

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

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

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

上一篇:删除数据库时报错 ERROR 1010 (HY000): Error dropping database (can't rmdir './cart', errno: 39)


下一篇:QCustomplot(二) 源码解读