程序流程

1.先全局变量theapp;

2.AfxWinMain,包括执行InitApplication、InitInstance(一般会重写)、Run

3.在InitInstance 会create 窗口,通过LoadFrame(多文档,只创建CMDIFrameWnd,至于cdoc、CMDIChildWnd、cview是执行ProcessShellCommand创建的)或者 ProcessShellCommand(单文档,同时创建cdoc、cframe、cview)。‘’

其实多文档也执行ProcessShellCommand。ProcessShellCommand用来创建先cdoc、再frame.同时在创建frame的时候,通过调用CFrameWnd::Create函数,发出WM_CREATE消息。响应CMainFrame::OnCreate函数,

从而响应CFrameWnd::CreateView,执行CreateView,创建cview.

单文档:

CMFCApp::InitInstance()  -> ProcessShellCommand -> OnFileNew()->CDocManager::OnFileNew()->OpenDocumentFile (因为是虚函数,所以执行子类的CSingleDocTemplate::OpenDocumentFile)  ->CreateNewDocument(创建CDocument对象)  ->CreateNewFrame ->CFrameWnd::LoadFrame(因为是虚函数,会先执行CMainFrame::LoadFrame,最后执行CFrameWnd::LoadFrame)->CFrameWnd::GetIconWndClass ->PreCreateWindow(因为是虚函数,会先执行CMainFrame::PreCreateWindow,最后执行CFrameWnd::PreCreateWindow)->AfxRegisterWndClass ->AfxRegisterClass(注册窗口,其中回调函数是DefWindowProc) ->CFrameWnd::Create ->CWnd::CreateEx ->PreCreateWindow(又一次,因为是虚函数,会执行CMainFrame::PreCreateWindow) ->AfxHookWindowCreate(通过SetWindowsHookEx钩子函数->_AfxCbtFilterHook ->AfxGetAfxWndProc ->AfxWndProc ->AfxCallWndProc ->WindowProc) ->CreateWindowEx(真正创建窗口,会发出WM_CREATE,从而进入到CMainFrame::OnCreate该函数创建cview、工具栏、状态栏、属性栏等。)->CFrameWndEx::OnCreate ->CFrameWnd::OnCreate ->CFrameWnd::OnCreateHelper ->CFrameWnd::OnCreateClient ->CWnd* CFrameWnd::CreateView ->CWnd::Create (和回到上面Create 一样了) ->CWnd::CreateEx ->AfxHookWindowCreate ->CreateWindowEx

上面这些函数被执行完后,回到winapp的InitInstance,执行下面的ShowWindow和UpdateWindow。

InitInstance执行完后,回到afxwinmain。执行run,进入消息循环。

即下面的部分具体解读

其实在CWnd::Create函数中也会先调

1.CWnd::Create -> CWnd::CreateEx-> PreCreateWindow ->AfxEndDeferRegisterClass ->AfxRegisterClass 进行窗口类注册

2. CFrameWnd::Create -> CWnd::CreateEx -> AfxHookWindowCreate -> ::SetWindowsHookEx(WH_CBT, _AfxCbtFilterHook, NULL, ::GetCurrentThreadId()); ->CALLBACK _AfxCbtFilterHook -> AfxGetAfxWndProc ->CALLBACK AfxWndProc ->AfxCallWndProc

->WindowProc                  所以可以在cwnd类的虚函数WindowProc 重写实现对应的功能

3.最后调用CreateWindowEx进行真正创建窗口。创建成功后,指向一个值的指针,该值传递给窗口WM_CREATE消息。该值通过在lParam参数中的CREATESTRUCT结构传递。如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。简单一句话:窗口产生之际发出WM_CREATE消息,响应afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);即执行CMainFrame::OnCreate,在该函数创建cview、工具栏、状态栏、属性栏等。->CMainFrame::OnCreate ->CMDIFrameWnd::OnCreate->CFrameWnd::OnCreateHelper

在MFC 单文档或者多文档模式CMainFrame::Create是通过CMainFrame::LoadFrame调用起来的。通过ProcessShellCommand 从而生成cdoc、cview等类。而LoadFrame是在应用程序类winapp的InitInstance函数被调用。

所以在整个CMainFrame类的执行先后顺序是:LoadFrame -> Create ->PreCreateWindow -> WindowProc -> OnCreate

上面这些函数被执行完后,回到winapp的InitInstance,执行下面的ShowWindow和UpdateWindow。

InitInstance执行完后,回到afxwinmain。执行run,进入消息循环。

说明创建每个cwnd类,都会创建钩子函数,回调函数。

多文档

