• MFC自动生成代码详解(一)


    首先声明这篇博客是给MFC刚刚上路的coder准备的,老鸟们就自觉无视我吧!

    大家有没有感觉,创建MFC工程时他总会生成一大堆文件一大堆代码。虽然给我们带来了便利,但是调试的时候碰到这些代码总是畏首畏脚的,从来不敢动他们。这篇博客就来帮大家解决这个问题。让你在熟悉他们的作用同时,真正的不怕他们!

    现在我见了一个工程名字为Example他会生成以上几个文件

    我们就从从Example.cpp开始,先看最中间的

    1. CExampleApp theApp; //application object  

    这段代码其实就是本程序的application object,每个程序有且仅有一个。当程序执行时,这个全域对象产生,构造是执行起来。CWinApp 之中的成员变量将因为theApp 这个全域对象的诞生而获得配置与初值。此段执行完后winmain登场,由于winmain并不在这几个文件夹了,所以不能直观的看到他。

    1. int AFXAPI AfxWinMain (...)  
    2. {  
    3. CWinApp* pApp = AfxGetApp();  
    4. AfxWinInit(...);  
    5. pApp->InitApplication();  
    6. pApp->InitInstance();  
    7. nReturnCode = pApp->Run();  
    8. AfxWinTerm();  
    9. }  


    theapp获得初值后,上面的代码开始执行。至于上面几个函数具体的代码实现会在后面的连载中一一介绍,在这里先交待一下他们的作用。

    1. AfxWinInit(...);  

    这句代码的意思借用《深入浅出MFC》的一句话,。MFC中的 AfxWinInit的确会为我们注册四个窗口类别,但不再是在AfxWinInit 中完成。

    1. pApp->InitApplication();  

    本段代码相当于CMyWinApp::InitApplication();CMyWinApp 继承自CWinApp,而InitApplication 又是CWinApp 的一个虚拟函数;我们并没有改写它(大部份情况下不需改写它),所以上述动作相当于调用:CWinApp::InitApplication();这些动作都是MFC 为了内部管理而做的。

    1. pApp->InitInstance();  

    这段代码和上面的代码一样,也相当于调用CMyWinApp::InitInstance();但是看下面的Example.cpp中的InitInstance()被我们改写了,所以说上述动作的的确确就是调用我们自己(CMyWinApp)的这个InitInstance 函数。我们将在该处展开我们的主窗口生命。

    1. nReturnCode = pApp->Run();  

    此时程序会执行Example.cpp中的InitInstance(),所以上面的run()函数我们先跳过。

    1. #include "stdafx.h"  
    2. #include "Example.h"  
    3. #include "ExampleDlg.h"  
    4.   
    5. #ifdef _DEBUG  
    6. #define new DEBUG_NEW  
    7. #endif  
    8.   
    9.   
    10. // CExampleApp  
    11.   
    12. BEGIN_MESSAGE_MAP(CExampleApp, CWinApp)  
    13.     ON_COMMAND(ID_HELP, &CWinApp::OnHelp)  
    14. END_MESSAGE_MAP()  
    15.   
    16.   
    17. // CExampleApp 构造  
    18.   
    19. CExampleApp::CExampleApp()  
    20. {  
    21.     // TODO: 在此处添加构造代码,  
    22.     // 将所有重要的初始化放置在 InitInstance 中  
    23. }  
    24.   
    25.   
    26. // 唯一的一个 CExampleApp 对象  
    27.   
    28. CExampleApp theApp;  
    29.   
    30.   
    31. // CExampleApp 初始化  
    32.   
    33. BOOL CExampleApp::InitInstance()  
    34. {  

    程序刚好执行的上面一句我们很多初始化都写在这个函数里,包括创建类对象,m_pMainWnd->ShowWindow(m_nCmdShow);  m_pMainWnd->UpdateWindow();两个函数这样再加上构造函数中的Create()函数,我的的窗口就这样生成了。很简单吧!

    1. nReturnCode = pApp->Run();  

    下面就到这段代码的了。MFC的消息机制也从这开始了。在上面窗口创建完之后消息队列中出现了一个WM_PAINT 消息,等待被处理。现在,执行的脚步到达pApp->Run。当然Run()和上面一样相当于CMyWinApp::Run();而Run 又是CWinApp 的一个虚拟函数。所以说他和initapplicationa()一样。执行的这里下面就是MFC的精髓所在了。MFC 提供给应用程序使用的「很方便的接口」是两组宏。以Hello 的主窗口为例,

    第一个动作是在Example.H 加上DECLARE_MESSAGE_MAP:

    1. DECLARE_MESSAGE_MAP()  

    下一个动作就用到Example.cpp中的一组宏

    1. BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)  
    2. ON_WM_PAINT()  
    3. ON_COMMAND(IDM_ABOUT, OnAbout)  
    4. END_MESSAGE_MAP()  

    这样消息WM_PAINT 就顺利导入导到OnPaint 函数中了。但是他最后怎么到他需要的函数中去的呢?这就是MESSAGE_MAP()的作用了。在这里先不详谈。

    下面就到下一个文件ExampleDlg.cpp了

    1. class CExampleDlg : public CDialog  
    2. {  
    3. // 构造  
    4. public:  
    5.     CExampleDlg(CWnd* pParent = NULL);  // 标准构造函数  
    6.   
    7. // 对话框数据  
    8.     enum { IDD = IDD_EXAMPLE_DIALOG };  
    9.   
    10.     protected:  
    11.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持  
    12.   
    13.   
    14. // 实现  
    15. protected:  
    16.     HICON m_hIcon;  
    17.   
    18.     // 生成的消息映射函数  
    19.     virtual BOOL OnInitDialog();  
    20.     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);  
    21.     afx_msg void OnPaint();  
    22.     afx_msg HCURSOR OnQueryDragIcon();  
    23.     DECLARE_MESSAGE_MAP()  
    24. };  

    看到注释相信大家对这段代码已经有了基本的了解了,在这其中是一些函数的声明包括构造函数,消息映射函数,和非常重要的用于数据动态绑定的DoDataExchange()接下来我们来看ExampleDlg.cpp

    1. BOOL CExampleDlg::OnInitDialog()  
    2. {  
    3.       
    4. }  
    5. void CExampleDlg::OnSysCommand(UINT nID, LPARAM lParam)  
    6. {  
    7.       
    8. }  
    9.   
    10. // 如果向对话框添加最小化按钮,则需要下面的代码  
    11. //  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,  
    12. //  这将由框架自动完成。  
    13.   
    14. void CExampleDlg::OnPaint()  
    15. {  
    16. }  

    cpp文件是对.h文件的函数的实现在这里就不全部copy过来的,在这只介绍最重要的三个函数

    1. BOOL CExampleDlg::OnInitDialog()  
    调用这个成员函数是对WM_INITDIALOG消息作出的反应。如果在对话框初始化后需要执行特别处理,覆盖覆盖该函数。首先调用基类OnInitDialog,但不考虑其返回值。正常情况下,覆盖的函数返回TRUE。调用是通过标准的全局对话框过程,而不是通过消息映射。因此该函数不需要消息映射入口。
    1. void CExampleDlg::OnSysCommand(UINT nID, LPARAM lParam)  

    这个函数主要是截获控制命令的

    1. void CExampleDlg::OnPaint()  

    OnPaint()是CWnd的类成员,负责响应WM_PAINT消息。

    下面就到了stdafx了

    1. // stdafx.h : 标准系统包含文件的包含文件,  
    2. // 或是经常使用但不常更改的  
    3. // 特定于项目的包含文件  
    4.   
    5. #pragma once  
    6.   
    7. #ifndef _SECURE_ATL  
    8. #define _SECURE_ATL 1  
    9. #endif  
    10.   
    11. #ifndef VC_EXTRALEAN  
    12. #define VC_EXTRALEAN        // 从 Windows 头中排除极少使用的资料  
    13. #endif  
    14.   
    15. // 如果您必须使用下列所指定的平台之前的平台,则修改下面的定义。  
    16. // 有关不同平台的相应值的最新信息,请参考 MSDN。  
    17. #ifndef WINVER              // 允许使用特定于 Windows XP 或更高版本的功能。    下面这段代码相信大家看注释就能明白,那就是本程序对版本的要求  
    18. #define WINVER 0x0501       // 将此值更改为相应的值,以适用于 Windows 的其他版本。  
    19. #endif  
    20.   
    21. #ifndef _WIN32_WINNT        // 允许使用特定于 Windows XP 或更高版本的功能。  
    22. #define _WIN32_WINNT 0x0501 // 将此值更改为相应的值,以适用于 Windows 的其他版本。  
    23. #endif                        
    24.   
    25. #ifndef _WIN32_WINDOWS      // 允许使用特定于 Windows 98 或更高版本的功能。  
    26. #define _WIN32_WINDOWS 0x0410 // 将它更改为适合 Windows Me 或更高版本的相应值。  
    27. #endif  
    28.   
    29. #ifndef _WIN32_IE           // 允许使用特定于 IE 6.0 或更高版本的功能。  
    30. #define _WIN32_IE 0x0600    // 将此值更改为相应的值,以适用于 IE 的其他版本。值。  
    31. #endif  
    32.   
    33. #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS  // 某些 CString 构造函数将是显式的  
    34.   
    35. // 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏  
    36. #define _AFX_ALL_WARNINGS  
    37.   
    38. #include <afxwin.h>         // MFC 核心组件和标准组件                                            下面的代码主要用来引用MFC各组件和类  
    39. #include <afxext.h>         // MFC 扩展  
    40.   
    41.   
    42. #include <afxdisp.h>        // MFC 自动化类  
    43.   
    44.   
    45.   
    46. #ifndef _AFX_NO_OLE_SUPPORT  
    47. #include <afxdtctl.h>     // MFC 对 Internet Explorer 4 公共控件的支持  
    48. #endif  
    49. #ifndef _AFX_NO_AFXCMN_SUPPORT  
    50. #include <afxcmn.h>           // MFC 对 Windows 公共控件的支持  
    51. #endif // _AFX_NO_AFXCMN_SUPPORT  

    最后就剩下stdafx.cpp了,这段代码大家注释简单明了,在这里就不做过多解释了!

    1. // stdafx.cpp : 只包括标准包含文件的源文件  
    2. // Example.pch 将作为预编译头  
    3. // stdafx.obj 将包含预编译类型信息  
    4.   
    5. #include "stdafx.h"  


    看了这么半天相信你对自动生成的代码已经有了一定的了解了吧!你是否找到编写MFC的乐趣了呢?如果是的,那就关注一下我吧!让我们一起学习,一起成长!

  • 相关阅读:
    23丨当Postgres磁盘读引起IO高的时候,应该怎么办
    22丨案例:当磁盘参数导致IO高的时候,应该怎么办
    LNMP环境搭建
    virtualbox中centos虚拟机网络配置
    chrome扩展程序开发
    Linux账号管理
    Linux设置文件与Shell操作环境
    Yii2之组件的注册与创建
    Stream 源码分析
    Exchanger 源码分析
  • 原文地址:https://www.cnblogs.com/zhaoxinshanwei/p/3830805.html
Copyright © 2020-2023  润新知