MFC编程框架总结

article/2025/1/11 6:09:24

简介

  MFC是一种C++类库,利用面向对象的方法封装了Windows API,为Windows应用程序的开发带来了极大便利。本文总结了使用MFC进行编程的基本方法,编程环境为VS2008 SP1。

搭建MFC开发环境

  由于使用MFC应用程序向导后VS会自动生成应用程序框架,因而本文先利用VS生成一个空项目,然后在此基础上一步步编写应用程序。
  打开VS2008,从菜单中依次打开文件->新建->项目,弹出新建项目对话框,在左侧的项目类型中选择Visual C++->Win32,在右侧的模板中选择Win32 项目,并填写项目名称及路径,本文的项目名称为Hello,如下图所示。
新建Win32项目
  点击确定按钮,进入Win32应用程序向导对话框,点击下一步
Win32应用程序向导
  应用程序类型选择Windows应用程序附加选项选择空项目,点击完成
Win32应用程序设置
  现在已经生成了一个Win32空项目,然后鼠标右键单击左侧工作空间窗口中的Hello项目,选择属性。在弹出的属性配置对话框中,打开配置属性->常规,将MFC的使用使用标准Windows库改为在共享DLL中使用MFC,然后点击确定按钮。
属性配置
  配置好该项属性后,项目就可以支持MFC类库了。

定义MFC应用程序对象

  开发MFC应用程序的首要任务是定义一个基于CWinApp类的应用程序对象。由于MFC已经对WinMain函数进行了封装,所以无需在程序中提供WinMain函数,而是采用对象来抽象表示应用程序,一个MFC应用程序有且仅有一个应用程序对象。
  鼠标右键单击左侧工作空间窗口中的Hello项目,依次选择添加->类,在弹出的对话框中选择C++类,点击添加按钮。
添加C++类
  在弹出的一般C++类向导对话框中填写应用程序对象的相关信息,本文将类名定义为CMyApp,基类一项填写CWinApp,其他项保持默认即可。
一般C++类向导
  点击完成按钮,会提示项目中未找到基类"CWinApp",点击跳过即可。
项目未找到基类
  为了解决提示中描述的问题,打开MyApp.h,添加#include <afxwin.h>语句,即可将CWinApp以及其他MFC类引入应用程序中,并在CMyApp类的定义中添加InitInstance函数的声明。

#pragma once#include <afxwin.h>class CMyApp : public CWinApp
{
public:CMyApp(void);~CMyApp(void);virtual BOOL InitInstance();
};

  InitInstance函数的主要作用是为应用程序创建一个窗口。窗口是Windows应用程序的核心,是实现人机交互的重要接口。与应用程序对象相同,MFC使用CWnd类及其派生类对窗口进行抽象表示。在创建应用程序的过程中,有两个比较重要的窗口类,即CWndCFrameWnd。前者是所有窗口类的基类,后者是从前者派生而来,被称为框架窗口,框架窗口在文档/视图体系结构中起着重要作用。
  接下来打开MyApp.cpp,定义一个CMyApp类的对象代表应用程序,程序开始执行时该对象即在内存中实例化。

#include "MyApp.h"// 应用程序对象
CMyApp myApp;CMyApp::CMyApp(void)
{
}CMyApp::~CMyApp(void)
{
}

创建框架窗口

  首先用同样的方法添加窗口类,右键单击左侧工作空间窗口中的Hello项目,依次选择添加->类,在弹出的对话框中选择C++类,点击添加按钮。弹出一般C++类向导对话框,类名填写CMainWindow,基类填写CFrameWnd,其他项保持默认即可。然后点击完成按钮,会提示项目中未找到基类"CFrameWnd",点击跳过即可。同样地,打开MainWindow.h,添加#include <afxwin.h>语句,即可解决提示中出现的问题。
  通过生成窗口对象并调用其CreateCreateEx函数,MFC应用程序可以创建一个窗口。打开MainWindow.cpp,在CMainWindow类的构造函数中添加Create函数。

CMainWindow::CMainWindow(void)
{Create(NULL, _T("The Hello Application"));
}

  然后打开MyApp.cpp,包含MainWindow.h头文件并添加InitInstance函数的定义。

