Win32程序与MFC程序构建顺序梳理

Windows程序的生成顺序

Windows窗口的生命周期

初始化操作
  • 从WinMain函数开始,注册窗口;
  • 创建窗口;
    • 调用CreateWindow,为程序建立了一个窗口,作为程序的屏幕
      舞台。CreateWindow产生窗口之后会送出WM_CREATE消息给窗口函数,后者
      于是可以在此时做些初始化操作(例如配置内存、打开文件、设置窗口初始数据等)。
  • 显示刷新窗口
 ShowWindow (hwnd, iCmdShow) ;    //显示窗口
UpdateWindow (hwnd) ;    //刷新窗口
用户交互操作

GetMessage函数用于从消息队列中获取消息,DispatchMessage函数(在Windows USER模块的帮助下)则是将消息分派到相应的窗口函数进行处理。这是Windows编程中常见的一种机制,用于处理用户界面的交互和事件。

WM_QUIT是特定的消息类型,当接收到这个消息时,GetMessage会返回0并结束while循环,进而结束整个程序。
下图为Windows处理用户交互信息的过程:
在这里插入图片描述

关闭窗口

使用者按下系统菜单中的Close命令 -> 系统送出WM_CLOSE消息 -> DefWindowProc处理调用DestroyWindow -> Destroy Window送出WM_DESTROY消息 -> 程序对WM_DESTROY的标准反应是调用PostQuitMessage送出WM_QUIT消息 -> 消息循环中的GetMessage取得,如步骤2,结束消息循环.

MFC程序的生成顺序

通过Windows SDK程序可以得出程序运行的最重要的两部分为WinMain(初始化操作)、WinProcedure(处理信息)

MFC中类的派生关系:CObject->CCmdTarget->CWinThread->CWinApp

准备阶段1

MFC程序中WinMain函数的作用被CWinApp类取代了,它所负责的全部初始化工作和对消息解释及分派都有 CWinApp类的内部函数来完成,但是WinMain仍然存在,并且扮演着驾驭CWinApp的角色。CWinApp中几个最重要的函数如下:

virtual BOOL InitApplication();
virtual BOOL InitInstance();
virtual int Run();

在SDK程序设计中至关重要的主窗口句柄(就是那个hwnd,几乎程序所有有关窗口的操作都必须用到该句柄,它为Windows定位所要输出的信息 的目的窗口),它被存储在CWinThread中名为m_MainWnd的成员变量中,而CWinThread是CWinApp的父类。

准备阶段2

WndProc窗口函数与WinMain一样被变形后由单独生成的类进行了替代,替代它的是名为CFrameWnd的类,该类一般因程序不同而被继承为不同的模样,比较有代表性的一般形态如下:

class CMyFrameWnd : public CFrameWnd
{
public:
    CMyFrameWND();
    afx_msg void OnPaint();
    afx_msg boid OnAbout();
    DECLARE_MESSAGE_MAP();
};
程序构建及运行
  • 1、设置全局对象
    大量的CWinApp之中的成员变量由于theApp的诞生而进行了配置或被赋初值,因此我们完全可以说theApp这个Application object是整个程序的引爆器。
  • 2、the App配置完成之后,应有WinMain函数处理
    在…\Microsoft Visual Studio\VC98\MFC\SRC目录下可以找到一个名为WinMain.cpp的文件其中体现WinMain主要工作的代码为:
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPTSTR lpCmdLine, int nCmdShow)
{
	...
	CWinApp* pApp = AfxGetApp();
	// AFX internal initialization
	if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
    goto InitFailure;
    if (pApp != NULL && !pApp->InitApplication())
    goto InitFailure;

    // Perform specific initializations
    if (!pThread->InitInstance())
    {...};
   nReturnCode = pThread->Run();
   }

重点为AfxWinInit函数调用、pApp->InitInstance(); nReturnCode=pApp->run();

  • 首先是AfxWinInit,它隐藏在APPINIT.CPP中,重要代码如下:
BOOL AFXAPI AfxWinInit(HINSTANCE hInstance, HINSTANCE hPrevInstance,
            LPTSTR lpCmdLine, int nCmdShow)
{	
		...
	    CWinApp* pApp = AfxGetApp();
	     if (pApp != NULL)
    {
        // Windows specific initialization (not done if no CWinApp)
        pApp->m_hInstance = hInstance;
       pApp->m_hPrevInstance = hPrevInstance;
       pApp->m_lpCmdLine = lpCmdLine;
       pApp->m_nCmdShow = nCmdShow;
        pApp->SetCurrentHandles();
    }
 }
  • pApp->InitInstance,CWinApp类中此函数是虚函数,由于程序改写了该函数,所以现在等于调用我们自己的InitInstance,我们的程序也将从这里开始自己主窗口的生命。生成的一个简单程序的这一段代码如下:
