当前位置: 首页 > news >正文

Visual Studio 2022的MFC框架——AfxWinMain全局对象和InitInstance函数

我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来重新审视一下Visual Studio 2022下开发工具的MFC框架知识。 

在看这篇帖子前,请先看我的另一篇帖子《Visual Studio 2022的MFC框架——应用程序向导》。

当程序调用了CWinApp类的构造函数,并执行了CMfcApp类的构造函数,且产生了theApp 对象之后,接下来就进入 WinMain 函数。根据前面我写的一些MFC帖子所示的代码,可以发现WinMain 函数实际上是通过调用 AfxWinMain函数来完成它的功能的。

Afx前缀的函数代表应用程序框架Application Framework函数。应用程序框架实际上是一套辅助我们生成应用程序的框架模型。该模型把多个类进行了一个有机的集成,可以根据该模型提供的方案来设计我们自己的应用程序。在MFC中,以Afx为前缀的函数都是全局函数,可以在程序的任何地方调用它们。

我们可以采取同样的方式查找定义AfxWinMain 函数的源文件,在搜索到的文件中双击winmain.cpp,并在其中找到 AfxWinMain函数的定义代码。

int AFXAPI AfxWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,_In_ LPTSTR lpCmdLine, int nCmdShow)
{ASSERT (hPrevInstance == NULL);int nReturnCode =-1;CWinThread* pThread = AfxGetThread();CWinApp* pApp AfxGetApp();// AFX internal initializationif ( !AfxWinInit (hInstance, hPrevInstance, lpCmdLine, nCmdShow))goto InitFailure;// App global initializations (rare)if (pApp != NULL && !pApp->InitApplication())goto InitFailure;// Perform specific initializationsif (!pThread->InitInstance()){if (pThread->m_pMainWnd != NULL){TRACE(traceAppMsg, 0, "Warning\n");pThread->m_pMainWnd->Destroywindow();}nReturnCode = pThread->ExitInstance();goto InitFailure;nReturnCode = pThread->Run();InitFailure:#ifdef _DEBUG// Check for missing AfxLockTempMap callsif (AfxGetModuleThreadState()->m_nTempMapLock != 0){TRACE(traceAppMsg, 0, "Warning\n", AfxGetModuleThreadState ()->m_nTempMapLock);}AfxLockTempMaps ();AfxUnlockTempMaps (-1);#endifAfxWinTerm();return nReturnCode;}

在上面所示的代码中,AfxWinMain首先调用AfxGetThread函数获得一个CWinThread类型的指针,接着调用 AfxGetApp函数获得一个CWinApp类型的指针。从MFC类库组织结构图中可以知道CWinApp派生于CWinThread。

下面是AfxGetThread函数的源代码,位于thrdcore.cpp文件中。

CWinThread* AFXAPI AfxGetThread()
{// check for current thread in module thread stateAFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState ();CWinThread* pThread = pState->m_pCurrentWinThread;return pThread;
}

从上面所示代码中可以发现, AfxGetThread函数返回的就是在 CWinApp构造函数中保存的 this指针。对Mfc程序来说,这个this指针实际上指向的是CMfcApp的全局对象:theApp。

AfxGetApp是一个全局函数,定义于 afxwin1.inl中:

_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp(){ return afxCurrentWinApp;}

而afxCurrentWinApp的定义位于 afxwin.h文件中,代码如下:

#define afxCurrentWinApp    AfxGetModuleState()->m_pCurrentWinApp

结合查看之前关于MFC帖子中所示的CWinApp构造函数代码,就可以知道 AfxGetApp函数返回的是在 CWinApp 构造函数中保存的 this 指针。对Mfc程序来说, 这个 this 指针实际上指向的是 CMfcApp的对象: theApp。也就是说,对Mfc程序来说, pThread和 pApp所指向的都是CMfcApp类的对象,即theApp全对象。

再来说说InitInstance函数,再回到上面所示的 AfxWinMain函数,可以看到在接下来的代码中,pThread和 pApp调用了三个函数,这三个函数就完成了Win32程序所需要的几个步骤:设计窗口类、注册窗口类、创建窗口、显示窗口、更新窗口、消息循环,以及窗口过程函数。pApp首先调用 InitApplication函数,该函数完成MFC内部管理方面的工作。

接着,调用pThread的 InitInstance 函数。在Mfc程序中,可以发现从 CWinApp派生的应用程序类CMfcApp也有一个InitInstance函数,其声明代码如下所示。

virtual BOOL InitInstance();

从其定义可以知道,InitInstance函数是一个虚函数。根据类的多态性原理,可以知道AfxWinMain函数在这里调用的实际上是子类  CMfcApp 的 InitInstance函数。CMfcApp类的 InitInstance函数定义代码如下所示。

BOOL CMfcApp::InitInstance()
{INITCOMMONCONTROLSEX InitCtrls;InitCtrls. dwsize sizeof (InitCtrls);//将它设置为包括所有要在应用程序中使用的//公共控件类InitCtrls. dwICC = ICC_WIN95_CLASSES;InitCommonControlsEx(&InitCtrls);CWinApp::InitInstance();//初始化OLE库if (!AfxOleInit()){AfxMessageBox (IDP_OLE_INIT_FAILED);return FALSE;}AfxEnableControlContainer();EnableTaskbarInteraction (FALSE);SetRegistryKey(_T("应用程序向导生成的本地应用程序")LoadStdProfileSettings(4); //加载标准 INI 文件选项(包括 MRU)//注册应用程序的文档模板。  文档模板//将用作文档、框架窗口和视图之间的连接CSingleDocTemplate* pDocTemplate;pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS (CMfcDoc),RUNTIME_CLASS (CMainFrame),  //主SDI框架窗口RUNTIME_CLASS (CMfcView));if ( !pDocTemplate)return FALSE;AddDocTemplate (pDocTemplate);//分析标准shel1命令、DDE、打开文件操作的命令行CCommandLineInfo cmdInfo;ParseCommandLine (cmdInfo);if ( !ProcessShellCommand (cmdInfo))return FALSE;//唯一的一个窗口已初始化,因此显示它并对其进行更新m_pMainWnd->ShowWindow(SW_SHOW);m_pMainWnd->Updatewindow ();return TRUE;
}

这几篇内容涉及的内容有点难,如果大家看不懂,要结合其他VC的资料综合看。

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。

相关文章:

Visual Studio 2022的MFC框架——AfxWinMain全局对象和InitInstance函数

我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来重新审视一下Visual Studio 2022下开发工具的MFC框架知识。 在看这篇帖子前,请先看我的另一篇帖子《Visual Studio 2022的MFC框架——应用程序向导》。 当程序调用了CWinApp类的构造…...

【网络】多路转接——poll | epoll

🐱作者:一只大喵咪1201 🐱专栏:《网络》 🔥格言:你只管努力,剩下的交给时间! 书接上文五种IO模型 | select。 poll | epoll 🍧poll🧁认识接口🧁简…...

音视频 ffmpeg命令视频录制(Windows)

先安装dshow软件 Screen Capturer Recorder, 项目地址:https://sourceforge.net/projects/screencapturer/files/ 然后查看可用设备名字:ffmpeg -list_devices true -f dshow -i dummy [dshow 0509d6c0] DirectShow video devices (some ma…...

【拾枝杂谈】从游戏开发的角度来谈谈原神4.0更新

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello,米娜桑们,这里是君兮_,结合最近的学习内容和以后自己的目标,今天又开了杂谈这个新坑,分享一下我在学习游戏开发的成长和自己的游戏理解,当然现在还是一枚…...

QT设置mainwindow的窗口title

QT设置mainwindow的窗口title 在QT程序中,通常会有**aaaa-[bbbbbbb]**这种形式的title,对于刚上手qt的程序员同学,可能会简单的以为修改这种title,就是使用setWindowTitle这个接口,其实只对了一半,这种形式…...

SaaS多租户系统架构设计

前言:多租户是SaaS(Software-as-a-Service)下的一个概念,意思为软件即服务,即通过网络提供软件服务。SaaS平台供应商将应用软件统一部署在自己的服务器上,客户可以根据工作的实际需求,通过互联网…...

Java自定义捕获异常

需求分析 ElectricalCustomerVO electricalCustomerVO new ElectricalCustomerVO(); electricalCustomerVO.setElcNumber(chatRecordsLog.getDeviceNumber()); List<ElectricalCustomerVO> electricalCustomerlist electricalCustomerMapper.selectElectricalCustomer…...

力扣--数组类题目27. 移除元素

给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 示例 1&#xff1a; 输入&#xff1a;nums [3,2,2,3], val 3 输出&#xff1a;2, nums [2,2] 解释&#xff1a;函数应该返回新的长度 2, 并且 n…...

实际并行workers数量不等于postgresql.conf中设置的max_parallel_workers_per_gather数量

1 前言 本文件的源码来自PostgreSQL 14.5&#xff0c;其它版本略有不同 PostgreSQL的并行workers是由compute_parallel_worker函数决定的&#xff0c;compute_parallel_worker是估算扫描所需的并行工作线程数&#xff0c;并不是您在postgresql.conf中设置的max_parallel_work…...

java定位问题工具

一、使用 JDK 自带工具查看 JVM 情况 在我的机器上运行 ls 命令&#xff0c;可以看到 JDK 8 提供了非常多的工具或程序&#xff1a; 接下来&#xff0c;我会与你介绍些常用的监控工具。你也可以先通过下面这张图了解下各种工具的基本作用&#xff1a; 为了测试这些工具&#x…...

【Java】基础入门 (十六)--- 异常

1.异常 1.1 异常概述 异常是指程序在运行过程中出现的非正常的情况&#xff0c;如用户输入错误、除数为零、文件不存在、数组下标越界等。由于异常情况再程序运行过程中是难以避免的&#xff0c;一个良好的应用程序除了满足基本功能要求外&#xff0c;还应具备预见并处理可能发…...

[javaWeb]Socket网络编程

网络编程&#xff1a;写一个应用程序,让这个程序可以使用网络通信。这里就需要调用传输层提供的 api。 Socket套接字 传输层提供协议&#xff0c;主要是两个: UDP和TCP 提供了两套不同的 api&#xff0c;这api也叫做socket api。 UDP和 TCP 特点对比&#xff1a; UDP: 无连…...

<MySon car=“宝马“ :money=“money“></MySon>有没有冒号

为什么car"宝马"没有&#xff1a; 但是 :money"money"就有&#xff1a; <script setup> import {ref} from vue import MySon from /components/MySon.vueconst money ref(100) </script><template><h3>father</h3><My…...

netty(三):NIO——多线程优化

NIO多线程优化 使用Boss线程来处理accepct事件使用Worker线程来处理读写事件&#xff0c;可以创建多个worker线程 package com.review;import lombok.extern.slf4j.Slf4j;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.*; impor…...

Linux操作系统--linux概述

1.Linux概述 Linux&#xff0c;全称GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff08;OS&#xff09;。简单的说就是一种操作系统。在日常中常见的操作系统有一下三种: 2.linux起源和背景 (1).linux的诞生 linux操作系统是由李纳斯托瓦兹&#xf…...

数组中出现次数超过一半的数字

⭐️ 题目描述 &#x1f31f; OJ链接&#xff1a;数组中出现次数超过一半的数字 思路&#xff1a; 采用投票计数的方式&#xff0c;我们可以把每个数字都看成一次投票并且计数&#xff0c;那么最后剩下来的就是数组中数字出现次数最多的那一个。比如 { 1,2,3,2,2,2,5,4,2 } &a…...

网络优化工程师,你真的了解吗?

一、5G网络优化工程师到底是什么&#xff1f; 5G&#xff0c;就是我们通常所说的第五代移动通信标准&#xff0c;属于目前最热门的新技术趋势。随着2019年5G技术进入正式的商用阶段&#xff0c;拥有广阔的发展前景&#xff0c;备受瞩目。“5G工程师”这个词是一个概念词&#x…...

git 的常用命令

git是一个版本管理器&#xff0c;是程序员必备工具之一&#xff0c;其主分为三个区&#xff1a; 工作区&#xff1a; 暂存区&#xff1a; 仓库&#xff1a; 通过保持软件版本&#xff0c;分支&#xff0c;合并&#xff0c;等多种版本操作&#xff0c;使软件能在自己想要的版本…...

linux如何拷贝文件,删除多余的一级目录,用*号代替所有文件

加上*&#xff0c;代表目录下的所有文件 mv /home/user/dir1/dir1/* /home/user/dir1/可以使用mv命令的通配符来去掉一层目录。 例如&#xff0c;假设有一个名为/home/user/dir1/dir2/file.txt的文件&#xff0c;要将它移动到/home/user/dir2/目录下并去掉dir1目录&#xff0…...

springboot使用properties

一、方式1&#xff1a; 1.1.配置类&#xff1a; package cn.zyq.stater.config;import cn.zyq.stater.bean.User4; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...