一、开篇引论

熟悉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消息)那儿设置一个端点

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

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

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

1.  全局变量CMyApp myApp;

2. _tWinMain

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

4. 窗口类的注册

5. 创建窗口

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

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

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

三、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)未展开的

2)展开后

2. 展开
{

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

}

1)未展开的

2)展开后

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

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

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

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

<MFC_1>深入剖析MFC的WinMain和消息机制的更多相关文章

  1. 剖析MFC六大关键技术(五六)--消息映射与命令传递

    说到消息,在MFC中,“最熟悉的神秘”可算是消息映射,那是我们刚开始接触MFC时就要面对的东西.有过SDK编程经验的朋友转到MFC编程的时候,一下子觉得什么都变了样.特别是窗口消息及对消息的处理跟以前 ...

  2. 深入剖析MFC中对于Windows消息处理、运行机制

    序: 本人对Windows系统.MFC谈不上有深入的了解,但对MFC本身包装API的机制很有兴趣,特别是读了候老师的<深入浅出MFC>后,感觉到VISUAL C++的Application ...

  3. 总结《二》MFC中WinMain和CALLBACK

    MFC中WinMain和回调函数CALLBACK 一,路线        1.一般普通窗口或控件建立调用的CWnd :: CreateEx函数        2.经过资源对话框创建的即不调用的CWnd ...

  4. MFC学习-第4课 消息机制和MFC作图

    转自: 1.http://blog.sina.com.cn/s/blog_6b5180bf01012kbz.html 2.http://blog.csdn.net/happyhhb/article/d ...

  5. WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化

    原文:WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制 ...

  6. MFC模态对话框的消息循环

    MFC模态对话框的消息循环 单线程程序, 当主窗口响应函数中弹出模态对话框时,为什么主窗口响应函数可能照常工作? 当弹出模态对话框时,线程的消息循环无法返回,父窗口的事件本应没人处理,应该处于卡死状态 ...

  7. MFC消息机制

    何谓消息.消息处理函数.消息映射?消息简单的说就是指通过输入设备向程序发出指令要执行某个操作.具体的某个操作是你的一系列代码.称为消息处理函数. 在SDK中消息其实非常容易理解,当窗口建立后便会有一个 ...

  8. MFC原理第五讲.消息映射.以及如何添加消息

    MFC原理第五讲.消息映射.以及如何添加消息 一丶消息映射是什么 我们知道.Win32程序.都是通过消息去驱动的. 不断的在处理消息. 只要我们使用固定的宏.就可以让我们的框架知道一旦消息发生.该往哪 ...

  9. 我对windows消息机制的理解(参考深入浅出MFC,欢迎批评指正!!)

    以消息为基础,以事件驱动之 程序的进行依靠外部消息来驱动,即:程序不断等待任何可能的输入,然后做判断,然后再做适当的处理. 消息输入:操作系统捕获,以消息形式进入程序.(操作系统通过其USERS模块中 ...

随机推荐

  1. HDU 5273 Dylans loves numbers(水题)

    题意:给出一个0≤N≤1018,求其二进制中有几处是具有1的,假设相连的1只算1处,比如1101011就是3处. 思路:一个个数,当遇到第一个1时就将flag置为1:当遇到0就将flag置为0.当遇到 ...

  2. 对于fmri的hrf血液动力学响应函数的一个很直观的解释-by 西南大学xulei教授

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% clear all;clc; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ...

  3. php时区测试

    php里面关于时间的函数有date,time,strtotime,gmdate等,里面只要和时间字符串相关的基本都收到时区的影响,所以时间戳才是唯一稳定时间记录,因为标准都是统一的.这里联想到数据库的 ...

  4. 【自动化测试】PO思路

    http://blog.csdn.net/liubofengpython/article/details/7720078

  5. Filling a Path 模式

    Filling a Path When you fill the current path, Quartz acts as if each subpath contained in the path ...

  6. mysql利用存储过程批量插入数据

    最近需要测试一下mysql单表数据达到1000W条以上时增删改查的性能.由于没有现成的数据,因此自己构造,本文只是实例,以及简单的介绍. 首先当然是建表: [sql]view plaincopy CR ...

  7. android view生命周期

    onFinishInflate() 当View中所有的子控件均被映射成xml后触发 onMeasure( int ,  int ) 确定所有子元素的大小 onLayout( boolean ,  in ...

  8. 让IE6IE7IE8支持CSS3属性的8种方法介绍

    我们都知道,IE浏览器暂不支持CSS3的一些属性.国外的工程师们,不安于此现状,他们总是尽量使用一些手段使IE浏览器也能支持CSS3属性,我觉得这些都是很有意义,很有价值的工作,可以推动整个技术领域的 ...

  9. Exploit用法示例

    一.msf> show exploits与msf> show payloads:这两条命令用于展示Metaploit目录中所有可用的漏洞利用代码和攻击载荷. 二.msf> searc ...

  10. 线性时间内确定T[0:n]是否有一个主元素

    设T[0:n-1]是n 个元素的数组.对任一元素x,设S(x)={ i | T[i]=x}.当| S(x) |>n/2 时,称x 为T 的主元素.设计一个算法,确定T[0:n-1]是否有一个主元 ...