• <MFC_1>深入剖析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消息)那儿设置一个端点

    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,它们觉得这样很浪费内存,所以想出了这么一个类似于多态的消息消息映射机制

  • 相关阅读:
    三种方式循环打印1-100的值
    线程中put(None)和主函数中put(None)的区别和用法
    进程、线程这篇博客,让你傻傻的一次就能记清楚
    单生产者进程和单消费者进程
    队列
    初始线程
    常见面试题之*args
    常见面试题之*args 和 **kwargs 的使用
    闭包函数之函数加括号和不加括号的意义
    仓鼠找sugar II
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3262790.html
Copyright © 2020-2023  润新知