BOOL CTestApp::InitInstance()
{
	 ...	
	CMainFrame* pMainFrame = new CMainFrame;//调用了CMainFrame的构造函数
	 ...
	 if (!ProcessShellCommand(cmdInfo))
           return FALSE;

    m_pMainWnd->ShowWindow(SW_SHOW);    //这两行与SDK程序
    m_pMainWnd->UpdateWindow();         //极为相似
}
  • CWinApp::Run事实上指向CWinThread::Run,它位于THRDCORE.CPP中,代码如下:
int CWinThread::Run()
{
	while (bIdle &&
               !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
        {
            // call OnIdle while in bIdle state
            if (!OnIdle(lIdleCount++))
                bIdle = FALSE; // assume "no idle" state
        }

            // phase2: pump messages while available
        do
        {
            // pump message, but quit on WM_QUIT
            if (!PumpMessage())
                return ExitInstance();

            // reset "no idle" state after pumping "normal" message
            if (IsIdleMessage(&m_msgCur))
            {
                bIdle = TRUE;
                lIdleCount = 0;
            }

        } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
    }

    ASSERT(FALSE); // not reachable
}
PumpMessage代码如下:
BOOL CWinThread::PumpMessage()
{
    ASSERT_VALID(this);
    if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
    {
        return FALSE;
    }

    // process this message

    if (m_msgCur.message != WM_KICKIDLE

          && !PreTranslateMessage(&m_msgCur))
    {
        ::TranslateMessage(&m_msgCur);//SDK相似代码
        ::DispatchMessage(&m_msgCur);
    }
    return TRUE;
}

MFC程序死亡调用顺序与Win32程序大同小异。
文章主要参考:
http://blog.chinaunix.net/uid-21169302-id-446230.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能中的核心概念

1 概述 人工智能英文缩写为AI,是一种由人制造出来的机器,该机器可以模仿人的思想和行为,从而体现出一种智能的反应。 人工智能的产业链分为基础层、技术层、应用层三个层次。 基础层包括:芯片、大数据、算法系统、网络等多项基础…

企业呼叫中心系统怎么样?

随着现代商业环境的变化,呼叫中心系统成为众多企业日常运营的重要组成部分。企业呼叫中心系统是一种集中管理和处理企业电话通信的解决方案,它可以改善客户服务质量,提升服务效率,并为企业带来诸多优势。 企业呼叫中心系统功能概…

2021年数维杯国际大学生数学建模D题2021年电影市场票房波动模型分析求解全过程文档及程序

2021年数维杯国际大学生数学建模 D题 2021年电影市场票房波动模型分析 原题再现: 1、电影票房预测建模背景   随着人们文化消费需求的增加,电影院和银幕的数量不断增加,我国的电影产业不断呈现出繁荣景象。2019年,全国电影票房…

2024年【金属非金属矿山(地下矿山)安全管理人员】及金属非金属矿山(地下矿山)安全管理人员实操考试视频

题库来源:安全生产模拟考试一点通公众号小程序 金属非金属矿山(地下矿山)安全管理人员是安全生产模拟考试一点通总题库中生成的一套金属非金属矿山(地下矿山)安全管理人员实操考试视频,安全生产模拟考试一…

libxls - 编译

文章目录 libxls - 编译概述笔记静态库工程测试控制台exe工程测试备注备注END libxls - 编译 概述 想处理.xls格式的excel文件. 查了一下libxls库可以干这个事. 库地址 https://github.com/libxls/libxls.git 但是这个库的makefile写的有问题, 在mingw和WSL下都编译不了. 好在…

1265. 数星星(树状数组/蓝桥杯)

题目&#xff1a; 输入样例&#xff1a; 5 1 1 5 1 7 1 3 3 5 5输出样例&#xff1a; 1 2 1 1 0 思路&#xff1a; 树状数组 代码&#xff1a; #include<cstdio> #include<iostream> using namespace std; const int N32010; int n; int tr[N],level[N];int lo…

Linux---用户组相关操作

1. 创建用户组 命令说明groupadd创建(添加)用户组 创建用户组效果图: 2. 创建用户并指定用户组 创建用户并指定用户组效果图: 3. 修改用户组 修改用户组效果图: 4. 删除用户组 命令说明groupdel删除用户组 删除用户组效果图: 说明: 如果用户组下面有用户先删除用户在…