#include "MainWindow.h"BOOL CMyApp::InitInstance()
{m_pMainWnd = new CMainWindow;m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE;
}

  其中,m_pMainWnd是指向CWnd类型的指针。该变量是由MFC定义的,指向应用程序的主窗口。ShowWindow函数的作用是显示窗口,其参数m_nCmdShowCWinApp类的成员变量。m_nCmdShow用于指定窗口的状态。通常情况下,m_nCmdShow的值为SW_SHOWNORMAL,即正常状态。UpdateWindow可以使窗口立即重新绘制。
  点击启动调试运行程序,可以看到一个标题为The Hello Application的空白窗口。
空白窗口

添加消息处理函数

  与过程化模型不同,Windows使用的是事件驱动编程模型,应用程序通过处理操作系统发送来的消息响应事件。以WM_PAINT消息为例,程序启动时会触发该消息用以绘制窗口,这时可以通过其对应的消息处理函数OnPaint对该消息进行处理。
  首先打开MainWindow.cpp添加消息映射及相应的命令响应函数。

BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)ON_WM_PAINT()
END_MESSAGE_MAP()void CMainWindow::OnPaint()
{CPaintDC dc(this);CRect rect;GetClientRect(&rect);dc.DrawText(_T("Hello, MFC"), -1, &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}

  该函数用于在窗口中输出Hello, MFC。然后在MainWindow.h中为消息处理函数添加声明。

protected:afx_msg void OnPaint();DECLARE_MESSAGE_MAP()

  重新点击启动调试运行程序,可以看到窗口中心输出了Hello, MFC
HelloMFC

创建普通窗口

  以上步骤阐述了框架窗口的使用,接下来将基于普通窗口创建应用程序。首先打开MainWindow.h,将基类CFrameWnd改为CWnd
  然后打开MainWindow.cpp,将BEGIN_MESSAGE_MAP宏中的基类改为CWnd,同时修改CMainWindow类的构造函数。

CMainWindow::CMainWindow(void)
{// 注册WNDCLASSCString strWndClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,AfxGetApp()->LoadStandardCursor(IDC_ARROW),(HBRUSH)(COLOR_WINDOW + 1),AfxGetApp()->LoadStandardIcon(IDI_WINLOGO));// 创建窗口CreateEx(0, strWndClass, _T("The Hello Application"),WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL);// 调整窗口大小CRect rect(0, 0, 352, 352);CalcWindowRect(&rect);SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
}

  可以看到,CMainWindow类的构造函数首先使用AfxRegisterWndClass函数注册了WNDCLASS。如果窗口类是从CFrameWnd派生的,并且将CFrameWnd::Create函数的第一个参数指定为NULL,MFC会完成WNDCLASS的注册。然而从CWnd派生窗口类时,需要自己注册WNDCLASSAfxRegisterWndClass函数的原型如下:

LPCTSTR AFXAPI AfxRegisterWndClass(UINT nClassStyle,HCURSOR hCursor = 0, HBRUSH hbrBackground = 0, HICON hIcon = 0);

  第一个参数nClassStyle指定了类样式,定义了窗口的某种操作特性。宏CS_HREDRAWCS_VREDRAW分别表示窗口被水平与垂直缩放时使整个客户区无效。第二个参数hCursor指定了该窗口中显示的光标形状。AfxGetApp函数用于获取当前应用程序对象的指针,其返回类型为CWinApp*CWinApp::LoadStandardCursor函数可以加载系统预定义的光标类型,IDC_ARROW代表标准箭头光标。第三个参数hbrBackground定义了窗口的默认背景色。(HBRUSH)(COLOR_WINDOW + 1)定义了白色背景。hIcon指定了Windows在桌面上、任务栏和其他地方代表应用程序的图标句柄。CWinApp::LoadStandardIcon函数用于加载预定义的系统图标。IDI_WINLOGO表示一个普通的应用程序图标。
  注册了WNDCLASS之后,就可以调用CWnd::CreateEx函数创建主窗口。第一个参数指定窗口扩展样式,第二个参数是AfxRegisterWndClass函数返回的WNDCLASS名称,第三个参数是窗口标题,第四个参数是窗口样式,接下来的四个参数指定了窗口的初始位置和大小,最后两个参数指定父窗口和菜单。
  CalcWindowRect函数根据参数rect计算窗口的尺寸,rect代表所希望的窗口客户区的尺寸。SetWindowPos函数使尺寸设置生效。
  从CWnd派生窗口类时,必须自己删除窗口对象。窗口在被销毁之前将收到最后一个消息WM_NCDESTROYCWnd类包括一个默认的OnNcDestroy函数,该函数首先执行一些清除任务,接着将调用PostNcDestroy函数。CFrameWnd类覆盖了PostNcDestroy函数并执行一个delete this语句删除自身。然而,CWnd类中的PostNcDestroy函数并不执行delete this语句,因而从CWnd派生窗口类时应该提供自己的PostNcDestroy函数。打开MainWindow.cpp,加入PostNcDestroy函数。

void CMainWindow::PostNcDestroy()
{delete this;CWnd::PostNcDestroy();
}

  然后打开MainWindow.h,加入该函数的声明。

virtual void PostNcDestroy();

  再次点击启动调试运行程序,可以看到一个尺寸较小的程序窗口。
HelloMFCSmallWindow


http://chatgpt.dhexx.cn/article/fUfWdJGf.shtml

相关文章

并发编程框架----disruptor框架(一)

背景 Disruptor是英国外汇交易公司LMAX开发的一个高性能队列&#xff0c;研发的初衷是解决内存队列的延迟问题&#xff08;在性能测试中发现竟然与I/O操作处于同样的数量级&#xff09;。基于Disruptor开发的系统单线程能支撑每秒600万订单&#xff0c;2010年在QCon演讲后&…

网络编程框架

网络编程 Socket网络通信编程 Socket主要解决一个网间进程通信&#xff08;不同主机进程间的相互通信问题&#xff09;。 提供进程通信的端点&#xff0c;一个程序将一段信息写入Socket中&#xff0c;该Socket将这段信息发送给另外一个Socket中&#xff0c;使这段信息能传送到…

您所应了解的Python四大主流网络编程框架

**本文内容摘录自《Python高效开发实战——Django、Tornado、Flask、Twisted》一书。**该书分为三部分&#xff1a;第1部分是基础篇&#xff0c;带领初学者实践Python开发环境和掌握基本语法&#xff0c;同时对网络协议、Web客户端技术、数据库建模编程等网络编程基础深入浅出地…

常见编程/框架介绍

文章大纲 一、C/C二、C#三、cocos2d-x四、go语言五、Hadoop六、HBase七、PHP八、python九、Spark十、Storm十一、Unity3D十二、Java十三、Android十四、Object-C与swift十五、.NET十六、R语言 一、C/C 1. 简介 C语言是目前世界上流行、使用最广泛的高级程序设计语言。C语言对操…

Linux 应用编程框架

粗略的复习下linux应用编程的一些知识&#xff0c;画个导图记录总结下&#xff1a;

Python 四大主流 Web 编程框架

目前Python的网络编程框架已经多达几十个&#xff0c;逐个学习它们显然不现实。但这些框架在系统架构和运行环境中有很多共通之处&#xff0c;本文带领读者学习基于Python网络框架开发的常用知识,及目前的4种主流Python网络框架&#xff1a;Django、Tornado、Flask、Twisted。 …

【常见编程/框架介绍】

目录 一、C/C 1. 简介 2. 特点 3. 优点 4. 缺点 5. 常见使用场景 二、C# 三、cocos2d-x 四、go语言 1. 简介 2. 优点 3. 缺点 4. 就业方向 五、Hadoop 1. 简介 2. 优势 3. 应用场景 六、HBase 七、PHP 1. 简介 2. 优点 3. 缺点 4. 就业方向 八、python …

mac命令行查看dSYM文件的UUID

通过命令行查看 *.dSYM 文件的UUID值&#xff0c;标准范式&#xff1a; xcrun dwarfdump --uuid dSYM文件 实例演示&#xff1a; 想查看 Electron Framework.dSYM 的UUID值&#xff1a; 结果&#xff1a;5BE9E0C9-3946-3E4D-B12A-595EDA5170AF

dSYM的简单介绍

通过http://www.cocoachina.com/ios/20100427/1222.html 这篇文章&#xff0c;结合自己日常工作的理解&#xff0c;提炼了一下主要内容 一、dsym是什么&#xff1f; 在XCODE编译项目之后,会在app旁看见一个同名的dSYM文件.&#xff08;rd称之为 符号文件&#xff09;他是一个编…

dSYM 文件分析工具

我在项目中使用了百度统计&#xff0c;友盟统计也可以&#xff0c;上线项目出bug的时候&#xff0c;错误信息统计中能比较方便的找出客户端异常的信息&#xff0c;可是很多像数组越界却只给出了 *** -[__NSArrayM objectAtIndex:]: index 50 beyond bounds [0 .. 39] 这类错误信…

firebase_crashlytics缺失dSYM unity ios

Firebase后台提示缺失dSYM文件的截图 解决方案&#xff1a; 一、找dSYM&#xff1a; 方法一&#xff1a; 打开xcode->window->organizer->选择你的版本包archives->show in finder->显示包内容->里面即可看到.dSYM文件 方法二&#xff1a; 打开终端&#…

iOS-详解没有dSYM文件 如何解析iOS崩溃日志

Xcode支持崩溃日志自动符号化&#xff0c;前提是本地有当时Build/Archive生成的dSYM文件&#xff0c;iOS崩溃日志符号化后&#xff0c;可以帮助开发者更好的定位问题&#xff0c;但如果dSYM文件丢失或拿到的崩溃日志不是标准的crash log&#xff0c;如何定位crash呢&#xff0c…

iOS开发-dSYM文件

文章目录 dSYMxcode的符号化解析每个架构的符号 Bitcode相关定位你的dSYMBuild UUID对比恢复隐藏的符号表文件符号化解析操作命令命令行工具 symbolicatecrash 符号化 dSYM 根据 苹果官方文档&#xff0c;当编译器将源代码转为机械码时&#xff0c;会生成调试符号(debug symbo…

ios崩溃日志分析,无dSYM文件

问题场景 大部分情况下&#xff0c;我们都拿不到dSYM文件&#xff0c;只有一份ipa文件一个crash文件&#xff0c;应该如何定位具体崩溃的代码呢&#xff1f; 实例说明 首先本人建立了一个demo工程&#xff0c;写了一段会crash的代码&#xff0c;如下图 然后打包成ipa包&…

命令行工具解析Crash文件,dSYM文件进行符号化

https://www.jishux.com/p/10628644fe5dabf3 序 在日常开发中&#xff0c;app难免会发生崩溃。简单的崩溃还好说&#xff0c;复杂的崩溃就需要我们通过解析Crash文件来分析了&#xff0c;解析Crash文件在iOS开发中是比较常见的。 获取崩溃信息方式 在iOS中获取崩溃信息的方…

iOS-dSYM 文件分析工具

来到新公司后&#xff0c;前段时间就一直在忙&#xff0c;前不久 项目 终于成功发布上线了&#xff0c;最近就在给项目做优化&#xff0c;并排除一些线上软件的 bug&#xff0c;因为项目中使用了友盟统计&#xff0c;所以在友盟给出的错误信息统计中能比较方便的找出客户端异常…

DSYM文件

什么是dSYM文件&#xff1f; iOS平台中&#xff0c;dSYM文件是指具有调试信息的目标文件&#xff0c;文件名通常为&#xff1a;xxx.app.dSYM。如下图所示&#xff1a; 为了方便找回Crash对应的dSYM文件和还原堆栈&#xff0c;建议每次构建或者发布APP版本的时候&#xff0c;备…

Xcode打包后,找不到dSYM文件

在一次分析crash时&#xff0c;需要用到dSYM文件&#xff0c;于是去对应的位置找&#xff0c;结果找到一个空文件夹&#xff0c;里面什么都没有&#xff0c;这是怎么回事&#xff1f; 后来发现是在打包的时候&#xff0c;在TARGET->Building Setting->Build Option下的设…

dSYM文件是什么 ?

Overview 概述 dSYM的全称是debug symbol, 所以dSYM文件就是debug symbol (dSYM) file, dSYM文件中的每个 debug symbol, 对应了一个关系, 这个关系一端是源代码里真实的符号(类名称、全局变量以及方法和函数名称), 另一端则是其定义的文件号和行号. Apple Documentation 苹果…