手把手分析 mfc 程序创建 代码执行流程
程序流程
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 程序创建 代码执行流程相关推荐
- 「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析
「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析 前言 一.我的开发环境 二.使用 Vue CLI (Vue 脚手架)快速搭建项目 三.初始项目的目录结构 ...
- 一篇文章教会你Python网络爬虫程序的基本执行流程
网络爬虫是指在互联网上自动爬取网站内容信息的程序,也被称作网络蜘蛛或网络机器人.大型的爬虫程序被广泛应用于搜索引擎.数据挖掘等领域,个人用户或企业也可以利用爬虫收集对自身有价值的数据. 一个网络爬虫程 ...
- JVM03Java代码执行流程
一.Java的跨平台性 Java代码的执行流程 jvm运行原理: 运行一个HelloWorld的类,运行完毕之后,文件夹里出现HelloWorld.class的文件 javac程序是一个Java编译器 ...
- Shiro框架:Shiro简介、登陆认证入门程序、认证执行流程、使用自定义Realm进行登陆认证、Shiro的MD5散列算法
一.Shiro介绍: 1.什么是shiro: (1)shiro是apache的一个开源框架,是一个权限管理的框架,实现用户认证.用户授权. (2)spring中有spring security,是一个 ...
- 分析Apache Log4j2 远程代码执行漏洞
漏洞描述 Log4j是Apache的一个开源项目,通过使用Log4j,可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护进程等:也 ...
- Android系统手机开机画面各个阶段代码执行流程分析(Part1)
提到Android系统的UI,我们最先接触到的便是系统在启动过程中所出现的画面了.Android系统在启动的过程中,最多可以出现三个画面,每一个画面都用来描述一个不同的启动阶段.本文将详细分析这三个开 ...
- Android系统手机开机画面各个阶段代码执行流程分析(Part2)
3. 第三个开机画面的显示过程 第三个开机画面是由应用程序bootanimation来负责显示的.应用程序bootanimation在启动脚本init.rc中被配置成了一个服务,如下所示: servi ...
- 2021-02-26js学习-arguement,函数,作用域链,js代码执行流程,对象创建,new执过程.
问题: Agurement概念认识? 伪数组概念认识? 函数的两种声明方式? 函数中没有声明而直接使用的变量是全局变量吗? Js块级作用域认识? 作用域链 概念认识? Js引擎执行代码的两步是什么? ...
- Vue项目启动代码执行流程分析
相信来看看这篇文章的童鞋,都对Vue已经有了大致的了解.所以,话不多说,直接进入正题. 首先看下图: 一般一个初步的Vue项目创建好之后都会有这三个文件:index.html .main.js .Ap ...
- Scala入门示例反编译分析代码执行流程
javap一下,看反编译结果: package com.zxl.java.chapter01;//分析 // 1. object在底层会生成两个类Hello , Hello$ // 2. Hello中 ...
最新文章
- mysql oracle 默认事务级别_oracle 默认的事务隔离级别
- Transformer t2t vit
- ElasticSearch-hadoop saveToEs源码分析
- vue路由跳转权限_vue权限路由实现方式总结
- 海德堡大学 BMCV 组(Master/Diploma/Bachelor)研究机会,生物医学图像分析方向
- linux系统声卡安装教程,Linux系统下如何安装声卡驱动?
- flowlayout布局怎么换行_web前端学习怎么入门
- AjaxPro实现方法
- 如何保证ArrayList线程安全
- jackson改变json值_使用jackson处理json数据
- 服装进销存管理软件榜单前十排名
- pdf拆分成多个文件,方法步骤
- html绘制平滑等值面,前端基于Canvas生成等值面的方案
- html5控制gif速度,用gifsicle优化GIF动图
- Riche million espérer interroger chasse.
- net start命令发生系统错误5和错误1058的解决方法
- java数组下标越界处理_可恶的Java数组下标越界检查
- web网络知识(一)公网IP、内网IP
- Flask中的session伪造
- 论语 阳货篇(笔记)