CdwdApp::InitInstance -> CMainFrame::LoadFrame ->CMDIFrameWndEx::LoadFrame -> CMDIFrameWnd::LoadFrame ->CFrameWnd::LoadFrame(其实这部分和上面的单文档一样的)-> CFrameWnd::GetIconWndClass ->PreCreateWindow(因为是虚函数,会先执行CMainFrame::PreCreateWindow,最后执行CFrameWnd::PreCreateWindow)->>AfxRegisterWndClass ->AfxRegisterClass(注册窗口,其中回调函数是DefWindowProc) ->CFrameWnd::Create ->CWnd::CreateEx->PreCreateWindow(又一次,因为是虚函数,会执行CMainFrame::PreCreateWindow)-> AfxHookWindowCreate(通过SetWindowsHookEx钩子函数->_AfxCbtFilterHook ->AfxGetAfxWndProc ->AfxWndProc ->DefWindowProc) ->CreateWindowEx(真正创建窗口,会发出WM_CREATE,从而进入到CMainFrame::OnCreate该函数创建cview、工具栏、状态栏、属性栏等。->CMainFrame::OnCreate ->CMDIFrameWndEx::OnCreate -> CFrameWnd::OnCreate -> CFrameWnd::OnCreateHelper -> OnCreateClient(因为是虚函数,实际执行CMDIFrameWndEx::OnCreateClient,也是多文档和单文档的区别,因为在单文档子类没有重写该虚函数) - >CMDIFrameWnd::OnCreateClient -> CMDIFrameWnd::CreateClient ->CreateWindowEx(穿件mdi 客户区m_hWndMDIClient,) ->ProcessShellCommand(参考单文档) ->CWinApp::OnFileNew->OpenDocumentFile(因为该函数是虚函数,实际执行的是CMultiDocTemplate::OpenDocumentFile)->CreateNewDocument(创建文档)-> CDocTemplate::CreateNewFrame ->LoadFrame(因为其是虚函数,实际执行CMDIChildWnd::LoadFrame,也是和单文档的区别) -> CFrameWnd::GetIconWndClass->PreCreateWindow(该函数为虚函数,实际执行CChildFrame::PreCreateWindow)  ->AfxRegisterWndClass ->AfxRegisterClass  ->Create (该函数为虚函数,实际执行CMDIChildWnd::Create) ->PreCreateWindow (又一次,该函数为虚函数,实际执行CChildFrame::PreCreateWindow) ->AfxHookWindowCreate(通过SetWindowsHookEx钩子函数->_AfxCbtFilterHook ->AfxGetAfxWndProc ->AfxWndProc ->AfxCallWndProc ->WindowProc)->SendMessage(WM_MDICREATE) ->CMDIChildWnd::OnCreate(在SendMessage函数到OnCreate之间,中间经历很多消息映射、命令传递等操作,即执行WindowProc回调函数)->CFrameWnd::OnCreateHelper ->CFrameWnd::OnCreateClient ->CFrameWnd::CreateView ->CWnd::Create ->CWnd::CreateEx ->AfxHookWindowCreate(通过SetWindowsHookEx钩子函数->_AfxCbtFilterHook ->AfxGetAfxWndProc ->AfxWndProc ->AfxCallWndProc ->WindowProc)-> CreateWindowEx

document template

document/view

程序每打开一份文件(数据),就产生3份对象。

1.document

2.view //外围必须封装一个外框窗口作为舞台

3.CMDIChildWnd(作为view 的外框窗口),当是多文档模式时。如果是单文档则直接是CFrameWnd。

所以多文档的流程是

在cview类中,消息函数onpaint调用ondraw虚函数。

CDocument:

1.void UpdateAllViews(CView* pSender, LPARAM lHint = 0L,  CObject* pHint = NULL);   //调用UpdateAllViews会执行CView::OnUpdate ->Invalidate ->产生wm_paint -> onpaint ->ondraw

2.virtual BOOL OnNewDocument();  //该函数是在OpenDocumentFile 中创建好文档、框架窗口、视图后,被调用的。

CView:

1. virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);   //利用Invalidate(TRUE)把窗口设置为重绘区(无效区)并产生wm_paint,会执行onpaint,执行ondraw.

2.virtual void OnInitialUpdate(); // called first time after construct   构造函数生成本类的对象,但没有产生窗口,OnCreate后窗口产生, 然后才是视图的OnInitialUpDate,一般在这里对视图的显示做初始化.然后再执行OnDraw

3.virtual void OnDraw(CDC* pDC) = 0;  //如果想在ondraw前,调整dc,可以先调用重写onpreparedc,再调用OnDraw。

4. CDocument* GetDocument() const;

5.CFrameWnd* GetParentFrame() const;

CFrameWnd:

1.CView* GetActiveView() const;           // active view or NULL

2.virtual CDocument* GetActiveDocument();

前面说doc和view是一一对应,现在又说一个doc可以对应多个view?

理解:确实一个doc对应一个view,并且是通过CMultiDocTemplate来进行管理维护,那么如果想一个doc对应多个view,

1.需要创建多个CMultiDocTemplate对象,并且指定RUNTIME_CLASS都是用一个doc,而使用不同的view。

2.因为应用程序开始默认只执行一次OpenDocumentFile,那么即只创建一次doc、frame、view.并且需要改造重写OnFileNew函数,让第一个CMultiDocTemplate对象执行OpenDocumentFile。

