首先声明这篇博客是给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. #ifdef _DEBUG
  5. #define new DEBUG_NEW
  6. #endif
  7. // CExampleApp
  8. BEGIN_MESSAGE_MAP(CExampleApp, CWinApp)
  9. ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
  10. END_MESSAGE_MAP()
  11. // CExampleApp 构造
  12. CExampleApp::CExampleApp()
  13. {
  14. // TODO: 在此处添加构造代码,
  15. // 将所有重要的初始化放置在 InitInstance 中
  16. }
  17. // 唯一的一个 CExampleApp 对象
  18. CExampleApp theApp;
  19. // CExampleApp 初始化
  20. BOOL CExampleApp::InitInstance()
  21. {

程序刚好执行的上面一句我们很多初始化都写在这个函数里,包括创建类对象,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. enum { IDD = IDD_EXAMPLE_DIALOG };
  8. protected:
  9. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
  10. // 实现
  11. protected:
  12. HICON m_hIcon;
  13. // 生成的消息映射函数
  14. virtual BOOL OnInitDialog();
  15. afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
  16. afx_msg void OnPaint();
  17. afx_msg HCURSOR OnQueryDragIcon();
  18. DECLARE_MESSAGE_MAP()
  19. };

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

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

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

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

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

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

MFC自动生成代码详解(一)的更多相关文章

  1. ASP.NET MVC 5 学习教程:生成的代码详解

    原文 ASP.NET MVC 5 学习教程:生成的代码详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...

  2. mybatis-generator : 自动生成代码

    [参考文章]:mybatis generator自动生成代码时 只生成了insert 而没有其他 [参考文章]:Mybatis Generator最完整配置详解 1. pom <plugin&g ...

  3. mybatis-generator自动生成代码插件

    mybatis自动生成代码(实体类.Dao接口等)是很成熟的了,就是使用mybatis-generator插件. 它是一个开源的插件,使用maven构建最好,可以很方便的执行 插件官方简介: http ...

  4. Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测

    Kaggle网站流量预测任务第一名解决方案:从模型到代码详解时序预测 2017年12月13日 17:39:11 机器之心V 阅读数:5931   近日,Artur Suilin 等人发布了 Kaggl ...

  5. Mybatis 自动生成代码,数据库postgresql

    最近做了一个项目,使用Mybatis自动生成代码,下面做一下总结,被以后参考: 一.提前准备: 1.工具类:mybatis-generator-core-1.3.2.jar 2.postgresql驱 ...

  6. Mybatis的逆向工程,自动生成代码(Mapper,xml,bean)

    步骤: 1. 新建一个Maven项目: 然后导入maven依赖: <dependencies> <dependency> <groupId>org.mybatis& ...

  7. MyBatis使用Generator自动生成代码

    MyBatis中,可以使用Generator自动生成代码,包括DAO层. MODEL层 .MAPPING SQL映射文件. 第一步: 配置好自动生成代码所需的XML配置文件,例如(generator. ...

  8. 【MyBatis】MyBatis自动生成代码查询之爬坑记

    前言 项目使用SSM框架搭建Web后台服务,前台后使用restful api,后台使用MyBatisGenerator自动生成代码,在前台使用关键字进行查询时,遇到了一些很宝贵的坑,现记录如下.为展示 ...

  9. Java中String的intern方法,javap&cfr.jar反编译,javap反编译后二进制指令代码详解,Java8常量池的位置

    一个例子 public class TestString{ public static void main(String[] args){ String a = "a"; Stri ...

随机推荐

  1. 转:Linux设备驱动开发(1):内核基础概念

    一.linux设备驱动的作用 内核:用于管理软硬件资源,并提供运行环境.如分配4G虚拟空间等. linux设备驱动:是连接硬件和内核之间的桥梁. linux系统按个人理解可按下划分: 应用层:包括PO ...

  2. L2tp协议简单解析

    1.L2TP简介 L2TP(Layer 2 Tunneling Protocol,二层隧道协议)是VPDN(Virtual PrivateDial-up Network,虚拟私有拨号网)隧道协议的一种 ...

  3. array numpy 模块

    高级用法:http://www.jb51.net/article/87987.htm from array import * 调用 array 与 import numpy as np  调用 np. ...

  4. git hg提交拉取

    工作总结web_acl 535 git clone “ssh://git@outergit.yonyou.com:49622/esn_web/web_acl.git" 600 git bra ...

  5. mysql备份的三种方式

    一.备份的目的 做灾难恢复:对损坏的数据进行恢复和还原需求改变:因需求改变而需要把数据还原到改变以前测试:测试新功能是否可用 二.备份需要考虑的问题 可以容忍丢失多长时间的数据:恢复数据要在多长时间内 ...

  6. lrzsz的安装与配置

    1)下载http://freshmeat.sourceforge.net/projects/lrzsz/ 2)tar zxvf lrzsz-0.12.20.tar.gz 3)mv lrzsz-0.12 ...

  7. ReentrantLock 使用

    从使用场景的角度出发来介绍对ReentrantLock的使用,相对来说容易理解一些. 场景1:如果发现该操作已经在执行中则不再执行(有状态执行) a.用在定时任务时,如果任务执行时间可能超过下次计划执 ...

  8. Python 字典 get() 方法

    描述 Python 字典 get() 方法和 setdefault() 方法类似,返回指定键的值,如果键不在字典中,返回一个指定值,默认为None. get() 和 setdefault() 区别:  ...

  9. 前端知识--------HTML内容

    HTML介绍 1.web服务本质 import socket sk = socket.socket() sk.bind(('127.o.o.1',8080)) sk.listen() while 1: ...

  10. PS切图导出代码后出现的图片布局散乱的解决方法——table布局

    前言: 一般来说,大部分美工PS切图后导出的都是使用PS默认的table布局的页面,出现最多的异常是上传代码,替换图片后,发现图片布局散乱,完全不是想要的效果.轻微的是浏览器不兼容,只有部分浏览器可以 ...