MFC(微软基础类库)以C++类的形式封装了Windows API,给开发者提供了便利,但是初学者常常会疑惑MFC程序的入口在哪里?下面给大家简单介绍一下MFC 程序入口和执行流程。

一 MFC程序执行过程剖析

1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用程序的窗口函数。而在MFC程序当中我们不在能找到类似WinMain这样的程序入口,取而代之的是一系列派生类的声明和定义以及一个冲CWinApp类派生而来的类的全局对象。CWinApp类被称之为应用程序对象,在一个MFC程序当中只允许有一个应用程序对象。由于CWinApp的派生对象是全局的,因此这个对象的构造函数会在所有的其他代码运行之前被调用,而由于CWinApp类当中包含了HWND、HINSTANCE等句柄的存在,其构造函数就执行了对这些成员数据的初始化操作,这里的所谓初始化仅仅是把所有的句柄对象赋值为NULL。

2)在调用完CWinApp的构造函数以后由连接器向程序内自动链接的AfxWinMain函数将被调用,而这个函数可以被看作MFC程序的入口函数。在这个函数当中调用全局AfxGetApp()函数获得应用程序对象,这时将调用AfxInit全局函数,这个函数的功能是使用操作系统传递给AfxWinMain函数的参数初始化应用程序对象当中的相关句柄数据成员。

3)之后AfxWinMain函数调用CWinApp::InitApplication成员函数,这个成员函数用来初始化应用程序对象当中的关于文档部分的内容。

4)随后调用CWinApp::InitInstance成员函数,在这个成员函数当中,使用new操作在堆上声明一个框架窗口对象,由此导致框架窗口对象的构造函数被调用,在框架窗口构造函数当中调用Create函数来创建窗口,而调用的Create函数一般将WNDCLASS参数设置成NULL,这样就由MFC内部调用PreCreateWindow函数,在这个函数当中由MFC注册几个默认的WNDCLASS供框架窗口的Create使用。这时程序控制权交还给CWinApp::InitInstance成员函数内部,由这个函数调用CWnd::ShowWindow显示窗口并且调用CWnd::UpdateWindow向窗口发送WM_PAINT消息。调用完CWinApp::InitInstance成员函数后由AfxWinMain函数调用CWinApp::Run成员函数,并由这个函数来创建和处理消息循环,并且在没有消息的时候处理OnIdle空闲处理。至此整个程序的创建过程完成。
 5)在程序的运行过程当中,由操作系统源源不断的发送消息给应用程序,并且由CWinApp::Run当中的消息循环处理并且分发给相关的窗口对象的DefWindowProc成员函数,并由这个成员函数查询窗口对象的消息映射表,如果查到对应项,则由登记在消息映射表当中的类成员函数处理,否则则按照Message Route当中的顺序象父层类发送。
 6)在消息运行结束,用户按下关闭按钮后,操作系统向程序发送WM_CLOSE消息,默认状况下程序调用DestoryWindow并且发送WM_DESTORY消息,应用程序接受到这个消息以后的默认操作是调用PostQuitMessage函数,由这个函数发送WM_QUIT消息。当程序对象接受到WM_QUIT消息后消息循环结束,由AfxWinMain函数调用AfxTerm函数清理程序使用过的资源并且结束整个程序。
小结:以上的所有描述涵盖了一个程序从开始、运行到结束的所有过程。 相信大家有点晕点了吧,实际编程中没有必要深刻理解这么多,这些大都是由MFC内部自动帮我们完成的。实际MFC编程过程中,其实懂得MFC程序中各个函数的执行流程即可。有时候过于追究MFC细节会白白浪费我们的精力,应该将主要精力放在使用MFC解决实际问题上。

 
二 VC6中SDI程序的执行流程
下面以VC6中的sdi工程为例,通过给每个函数前设置断点后调式执行,可以看出MFC的SDI的执行流程。记录如下,希望对MFC执行有疑惑的人有帮助。
1)CSdiApp theApp;          //sdi.cpp
2)CSdiApp::CSdiApp()             //sdi.cpp
3)BOOL CSdiApp::InitInstance()         //sdi.cpp
4)CSdiDoc::CSdiDoc()                   //sdiDoc.cpp
5)CMainFrame::CMainFrame()          //MainFrm.cpp
6)BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)    //MainFrm.cpp
7)int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)    //MainFrm.cpp
8)CSdiView::CSdiView()                     //sdiView.cpp
9)BOOL CSdiView::PreCreateWindow(CREATESTRUCT& cs)         //sdiView.cpp
10)BOOL CSdiDoc::OnNewDocument()                //sdiDoc.cpp
11) void CSdiView::OnDraw(CDC* pDC)                //sdiView.cpp
// ---------------- 关闭窗口后-------------------------------------
12) CSdiView::~CSdiView()
13) CMainFrame::~CMainFrame()
14) CSdiDoc::~CSdiDoc() 
传送门:请点击

