MFC 学习笔记(一):MFC单文档程序运行流程梳理与总结

MFC 学习笔记(一):MFC单文档程序运行流程梳理与总结

1.MFC单文档程序运行流程

1.首先利用全局变量对象 theApp 启动应用程序
(这是因为这个全局对象,基类CWinApp中 this 的指针才能指向这个对象。)

2.调用全局应用程序对象 theApp 的构造函数
(需要先调用其基类CWinApp的构造函数,
完成应用程序的一些初始化工作,并将应用程序对象的指针保存起来。)

3.进入WinMain函数
(CWinApp的构造函数中调用 AfxWinMain 函数)

4.调用虚函数:InitInstance()
(利用在AfxWinMain函数中可以获取子类的指针,并调用InitInstance函数 如下图)
(③ 指令实际上调用的是子类(CTestApp)的InitInstance函数)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.子类(CTestApp)中的InitInstance()函数完成应用程序的一些初始化工作
(包括窗口类的注册,创建,窗口的显示和更新。
期间会多次调用CreateEX函数,因为一个单文档MFC应用程序有多个窗口,包括框架窗口.工具条.状态条等。)

初始化举例
例如:
1)CTestApp::Initstance()函数中定义了一个单文档模板对象指针,
2)该对象就把文档类对象、框架类对象、视窗类对象有机地组织在一起,
3)接着利用AddDocTemplate函数把这个单文档模板添加到文档模板中,从而把这个三个类组织成为一个整体,如图:
在这里插入图片描述
又如:
1)m_pMainWnd 表示指向程序框架窗口的指针(CMainFrame)
2)通过该指针显示和更新程序框架窗口
在这里插入图片描述

4.进入消息循环。
上图:pThread->Run()
(虽然也设置了默认的窗口过程函数,但是,MFC应用程序实际上是采用消息映射机制来处理各种消息。当收到WM_QUIT消息时,退出消息循环,程序结束。)

参考博客:
https://blog.csdn.net/c_base_jin/article/details/52345563

PS:
1.Afx前缀的函数代表应用程序框架(Application Framework)函数,属于全局函数,它们可以在程序的任何地方被调用。
2.以域作用符“::”开始的表示的函数,表明该函数是一个全局函数。

2.总结补充

1.由于theApp是全局对象,因此会在进入WinMain()之前完成构造
theApp的构造动作会导致一系列的对theApp的初始化动作:

pModuleState->m_pCurrentWinApp = this;

2.接着进入WinMain()
WinMain()(_tWinMain(),这是为了UniCode而准备的一个宏)直接调用AfxWinMain(),AfxWinMain()发挥真正应该由WinMain()发挥的作用,它取得theApp,然后必须先调用AfxWinInit(),再用取得的指向theApp的指针pApp调用InitApplication()、InitInstance()和Run(),最后调用AfxWinTerm()终止程序。
即AfxWinMain()中的动作相当于:

AfxWinInit();
CWinApp::InitApplication();
CMyWinApp::InitInstance();
CWinApp::Run();

3.AfxWinInit()做什么?
首先将WinMain()传进来的四个参数保留在theApp的成员变量里。
调用AfxInitThread(),此函数又调用::SetWindowHookEx(),不知干啥。另外此函数还将消息队列尽量加大到96。

4.CWinApp::InitApplication()做什么?
会做一些与CDocManager()和Document Template相关的工作,是MFC的内部管理范畴。

5.CMyWinApp::InitInstance()做什么?
终于来到了我们可以改写的InitInstance(),这个函数是CWinApp的虚函数,CMyWinApp通常要改写它,其实在CWinApp中InitInstance()是一个空函数。
InitInstance()的动作如下:

m_pMainWnd = new CMyFrameWnd();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();

【(InitInstance()首先会创建一个CMyFrameWnd对象,并将指针保留在m_pMainWnd中。这个CMyFrameWnd对象的创建过程就会导致主窗口的登记和建立,因为CFrameWnd的构造函数中会调用Create()函数,而这个函数负责创建窗口(通过调用CreateWindowEx),窗口风格使用最常见的WS_OVERLAPPEDWINDOW。
但是这仅仅是创建窗口,窗口类注册的动作(必须先于窗口的创建)又发生在哪里呢?
其实Create()的调用会导致CWnd::CreateEx()的调用,此函数才是真正调用CreateWindowEx()创建窗口者,在调用CreateWindowEx()之前会调用CFrameWnd::PreCreateWindow(),此函数判断传入的窗口类名lpszClassName是否为NULL,若是,则通过一系列的调用(非常之绕)为其注册默认窗口类别。由于每个窗口创建过程中PreCreateWindow()都只在创建之前被调用,因此窗口的注册大多在创建之前发生。CWnd及其派生类的各个不同)

