MFC程序执行过程深入剖析

本文较为详细的分析了VC++程序设计的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()

感兴趣的朋友可以采用断点调试测试一下SDI程序的执行流程,以加深对MFC运行原理的理解,从而更好的掌握Windows程序设计。

(0)

相关推荐

  • MFC程序对文件的处理方法

    对文件的处理是MFC程序设计中非常常见的应用.本文就以实例形式做一简单叙述.具体方法如下: 1.CFileDialog的应用 格式如下: CFileDialog::CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter =

  • MFC实现全屏功能代码实例

    windows应用程序中有很多的播放器都有快捷键控制窗口以全屏幕的方式显示.MFC实现给应用程序加上全屏幕的功能,并不需要很多的代码,比如给一个基于对话框的应用程序加上全屏功能只需要以下少量代码就可以实现了. 实现代码如下所示: void CFullScreenDlg::FullScreenView(void) { RECT rectDesktop; WINDOWPLACEMENT wpNew; if (!IsFullScreen()) { // We'll need these to rest

  • MFC绘制不规则窗体的方法

    本文实例讲述了MFC 绘制不规则窗体的方法.分享给大家供大家参考.具体分析如下: 实现过程: 1.首先创建基于DLG的MFC应用程序,命名为:tryBGDlg,并将DLG的属性设置为:Title Bar :False ,其它设置不变 2.制作两幅图像,其中的一幅黑白图像,是根据播放器外观来制作的,其中白色区域是要保留的最终在桌面上显示的区域.将这两幅图像添加到工程中,第一个ID号设置为IDB_INTERFACE,第二个ID号设置为:IDB_MASK 3.在CtryBGDlg类中添加一个在函数:

  • MFC创建右键弹出菜单的方法

    本文实例讲述了MFC创建右键弹出菜单的方法.分享给大家供大家参考.具体实现方法如下: ①.添加一个菜单资源,ID为IDM_RIGHTMENU.因为在显示右键菜单时顶级菜单是不显示的,所以可以给它设置任意文本. ②.给视类添加WM_RBUTTONDOWN消息,在该消息中处理右键弹出菜单.因为视类窗口始终覆盖在框架窗口之上,框架窗口接收不到鼠标消息,所以由视类捕获WM_RBUTTONDOWN消息. 复制代码 代码如下: void CMenuView::OnRButtonDown(UINT nFlag

  • MFC命名规则汇总

    本文汇总了MFC中消息.控件.对话框等等的命名规则,作为初学者应详细了解并遵守这类规则.详细规则如下所示: 一.MFC中ID 编号原则: IDC_:控件的ID命名前缀(Control) IDM_:菜单的ID命名前缀(Menu) IDD_:对话框的ID命名前缀(Dialog) IDR_:资源的ID命名前缀(Resource) IDS_:字符串的ID命名前缀(String) IDB_:位图资源的ID命名前缀(Bitmap) 二.MFC系统消息前缀小集 ABM        应用程序桌面工具条appl

  • MFC设置对话框焦点的方法简述

    本文简单讲述了MFC设置对话框焦点的方法,分享给大家供大家参考.具体实现方法如下: 具体的方法有两种: 1. 设置对话框控件的tab order. 按Ctrl+D即可看见.将需要被设置到焦点的空间的tab order设为1. 2. 对话框的OnInitDialog返回FALSE.解释如下:(摘抄至msdn)   If OnInitDialog returns nonzero, Windows sets the input focus to the first control in the dia

  • MFC自定义消息的实现方法

    一.概述: 消息机制是windows程序的典型运行机制,在MFC中有很多已经封装好了的消息,如WM_BTN**等.但是在有些特殊情况下我们需要自定义一些消息去完成一些我们所需要的功能,这时候MFC的向导不能帮助我们做到这一点.对此,我们可以通过添加相应的代码去完成这个功能. 二.实现方法: 添加自定义消息操作如下: 1. 建立MFC工程,如基于对话框的应用程序,Test. 2. 在资源中添加要处理的消息的值,即在CTestDlg.h中添加 如下代码. (因为很多MFC的消息是在WM_USER内的

  • 构建mfc窗体的简单示例

    复制代码 代码如下: #include<afxwin.h>//包含MFC头文件//从MFC的主要框架窗体派生用户窗体类class CMyWnd:public CFrameWnd{public: CMyWnd(LPCTSTR szTitle) {  //调用父类Create函数创建窗体  Create(NULL,szTitle); }};//从MFC的应用程序派生用户程序类class CMyApp:public CWinApp{public: virtual BOOL InitInstance(

  • MFC程序执行过程深入剖析

    本文较为详细的分析了VC++程序设计的MFC程序执行过程,有助于加深对MFC程序运行原理的理解.分享给大家供大家参考之用.具体分析如下: 一 MFC程序执行过程剖析 1)我们知道在WIN32API程序当中,程序的入口为WinMain函数,在这个函数当中我们完成注册窗口类,创建窗口,进入消息循环,最后由操作系统根据发送到程序窗口的消息调用程序的窗口函数.而在MFC程序当中我们不在能找到类似WinMain这样的程序入口,取而代之的是一系列派生类的声明和定义以及一个冲CWinApp类派生而来的类的全局

  • Java程序执行过程及内存机制详解

    本讲将介绍Java代码是如何一步步运行起来的,其中涉及的编译器,类加载器,字节码校验器,解释器和JIT编译器在整个过程中是发挥着怎样的作用.此外还会介绍Java程序所占用的内存是被如何管理的:堆.栈和方法区都各自负责存储哪些内容.最后用一小块代码示例来帮助理解Java程序运行时内存的变化. Java程序执行过程 步骤 1: 写源代码,源代码将以.java的文件格式保存在电脑硬盘中. 步骤 2: 编译器(compiler)检查是否存在编译期错误(例如缺少分号,关键字拼写错误等).若通过检测,编译器

  • Python字节码与程序执行过程详解

    目录 问题: 1. 执行过程 2. 字节码 3. 源码编译 三种编译模式: 4. PyCodeObject 5. 反编译 6. pyc 问题: 我们每天都要编写一些Python程序,或者用来处理一些文本,或者是做一些系统管理工作.程序写好后,只需要敲下python命令,便可将程序启动起来并开始执行: $ python some-program.py 那么,一个文本形式的.py文件,是如何一步步转换为能够被CPU执行的机器指令的呢?此外,程序执行过程中可能会有.pyc文件生成,这些文件又有什么作用

  • php-fpm重启导致的程序执行中断问题详解

    背景和初步排查 订单业务对账时报警了,有笔订单在我们自己的mongo库里没有找到 业务接口  /3/xx/vgift/send 调用礼物系统  sendPresent 接口完成送礼, 之后写mongo,但是php error log 里却查不到任何mongo异常日志 写mongo没有异常,但是库里却没记录,推断只有2个可能 1是error log 丢日志了 2是程序执行过程中操作完sendPresent后down掉了,导致没写入mongo -第一个情况工作多年的经验来看应该不至于,那就先根据第二

  • 详解微信小程序动画Animation执行过程

    前言 因官方文档描述不清晰,本文主要介绍微信小程序动画 实现过程 / 实现方式. 实现过程 推荐你对照 官方文档 来看本文章,这样更有利于理解. 简单来说,整个动画实现过程就三步: 创建一个动画实例 animation. 调用实例的方法来描述动画. 最后通过动画实例的 export 方法导出动画数据传递给组件的 animation 属性. 前两步是定义一个动画并设置都要干什么,然后把这个设置好的 "规则" 扔给界面上的某个元素,让它按照这个规则执行. 当然如果有多个元素的 animat

  • 如何理解PHP程序执行的过程原理

    概述 Web环境我们假设为Apache.在编译PHP的时候,为了能够让Apache支持PHP,我们会生成一个mod_php5.so的模块.Apache加载这个模块,在url访问.php文件的时候,就会转给mod_php5.so模块来处理. 这个就是我们常说的SAPI.英文名字是:Server Application Programming Interface.SAPI其实是一个统称,其下有 ISAPI,CLI SAPI,CGI等.有了它,就可以很容易的跟其他东西交互,比如APACHE,IIS,C

  • MyBatis核心源码深度剖析SQL语句执行过程

    目录 1 SQL语句的执行过程介绍 2 SQL执行的入口分析 2.1 为Mapper接口创建代理对象 2.2 执行代理逻辑 3 查询语句的执行过程分析 3.1 selectOne方法分析 3.2 sql获取 3.3 参数设置 3.4 SQL执行和结果集的封装 4 更新语句的执行过程分析 4.1 sqlsession增删改方法分析 4.2 sql获取 4.3 参数设置 4.4 SQL执行 5 小结 1 SQL语句的执行过程介绍 MyBatis核心执行组件: 2 SQL执行的入口分析 2.1 为Ma

  • MFC程序中使用QT开发界面的实现步骤

    目录 添加QT依赖 添加信号槽机制 添加qt界面 配置元编译过程 一些问题的处理 测试信号槽 使用qt designer 设计界面 如果你有一个现成的MFC项目在做维护,但是你厌倦了使用MFC繁琐的操作来做界面美化,或者你需要在这个项目中用到QT里面好用的某些功能:亦或者是你需要使用某些只能在MFC中使用的组件,但是界面这部分已经用QT做好了.那么这篇文章可能可以帮助到你 演示环境使用Visual Studio 2019 + QT5.12.8 版本 添加QT依赖 首先创建一个基于对话框的MFC工

  • 探讨JavaScript语句的执行过程

    废话不多说,直奔主题了.javascript的运行原理总结如下: 1.按照html文档流顺序执行javascript代码 浏览器是按照文档流从上到下逐步解析页面结构和信息的,javascript代码作为嵌入的脚本作为html文档的组成部分,所以javascript代码在加载时的执行顺序也是根据脚本标签<script>的出现顺序来确定的. 如果通过脚本标签<script>的src属性来引入外部.js文件,那么它也将按照其语句出现的顺序来执行,而且执行过程是文档加载的一部分.不会因为是

  • 游览器中javascript的执行过程(图文)

    1. 大多数游览器的组件构成如图      在最底层的三个组件分别是网络,UI后端和js解释器.作用如下: (1)网络- 用来完成网络调用,例如http请求,它具有平台无关的接口,可以在不同平台上工作 (2)UI 后端- 用来绘制类似组合选择框及对话框等基本组件,具有不特定于某个平台的通用接口,底层使用操作系统的用户接口 (3)JS解释器- 用来解释执行JS代码 ps:上图和知识点主要来自<HOW BROWSERS WORK: BEHIND THE SCENES OF MODERN WEB BR

随机推荐