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

  • 相关阅读:
    AcWing 1027. 方格取数 dp
    AcWing 1014. 登山 dp
    acwing 482. 合唱队形 dp
    LeetCode 1463. 摘樱桃II dp
    LeetCode 100. 相同的树 树的遍历
    LeetCode 336. 回文对 哈希
    LeetCode 815. 公交路线 最短路 哈希
    算法问题实战策略 DARPA大挑战 二分
    算法问题实战策略 LUNCHBOX 贪心
    AcWing 1100. 抓住那头牛 BFS
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3262790.html
Copyright © 2011-2022 走看看