PreCreateWindow()函数为不同窗口指定了不同的默认窗口类别:
CWnd使用的窗口类别是_afxWnd
CFrameWnd和CMDIChildWnd使用的窗口类别是_afxWndFrameOrView
CMDIFrameWnd使用的窗口类别是_afxWndMDIFrame】

综上,InitInstance()中的第一个动作――创建CMyFrameWnd对象――完成了窗口的创建。之后的动作就很直观了,ShowWindow()显示窗口,UpdateWindow()发送WM_PAINT消息更新窗口。

6.回到AfxWinMain()中,接下来执行的是CWinApp::Run()。
Run()所做的正是维持程序运行的“消息循环”。CWinApp::Run()会调用CWinThread::Run(),此Run()中有消息循环,通过PumpMessage()得到并转发消息(调用::GetMessage()、::TranslateMessage()、::DispatchMessage(),一如SDK!)。
**但是转发到哪里呢?窗口函数呢?**原来在MFC为我们注册默认窗口类的时候已经指定了窗口函数为DefWindowProc(),但是真正处理消息的又不是它,而是一个全局函数AfxWndProc(),这是MFC通过hook和subclassing技术做到的,暂且不提。

综上,MFC为我们的程序提供了WinMain()、注册了窗口类、创建了窗口甚至提供了窗口函数,留给我们做的只是写出响应消息的处理函数,而这些消息和处理函数如何对应起来还要靠MFC六大关键技术之一的Message Mapping(消息映射)消息映射机制的目的是首先搭建起消息和消息处理函数对应的大框架,再通过宏的机制让程序员能够方便地添加消息和消息处理函数之间的对应关系。

7.在程序运行的过程中,程序不断地由消息所驱动,直到用户动作发出了WM_CLOSE消息,程序即将关闭
过程是:由于CMyFrameWnd没有设立WM_CLOSE的处理函数,因此该消息被送往预设处理函数,预设函数对WM_CLOSE的处理是调用::DestroyWindow(),进而发送WM_DESTROY消息,WM_DESTROY消息同样会被送到预设处理函数,预设函数对WM_DESTROY的处理方法是调用::PostQuitMessage(),发送WM_QUIT,CWinApp::Run()在收到WM_QUIT后会结束自己的消息循环,并调用ExitInstance(),这是CWinApp的虚函数,可被CMyWinApp改写,调用过此函数后,回到AfxWinMain()中调用AfxWinTerm()结束程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/491304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对话清华教授孙茂松:第三代人工智能要处理“可解释性”问题

来源:澎湃新闻正如人类会综合利用视觉、听觉、触觉、语言等信息,让人工智能(AI)从多角度、多模态、多学科学习自然语言也是清华大学人工智能研究院的目标与任务。2019年7月1日,清华大学人工智能研究院第八个研究中心&a…

验证gpu版pytorch是否可用

import torchtorch.cuda.is_available() Truetorch.cuda.current_device() 0torch.cuda.device(0) <torch.cuda.device object at 0x0000023034332438>torch.cuda.device_count() 1torch.cuda.get_device_name(0) GeForce GTX 1660

oracle instr函数

语法&#xff1a;instr( fatherstr, sonstr [, start_position [, matchtimes ] ] )fatherstr&#xff1a;父字符串。要在此字符串中查找子字符串的位置。sonstr&#xff1a;要在fatherstr中查找的字符串. start_position&#xff1a;代表从fatherstr開始查找的的開始位置。此參…

QT学习笔记(一):VS2013 +QT 5.8 运行、编译问题解决

QT学习笔记&#xff08;一&#xff09;&#xff1a;VS2013 QT 5.8 运行、编译问题解决 jom: E:\C\4.QT\HelloWord\Makefile.Debug [debug\moc_predefs.h] Error 1 ‘cl’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 jom: E:\C\4.QT\HelloWord\Makefile…

使用清华镜像安装pytorch失败的解决方法

首先添加清华镜像至Anaconda仓库&#xff1a; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --set show_channel_urls yes …

受精卵或非“生命起始”?网友:教材是不是要改了……

来源&#xff1a;中国新闻网一直以来&#xff0c;科学家们都认为&#xff0c;精卵结合受精以后就是生命。但是&#xff0c;最近中美胚胎学家的一项最新联合研究成果表明&#xff0c;人类受精卵存在两套独立纺锤体&#xff0c;即从精卵结合到发生第一次有丝分裂期间&#xff0c;…

QT学习笔记(二):QT MinGW 和 MSVC 编译方式

QT学习笔记&#xff08;二&#xff09;&#xff1a;QT MinGW 和 MSVC 编译方式 Qt 中有两种方式编译&#xff1a;一种是MinGW &#xff0c;另一种MSVC&#xff0c;是使用两种不同的编译器。 1、MSVC是指微软的VC编译器&#xff1b; 2、MingGW是指是Minimalist GNU on Window…

利用Excel进行成对(配对)T检验

