今天给新来的同事讲MFC的消息循环,诸如什么时候启动的,如何循环的,消息是如何传递的等等,结果收效甚微,原因是他们连基本的程序产生到程序运行结束的基本过程都不清楚,所以我决定先梳理一个程序从生到死经历的过程,再讲消息传递。
调用CreateProcess创建一个进程内核对象
↓
系统为进程创建一个私有地址空间(虚拟地址空间)
↓
在进程地址空间保留区域将exe文件和需要的DLL映射到进程的地址空间
↓
找到启动地址(启动函数),开始执行exe文件的启动代码
↓
创建主线程
↓
调用C/C++运行期启动函数(_tmainCRTStartup,启动函数的功能在本文后面描述)
现在将启动函数的功能归纳如下:
1, 检索指向新进程的完整命令行的指针。
2,检索指向新进程的环境变量的指针。
3,对C / C + +运行期的全局变量进行初始化。如果包含了S t d L i b . h 文件,代码就能访问这些变量。表4 - 1 列出了这些变量。
4,对C 运行期内存单元分配函数(m a l l o c 和c a l l o c )和其他低层输入/输出例程使用的内存栈进行初始化。
5,为所有全局和静态C + +类对象调用构造函数。
↓
启动函数的初始化操作完成后,C / C + +启动函数就调用应用程序的进入点函数(wWinMain)
↓
调用AfxWinMain
↓
在AfxWinMain中初始化MFC(AfxWinInit)
↓
做应用程序初始化,包括创建主窗口(调用主线程的InitInstance)
↓
创建成功,进入消息循环(调用主线程的Run)
↓
Run从消息队列中取得消息,转换消息,派发消息到各个窗口。
↓
当进入点函数返回时,启动函数便调用C 运行期的e x i t 函数,将返回值(n M a i n R e t Va l )传递给它。
E x i t 函数负责下面的操作:
1, 调用由_onexit函数的调用而注册的任何函数。
2,为所有全局的和静态的C++类对象调用析构函数。
3,调用操作系统的ExitProcess函数,将nMainRetVal传递给它。这使得该操作系统能够撤消进程并设置它的e x i t 代码。
↓
线程结束
↓
进程结束