3.这时候就不需要再创建doc,只需要创建frame(view也在该过程创建的)。所以可以重写cdoc::OnNewDocument(),调用CreateNewFrame。

所以就可以一个doc可以对应多个view。

手把手分析 mfc 程序创建 代码执行流程相关推荐

  1. 「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析

    「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析 前言 一.我的开发环境 二.使用 Vue CLI (Vue 脚手架)快速搭建项目 三.初始项目的目录结构 ...

  2. 一篇文章教会你Python网络爬虫程序的基本执行流程

    网络爬虫是指在互联网上自动爬取网站内容信息的程序,也被称作网络蜘蛛或网络机器人.大型的爬虫程序被广泛应用于搜索引擎.数据挖掘等领域,个人用户或企业也可以利用爬虫收集对自身有价值的数据. 一个网络爬虫程 ...

  3. JVM03Java代码执行流程

    一.Java的跨平台性 Java代码的执行流程 jvm运行原理: 运行一个HelloWorld的类,运行完毕之后,文件夹里出现HelloWorld.class的文件 javac程序是一个Java编译器 ...

  4. Shiro框架:Shiro简介、登陆认证入门程序、认证执行流程、使用自定义Realm进行登陆认证、Shiro的MD5散列算法

    一.Shiro介绍: 1.什么是shiro: (1)shiro是apache的一个开源框架,是一个权限管理的框架,实现用户认证.用户授权. (2)spring中有spring security,是一个 ...

  5. 分析Apache Log4j2 远程代码执行漏洞

    漏洞描述 Log4j是Apache的一个开源项目,通过使用Log4j,可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护进程等:也 ...

  6. Android系统手机开机画面各个阶段代码执行流程分析(Part1)

    提到Android系统的UI,我们最先接触到的便是系统在启动过程中所出现的画面了.Android系统在启动的过程中,最多可以出现三个画面,每一个画面都用来描述一个不同的启动阶段.本文将详细分析这三个开 ...

  7. Android系统手机开机画面各个阶段代码执行流程分析(Part2)

    3. 第三个开机画面的显示过程 第三个开机画面是由应用程序bootanimation来负责显示的.应用程序bootanimation在启动脚本init.rc中被配置成了一个服务,如下所示: servi ...

  8. 2021-02-26js学习-arguement,函数,作用域链,js代码执行流程,对象创建,new执过程.

    问题: Agurement概念认识? 伪数组概念认识? 函数的两种声明方式? 函数中没有声明而直接使用的变量是全局变量吗? Js块级作用域认识? 作用域链 概念认识? Js引擎执行代码的两步是什么? ...

  9. Vue项目启动代码执行流程分析

    相信来看看这篇文章的童鞋,都对Vue已经有了大致的了解.所以,话不多说,直接进入正题. 首先看下图: 一般一个初步的Vue项目创建好之后都会有这三个文件:index.html .main.js .Ap ...

  10. Scala入门示例反编译分析代码执行流程

    javap一下,看反编译结果: package com.zxl.java.chapter01;//分析 // 1. object在底层会生成两个类Hello , Hello$ // 2. Hello中 ...

最新文章

  1. mysql oracle 默认事务级别_oracle 默认的事务隔离级别
  2. Transformer t2t vit
  3. ElasticSearch-hadoop saveToEs源码分析
  4. vue路由跳转权限_vue权限路由实现方式总结
  5. 海德堡大学 BMCV 组(Master/Diploma/Bachelor)研究机会,生物医学图像分析方向
  6. linux系统声卡安装教程,Linux系统下如何安装声卡驱动?
  7. flowlayout布局怎么换行_web前端学习怎么入门
  8. AjaxPro实现方法
  9. 如何保证ArrayList线程安全
  10. jackson改变json值_使用jackson处理json数据
  11. 服装进销存管理软件榜单前十排名
  12. pdf拆分成多个文件,方法步骤
  13. html绘制平滑等值面,前端基于Canvas生成等值面的方案
  14. html5控制gif速度,用gifsicle优化GIF动图
  15. Riche million espérer interroger chasse.
  16. net start命令发生系统错误5和错误1058的解决方法
  17. java数组下标越界处理_可恶的Java数组下标越界检查
  18. web网络知识(一)公网IP、内网IP
  19. Flask中的session伪造
  20. 论语 阳货篇(笔记)

热门文章

  1. Android项目实战(三十四):蓝牙4.0 BLE 多设备连接
  2. 阿里云前端周刊 - 第 9 期
  3. linux系统一键安装php运行环境apache,mysql等
  4. 用PowerShell收集服务器日检报告,并发邮件给管理员
  5. 安卓开发_使用AlertDialog实现对话框
  6. 简单电脑***《菜鸟级》
  7. 微信小程序的模块化开发,提高效率第一篇
  8. JDK11即将来临,新特性了解一下
  9. python加法程序结果图片_OpenCV-Python系列之图像上的算术运算
  10. PHP 使用 ZipArchive 将文件打包成 zip