//////////////////////////////////////////////////////////////////////////////////////////
MFC程序的执行顺序依次是:theApp全局对象定义处、TestApp构造函数、WinMain。
程序在加载main函数之前,会先为全局变量和全局对象分配内存空间。
对于MFC程序来说,通过产生一个应用程序类的对象来唯一标识应用程序的实例。每一个MFC程序实例有且仅有一个该派生类的实例化对象,也就是theApp全局对象,该对象就表示了应用程序本身。
theApp对象的构造函数CtestApp在调用之前,会调用其父类CWinApp的构造函数,从而就把我们程序自己创建的类与Microsoft提供的基类关联起来了。CWinApp的构造函数完成程序运行时的一些初始化工作。
AfxWinMain函数:WinMain函数实际上是通过调用AfxWinMain函数来完成它的功能的。
AfxWinMain调用AfxGetThread函数获得一个CWinTread类型的指针。
接着AfxWinMain调用AfxGetApp函数获得一个CWinApp类型的指针。
由以下代码可以看出:AfxGetThread函数返回的就是AfxGetApp函数的结果。
- CWinThread* AFXAPI AfxGetThread()
- {
- // check for current thread in module thread state
- AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
- CWinThread* pThread = pState->m_pCurrentWinThread;
- // if no CWinThread for the module, then use the global app
- if (pThread == NULL)
- pThread = AfxGetApp();
- return pThread;
- }
复制代码
因此,AfxWinMain函数中的pThread和pApp这两个指针是一致的。
AfxGetApp函数返回的是在CWinApp构造函数中保存的this指针(详见CWinApp类定义的源文件:appcore.cpp)。
对本Test程序来说,这个this指针实际上指向的是CTestApp的对象:theApp。也就是说,pThread和pApp所指向的都是CTestApp类的对象,即theApp全局对象。
InitInstance函数:
pThread和pApp调用了三个函数(InitApplication、InitInstance和Run)去完成Win32程序所需要的几个步骤:设计窗口类、注册窗口类、创建窗口、显示窗口、更新窗口、消息循环以及窗口过程函数。
pApp首先调用InitApplication函数完成MFC内部管理方面的工作。
接着,调用pThread的InitInstance函数(其实是调用从CWinApp派生的应用程序类CTestApp中的虚函数InitInstance)。
MFC框架窗口
1.设计和注册窗口:MFC已经为我们预定义了一些默认的标准窗口类,只需呀选择所需的窗口类,然后注册就可以了。
窗口类的注册由AfxEndDeferRegisterClass函数完成(AfxEndDeferRegisterClass函数首先判断窗口类的类型,然后赋予其相应的类名,这些类名是MFC预定义的,然后调用AfxRegisterClass函数注册窗口类)。
AfxRegisterClass函数首先获得窗口类的信息,如果该窗口已经注册,则直接返回一个真值;如果尚未注册,就调用RegisterClass函数注册该窗口类(注册窗口类使用的函数其实和Win32 SDK编程中所使用的函数一致)。
我们所创建的这个MFC应用程序Test,实际上有两个窗口。
其中之一:CMainFrame:: PreCreateWindow,这是在窗口产生之前被调用的。CMainFrame:: PreCreateWindow函数又调用了AfxDeferRegisterClass,而AfxDeferRegisterClass实际上是一个宏,指向AfxEndDeferRegisterClass(前面提到,此函数的功能就是注册窗口类)。
2.创建窗口:
窗口的创建是由CWnd类的CreateEx函数实现的。(声明:AFXWin.h实现:WINCORE.CPP)
(在MFC的底层代码中CFrameWnd::Create调用了上述的CreateEx函数,而CFrameWnd:: LoadFrame又调用CFrameWnd::Create函数。此过程请自行跟踪。)
CWnd::CreateEx调用CMainFrame:: PreCreateWindow(PreCreateWindow是一个虚函数,所以这里实际上调用的是子类,即CMainFrame:: PreCreateWindow。这里再次调用此函数是为了在产生窗口之前让程序员有机会修改程序的外观。例如,去掉窗口最大化按钮等)
3.显示和更新窗口
CTestApp:: m_pMainWnd
m_pMainWnd是一个CWnd类型并且保存了应用程序框架窗口对象的指针,也就是说m_pMainWnd变量是一个指向CMainFrame对象的指针。
CTestApp::InitInstance函数实现内部有如下两行代码:
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
这两行代码实现了窗口的显示和更新。
消息循环
CWinThread::Run函数完成消息循环。
该函数由AfxWinMain::pThread函数调用。
形式:pThread->Run();
CWinThread::Run函数主要是一个for循环,该循环在收到一个WM_QUIT消息时退出。在此循环中调用了一个PumpMessage函数。
窗口过程函数
AfxEndDeferRegisterClass函数源程序:wndcls.lpfnWndProc = DefWindowProc
这里指定的一个默认窗口过程DefWindowProc。但实际上MFC程序并不是把所有的消息都交给DefWindowProc这一默认窗口过程来处理。而是采用了一种“消息映射机制”。
///////////////////////////////////////////////////////////////////////////////////////////
梳理全过程
1.首先利用全局应用程序对象theApp启动应用程序。正是产生了这个全局对象,基类CWinApp中的this指针才能指向这个对象。如果没有这个全局对象,程序在编译的时候不会出错,但在运行时就出错。
2.调用全局应用程序对象的构造函数,从而就会先调用其基类CWinApp的构造函数。后者完成应用程序的一些初始化工作,并将应用程序对象的指针保存起来。
3.进入WinMain函数。在AfxWinMain函数中可以获取子类(对Test程序来说,就是CTestApp类)的指针,利用此指针调用虚函数:InitInstance,根据多态性原理,实际上调用的是子类(CTestApp)的InitInstance函数。后者完成一些应用程序的初始化工作,包括窗口类的注册、创建,窗口的显示和更新。期间会多次调用CreateEx函数,因为一个单文档MFC应用程序有多个窗口,包括框架窗口、工具条、状态条等。
4.进入消息循环。虽然也设置了默认的窗口过程函数,但是,MFC应用程序实际上采用消息影射机制来处理各种消息的。当收到WM_QUIT消息时,退出消息循环,程序结束。
///////////////////////////////////////////////////////////////////////////////////////////
MFC内部结构剖析的更多相关文章
-
我的MFC学习之路(一)
因为项目需求,我开始应用MFC写程序.具体接触MFC的时间大概也有两个月了.现在的水平算是刚刚踏入了MFC大门的半只脚.目前能基本使用MFC Class Wizard,可以根据实例仿照完成需求,小范围 ...
-
让DB2跑得更快——DB2内部解析与性能优化
让DB2跑得更快——DB2内部解析与性能优化 (DB2数据库领域的精彩强音,DB2技巧精髓的热心分享,资深数据库专家牛新庄.干毅民.成孜论.唐志刚联袂推荐!) 洪烨著 2013年10月出版 定价:7 ...
-
pg 资料大全1
https://github.com/ty4z2008/Qix/blob/master/pg.md?from=timeline&isappinstalled=0 PostgreSQL(数据库) ...
-
<;MFC_1>;深入剖析MFC的WinMain和消息机制
一.开篇引论 熟悉Win32开发的朋友,应该非常了解它的基本组成和流程 1. WinMain:书写窗口类(WNDCLASS) -> 注册窗口类 -> 创建窗口 -> 显示窗口和更新窗 ...
-
MFC程序执行过程剖析
一 MFC程序执行过程剖析 1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用 ...
-
MFC程序执行过程剖析(转)
一 MFC程序执行过程剖析 1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用 ...
-
深入剖析MFC中对于Windows消息处理、运行机制
序: 本人对Windows系统.MFC谈不上有深入的了解,但对MFC本身包装API的机制很有兴趣,特别是读了候老师的<深入浅出MFC>后,感觉到VISUAL C++的Application ...
-
剖析MFC六大关键技术(五六)--消息映射与命令传递
说到消息,在MFC中,“最熟悉的神秘”可算是消息映射,那是我们刚开始接触MFC时就要面对的东西.有过SDK编程经验的朋友转到MFC编程的时候,一下子觉得什么都变了样.特别是窗口消息及对消息的处理跟以前 ...
-
第3章 MFC框架程序剖析
参考: https://blog.csdn.net/u014162133/article/details/46573873 1. 2.MFC简介:MFC(Microsoft Foundation Cl ...
随机推荐
-
11.12模拟考T1(可持续优化)PS:神奇的东西
1.数列操作 (array.pas/c/cpp) [问题描述] 现在有一个数列,最初包含0个数.现在要对数列操作n次,操作有3类. 1) a k,在数列的最后插入一个整数k 2) s 将最近插入的 ...
-
[转载]android的消息处理机制(图+源码分析)——Looper,Handler,Message
2013-12-18 14:17:33 转载自: http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html 请跳转到转载 ...
-
axure注册码
ahjesus Axure RP 7.0注册码 用户名:axureuser 序列号:8wFfIX7a8hHq6yAy6T8zCz5R0NBKeVxo9IKu+kgKh79FL6IyPD6lK7G6+t ...
-
SharePoint Server 2010安装图解
SharePoint Server 2010作为MOSS 2007的升级版本,自从2009年底发布Beta版本以来就备受关注,网络上已经出现了很多相关的文章,其中也不乏中文的信息. 最近SharePo ...
-
Mac IDEA插件——protobuf 插件
最近在搞PB的版本的升级,历史的PB的版本是2.4,现在是打算升级到3.2,当面PB的版本肯定有很多变化了,就不再这里多说了,这里重点说一说,采用IDEA的插件方便执行PB的文件的JAVA编译,这样的 ...
-
1.如何使用vbs打开网页并且登陆
例如自动打开繁星的网页并且登录 Private Sub CommandButton1_Click() Dim ie As Object Set ie = CreateObject("Inte ...
-
[ASP.NET MVC] Razor 布局
整体视图模板 View模板会先找到对应的controller文件,再找此文件下的Shared文件夹. 比如项目最外层的View/Shared 目录下有一个_Layout.cshtml模板页,有这样代码 ...
-
python3打包成exe---pyinstaller方法
前言: 主要介绍python3的pyinstaller打包方法 pyinstaller安装参考地址:http://www.pyinstaller.org/ pywin32的下载地址:https://s ...
-
py-faster-rcnn + opencv3.0.0 + ubuntu16.04配置(CPU模式)
最近开始做行人检测,因此开始接触faster-rcnn,这里贴上配置教程(亲测可行),不过是基于cpu的,蓝瘦... 参考博客:http://www.tuicool.com/articles/nYJr ...
-
位运算骚操作 Part 1
▶ 原文标题<Bit Twiddling Hacks>,地址:https://graphics.stanford.edu/~seander/bithacks.html ▶ 额外参考资料:h ...