MFC 程序入口和执行流程的更多相关文章

  1. 一个简单的mfc单页界面文件读写程序(MFC 程序入口和执行流程)

    参考:MFC 程序入口和执行流程  http://www.cnblogs.com/liuweilinlin/archive/2012/08/16/2643272.html 程序MFCFlie      ...

  2. 【转载】MFC 程序入口和执行流程

    原文链接: http://www.cnblogs.com/liuweilinlin/archive/2012/08/16/2643272.html 一 MFC程序执行过程剖析 1)我们知道在WIN32 ...

  3. 【转】MFC 程序入口和执行流程

    一 MFC程序执行过程剖析 1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用 ...

  4. MFC学习(三)程序入口和执行流程

    1) WIN32 API程序当中,程序入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用程序窗口函数.而在MFC程序当中我们 ...

  5. 一个 Spark 应用程序的完整执行流程

    一个 Spark 应用程序的完整执行流程 1.编写 Spark Application 应用程序 2.打 jar 包,通过 spark-submit 提交执行 3.SparkSubmit 提交执行 4 ...

  6. Yii2 源码分析 入口文件执行流程

    Yii2 源码分析  入口文件执行流程 1. 入口文件:web/index.php,第12行.(new yii\web\Application($config)->run()) 入口文件主要做4 ...

  7. MFC程序开始的执行过程详述

    1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用程序的窗口函数.而在MFC程 ...

  8. vc++深入跟踪MFC程序的执行流程

    在MFC程序设计的学习过程中最令人感到难受,甚至于有时会动摇学习者信心的就是一种对于程序的一切细节都没有控制权的感觉.这种感觉来源于学习者不知道一个MFC程序是如何运行起来的(即一个MFC程序的执行流 ...

  9. 深入跟踪MFC程序的执行流程

    来源: http://blog.csdn.net/ljianhui/article/details/8781991 在MFC程序设计的学习过程中最令人感到难受,甚至于有时会动摇学习者信心的就是一种对于 ...

随机推荐

  1. H5新特性之webWorker

    众所周知javascript是单线程语言,这就是js开发难度较低的原因了,因为不需要解决多线程的资源共享问题(例如死锁),但是单线程性能并不好,因此多了一个webWorker实现js的多进程来提升js ...

  2. 你能选择出,前几个元素吗?使用纯css

    面试被问到 ,你能选择出前几个元素吗?括弧只能使用css 我当时是一脸懵逼... 回去的路上思考一路 终于想到了解决办法 虽然为时已晚 但是觉得很有意义... 首先要用到 否定选择器 : :not() ...

  3. Docker1.12.6+CentOS7.3 的安装

    安装旧版的docker-engine-1.12.6 kubeadm init --api-advertise-addresses=172.16.160.211命令的时候,提示docker版本太新了 一 ...

  4. 为什么我不推荐你使用vue-cli创建脚手架?

    最近在知乎看到一个问题,原问题如下: "很奇怪,为什么现在能找到自己手动创建vue脚手架的文章非常少,而且大家似乎对webpack4的热情并不高,对于想基于vue2.0+webpack4搭建 ...

  5. spring cloud eureka显示ip

    eureka.instance.preferIpAddress=trueeureka.instance.instance-id=${spring.cloud.client.ipAddress}:${s ...

  6. [洛谷P2234][HNOI2002] 营业额统计 - Treap

    Description Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额. ...

  7. QT生成随机数

    QT生成随机数和C语言差距不大,C语言用srand()和rand(),QT是用Qsrand()和qrand(): QT生成随机数的格式是: qsrand(QTime(0,0,0).secsTo(QTi ...

  8. 深度学习中Xavier初始化

    "Xavier"初始化方法是一种很有效的神经网络初始化方法,方法来源于2010年的一篇论文<Understanding the difficulty of training ...

  9. Ubuntu+Firefox总是打不开网页

    参考链接 火狐的设置里面找: 首选项 -> 高级 -> 网络 -> 连接 -> 设置, 结果发现之前默认是选择了使用系统代理设置, 果断拒绝!... 勾选第一项, " ...

  10. Extensions in UWP Community Toolkit - WebViewExtensions

    概述 UWP Community Toolkit Extensions 中有一个为 WebView 提供的扩展 - WebViewExtensions,本篇我们结合代码详细讲解 WebView Ext ...