回归预测 | MATLAB实现IBL-LSSVM【23年新算法】逻辑优化算法优化最小二乘支持向量机的数据回归预测 (多指标,多图)

回归预测 | MATLAB实现IBL-LSSVM【23年新算法】逻辑优化算法优化最小二乘支持向量机的数据回归预测 &#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现IBL-LSSVM【23年新算法】逻辑优化算法优化最小二乘支持向量机的数据回归预测 &#xff08;多指标…

【C++】封装:练习案例-点和圆的关系

练习案例&#xff1a;点和圆的关系 设计一个圆形类&#xff08;Circle&#xff09;&#xff0c;和一个点类&#xff08;Point&#xff09;&#xff0c;计算点和圆的关系。 思路&#xff1a; 1&#xff09;创建点类point.h和point.cpp 2&#xff09;创建圆类circle.h和circle…

什么是漏电保护芯片?具有什么作用?

漏电保护芯片是一种用于监测电气设备是否存在漏电并提供保护的微型芯片。漏电是电气设备中普遍存在的一种安全隐患,当设备发生漏电时,电流会流回地线,并可能导致电击、火灾等严重后果。因此,漏电保护芯片的使用对于保障人身财产安全具有非常重要的意义。下面就是我们几款漏电保…

格式化Echarts的X轴显示,设置显示间隔

业务需求&#xff1a;x轴间隔4个显示&#xff0c;并且末尾显示23时 x轴为写死的0时-23时&#xff0c;使用Array.from data: Array.from({ length: 24 }).map((_, i) > ${i}时) 需要在axisLabel 里使用 interval: 0, // 强制显示所有刻度标签&#xff0c;然后通过 formatter …

【Axure教程】区间评分条

区间评分条是一种图形化的表示工具&#xff0c;用于展示某一范围内的数值或分数&#xff0c;并将其划分成不同的区间。这种评分条通常用于直观地显示数据的分布或某个指标的表现。常用于产品评价、调查和反馈、学术评价、健康评估、绩效评估、满意度调查等场景。 所以今天作者…

大语言模型加速信创软件 IDE 技术革新

QCon 全球软件开发大会&#xff08;上海站&#xff09;将于 12 月 28-29 日举办&#xff0c;会议特别策划「智能化信创软件 IDE」专题&#xff0c;邀请到华为云开发工具和效率领域首席专家、华为软件开发生产线 CodeArts 首席技术总监王亚伟担任专题出品人&#xff0c;为专题质…

bottom-up-attention-vqa-master 成功复现!!!

代码地址 1、create_dictionary.py 建立词典和使用预训练的glove向量 &#xff08;1&#xff09;create_dictionary() 遍历每个question文件取出所关注的question部分&#xff0c;qs 遍历qs&#xff0c;对每个问题的文本内容进行分词&#xff0c;并将分词结果添加到字典中&…

解决飞书文档导出word后公式乱码/不可显示问题

目录 项目场景: 原因分析: 解决方案: 项目场景: 飞书文档导出为word: 但是公式会出现在word中无法显示、乱码等问题。 原因分析: 飞书做的有点菜

智能优化算法应用:基于静电放电算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于静电放电算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于静电放电算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.静电放电算法4.实验参数设定5.算法结果6.…

DS哈希查找—线性探测再散列

Description 定义哈希函数为H(key) key%11&#xff0c;输入表长&#xff08;大于、等于11&#xff09;。输入关键字集合&#xff0c;用线性探测再散列构建哈希表&#xff0c;并查找给定关键字。 –程序要求– 若使用C只能include一个头文件iostream&#xff1b;若使用C语言…

Java_Lambda表达式JDK8新特性(方法引用)

一、Lambda表达式 接下来&#xff0c;我们学习一个JDK8新增的一种语法形式&#xff0c;叫做Lambda表达式。作用&#xff1a;用于简化匿名内部类代码的书写。 1.1 Lambda表达式基本使用 怎么去简化呢&#xff1f;Lamdba是有特有的格式的&#xff0c;按照下面的格式来编写Lamd…

FPGA实现 TCP/IP 协议栈 客户端 纯VHDL代码编写 提供4套vivado工程源码和技术支持

目录 1、前言版本更新说明免责声明 2、相关方案推荐我这里已有的以太网方案1G 千兆网 TCP-->服务器 方案10G 万兆网 TCP-->服务器客户端 方案常规性能支持多节点FPGA资源占用少数据吞吐率高低延时性能 4、TCP/IP 协议栈代码详解代码架构用户接口代码模块级细讲顶层模块PA…

腾讯地图绘画多边形和计算面积

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>地图</title></head><script src…