首先在Excel中添加数据分析工具 https://jingyan.baidu.com/article/c275f6ba74b69ee33d7567c8.html 在Excel添加要分析的两组数据&#xff1a; 点击数据——>数据分析&#xff0c;选择t-检验&#xff1a;平均值的成对二样本分析&#xff0c;分别选取两组要分析的数据和输…

垃圾要分类!我们的大脑如何处理垃圾呢?

来源&#xff1a;中国生物技术网最近&#xff0c;垃圾分类已经成了热点话题&#xff0c;但实行这一举措的最终目的还是为了保护我们赖以生存的地球环境。同样&#xff0c;大脑为了维持健康&#xff0c;也专门有一套自己的“垃圾清除系统”&#xff0c;即glymphatic&#xff08;…

Scala模式匹配和类型系统

Scala模式匹配和类型系统 1.模式匹配比java中的switch case强大很多&#xff0c;除了值&#xff0c;类型&#xff0c;集合等进行匹配&#xff0c;最常见的Case class进行匹配&#xff0c;Master.scala有大量的模式匹配。 Case "_"表示不满足上面的所有情况的体验&…

QT学习笔记(三):Qt软件打包发布(QT5.8 _msvc2013_64+Win10_64)

QT学习笔记&#xff08;三&#xff09;&#xff1a;Qt软件打包发布&#xff08;QT5.8 _msvc2013_64Win10_64&#xff09;1.编译方式介绍&#xff1a;2.动态编译方式打包发布QT程序&#xff1a;方法一&#xff1a;手动复制方法二&#xff1a;使用工具问题&解决&#xff1a;环…

贝叶斯用于文档分类

from numpy import *def loadDataSet():# 词条切分后的文档集合&#xff0c;列表每一行代表一个文档postingList [[my, dog, has, flea, please],[not, take, him, to, dog, stupid],[my, is, cute, love, him],[stop, posting, stupid, worthless, garbage],[my, licks, my, …

使用pt-heartbeat检测主从复制延迟

不要用SECONDS_BEHIND_MASTER来衡量MYSQL主备的延迟时间&#xff0c;原因如下&#xff1a; A&#xff1a;备库Seconds_behand_master值是通过将服务器当前的时间戳与二进制日志中的事件的时间戳对比得到的&#xff0c;所以只有在执行事件时才能报告延迟 B&#xff1a;如果备库复…

麦肯锡报告摘译:未来成功城市的14个特征

来源&#xff1a;TOP产业办公研究院【前言】&#xff1a;本文摘译自麦肯锡发布的一份研究报告。报告来源&#xff1a;McKinsey&Company Report: Thriving amid turbulence: Imagining the cities of the future. Authored by Jonathan Woetzel , Vineet Rajadhyaksha , Joe…

编程关键词介绍...

编程关键词介绍&#xff1a; gcc是GUN compiler Collection (GUN编译器套件)&#xff0c;也可以简单理解为编译器&#xff0c;他可以编译多种语言。 GNU是基于Unix开发设计&#xff0c;并且是与Unix兼容的操作系统&#xff0c;该项目由Richard Stallman在1983年创建&#xff…

MATLAB编辑GUI界面

在命令窗口输入&#xff1a;guide 即可进入编辑 若要在GUI界面的一个面板上显示程序中随意给定的字符&#xff1a; 首先创建一个“可编辑文本”&#xff08;位于左侧工具栏&#xff09;&#xff1a; 双击该面板&#xff0c;弹出该面板的工具栏&#xff0c;设置“string”&am…

单个神经元不可靠!这项新研究推翻以往认知,感知的最大限制在于解码过程...

来源&#xff1a;凹非寺“单个神经元不可靠&#xff01;”一项关于神经元的研究&#xff0c;让众人看嗨了。这项研究通过在小鼠身上做实验&#xff0c;先展示了神经元“不靠谱”的一面&#xff1a;单个神经元两次对相同视觉刺激的反应&#xff0c;竟然是不一样的。对于神经元的…

(转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在

问题描述&#xff1a;在用vs生成MVC时若使用Internet应用程序为模版&#xff0c;项目建好后重新编译下无法通过&#xff0c;弹出错误&#xff1a; 解决方案&#xff1a;问题出来后&#xff0c;询问了身边很多人都是一头雾水&#xff0c;于是乎各种谷歌和百度&#xff0c;还好功…

QT学习笔记(四):Qt5+MSVC编译 中文字符显示乱码问题解决

QT学习笔记&#xff08;四&#xff09;&#xff1a;Qt5MSVC编译 中文字符显示乱码问题解决问题&#xff1a;1、解决方法一&#xff1a;2、解决方法二&#xff1a;3、解决方法三&#xff1a;4、解决方法四&#xff1a;结果显示&#xff1a;Qt5MSVC编译 中文字符显示乱码。 现在为…