【C++】(三) MFC入门教程 (VS 2005)

前期C++教程

概述

  MFC(Microsoft Fundamental Class)全称叫做微软基础类库,是微软公司开发的一个C++类库,主要封装了大部分Windows API函数。此外,MFC不仅仅是一个类库,还是一个框架,每次新建一个MFC的工程,VS会自动生成一些基础文件,封装MFC的内核,这样在编程时就不需要考虑一些底层功能的实现,程序员可以专心实现自己想要的功能。

新建工程

  本博客主要采用的还是非常“古老”的VS2005,虽然软件很老,但对于初学者来说比较友好,不会有太多花里胡哨的东西。首先我们来学习如何新建工程。

  如果使用的VS版本比较高,如VS 2019,那么使用MFC之前要在C++桌面程序中添加MFC支持,具体过程可以参考这篇博客

  首先打开VS,选择“文件”->“新建”->“项目”
在这里插入图片描述
  新建项目结束之后,在Visual C++中选择MFC中的MFC应用程序,然后给项目工程取个名字并确定一个路径,然后点击确定。
在这里插入图片描述

  补充一点:一般用VS2005学习C++时,新建的都是win32中的Windows控制台程序,所谓控制台,也就是运行程序之后弹出的小黑框,和Devc++差不多。

  点击确定之后,可以看到项目设置的界面:
在这里插入图片描述
  可以看到左侧列表中的各项设置,依次点击下一步即可对这些一一设置,但如果觉得它默认设置也可以接受,可以随时点击完成采用其默认设置。一般来说,简单的程序只需要设置应用程序类型即可。在这个界面,点击下一步。
在这里插入图片描述
  在这个界面,只需要选择应用程序类型即可,其他设置保持默认,如果不需要其他的高级操作,直接点击完成即可。
  那么问题来了,单文档、多文档、对话框它们有什么区别呢?
  单文档和多文档的区别最典型的例子就是记事本和Word,至于对话框,可以理解为制作一个交互界面,但实际上单文档和多文档都可以添加对话框。因此我对这几个概念的理解就是,单文档和多文档一开始运行出来的是一个文档视图窗口,可以在上面进行绘制图案等操作,而对话框则只有对话框,并在对话框上面添加一些控件进行编程。个人认为初学者完全没有必要纠结这些内容,一般选择单文档或对话框即可,相对简单。
  下面将以单文档为例介绍MFC,大都也适用于对话框和多文档。

工程文件结构

  新建项目之后,可以看到解决方案资源管理器窗口中看到包含了三个文件夹,分别是头文件,源文件,资源文件,其中包含的文件及其作用如下图所示。
在这里插入图片描述
打开类视图窗口,可以看到创建项目时已包含的类
在这里插入图片描述
明显可以发现,这个类和文件是一一对应的,比如Doc、View、App、MainFrame类,如果点开其左边的加号,可以看到其继承的是哪些类,这样或许能够对Windows程序框架有一个更好的了解,但如果觉得太复杂也不用纠结。

主界面绘图和显示文字等操作

  新建一个项目工程之后,可以直接点击运行,就可以看到一个主界面,包括了菜单栏,工具栏和主要的显示界面,这个是底层程序已经写好的,不需要程序员去考虑是怎么生成的。
  对于新手来说,最简单的入门操作就是在主界面上绘制图形,比如画一个圆,然后给它填充一个颜色。要实现这个功能,首先是要清楚和界面绘制相关的类有哪些,其次就是要了解绘制图案的步骤
  对于第一个问题,最为推荐手边备用一个 MFC文档,主要记录的是MFC中类的名字和使用方法,遇到不熟悉的类,查这个文档肯定要比去网上搜来得快捷。
  对于第二个问题,绘制一个图案,一般的步骤是什么?参考这个链接,里面提到,在MFC中绘制图像,一般要涉及两个对象,一是设备上下文对象,包括CDC及其派生类;二是GDI(Graphic Device Interface)对象,包括CFont、CBrush、CPen等。这两者的关系可以理解为前者是环境,后者是工具。常用的GDI类如下所列。

  • CPen:用来绘制线条;
  • CBursh:用来填充绘制对象的内部;
  • CBitmap:用来操作位图对象;
  • CFont:用来绘制文本;
  • CPalette:用于应用程序和彩色输出设备(如显示器)之间的接口。

总结来说,使用GDI绘图,一般的操作是:

  • 创建GDI对象;
  • 创建或取得设备上下文对象;
  • 使用SelectObject把GDI对象选入设备上下文;
  • 使用图形输出函数在指定上下文中绘制图形。

附:MFC中DrawText函数的使用

对话框

  学完了文档视图下绘制界面等操作,接下来就是重头戏——对话框及其常用的操作。一般想到制作一个GUI界面,主要想实现的还是交互功能,而这就需要用到对话框。

对话框属性

  在资源界面中(双击name.rc文件(name代表工程名)或在菜单栏视图中找)可以看到有一个Dialog文件夹,这是本项目中所有的对话框,双击一个打开。
在这里插入图片描述
然后选中对话框之后,在属性栏(如果没有去视图里面找),即可看到对话框对应的属性。
在这里插入图片描述
常用属性总结如下:

属性取值及其含义
Border如果选择默认选项,则窗口不能缩放,选择resizing则可以缩放
Caption窗口的名字
ID窗口ID,不建议修改
Maximum/Minimum Box窗口最大化和最小化按钮是否显示
MENU窗口是否添加菜单栏,需要先新建一个菜单栏,而且不能出现多个对话框使用一个菜单的情况
Title Bar上面的标题栏,最好要有,不然窗口无法拖动

给对话框添加类

  确定对话框属性之后,首要的就是给对话框添加一个类,这样该对话框中的控件也就“有了家”,建立的控件对应的消息响应函数一般也都会作为这个对话框类的成员函数或变量。
  在对话框任意位置右键,选择“添加类”:
在这里插入图片描述
在这里插入图片描述

模态对话框和非模态对话框

  从上面可以看出,这个类继承的是CDialog类,也就是它含有CDialog类中全部的成员函数。对于这些,初学者不需要全部了解,但一些常用的基本操作还是得要会——比如弹出模态对话框和非模态对话框。
  按下一个按钮弹出一个对话框,这种操作可以说是交互程序中最常见的了,那么,弹出的对话框就存在两种形式——模态对话框和非模态对话框。模态是指弹出对话框之后就不能点击非对话框中的选项,必须要先处理弹出对话框的消息;而非模态,就是弹出对话框之后还可以点击其他内容(暂时先不管弹出的对话框)。
  来看几个代码:

/*模态对话框*/
//CTest是对话框添加的一个类
CTest dlg1;
dlg1.DoModal();  //弹出模态对话框

/*非模态对话框*/
//CPop是需要弹出的对话框对应的类
//先在弹出该对话框的对话框(“父对话框”)对应的类中添加一个变量,注意引用子对话框的头文件
CPop *dlg_pop;
//在弹出子对话框的消息响应程序中
dlg_pop = new CPop(); //先创建一个全局对象(记得之后给它delete掉)
dlg_pop->Create(ID_pop); //ID_pop是子对话框的ID
dlg_pop->ShowWindow(SW_SHOWNORMAL);//这个函数照抄

菜单栏

  如果新建的项目类型是单文档,那么在资源视图就会有一个MENU的文件夹,同时会有一个默认的Menu,也就是主文档视图对应的menu;如果新建的项目类型是对话框,那么资源视图默认是没有Menu文件夹的,需要自己创建,方法就是在资源视图右键,选择添加资源。
在这里插入图片描述
在这里插入图片描述
  建立菜单之后,在资源视图双击菜单,即可对它进行编辑。
在这里插入图片描述
这里需要注意的是,如果想要实现下拉菜单,那么下拉菜单的上一级的属性必须设置为Popup:在这里插入图片描述
同样,需要注意,如果需要给按钮添加事件响应程序,则需要将popup属性设置为false。

常用控件及其使用方法

  了解完了对话框的基本操作,接下来就是学习对话框中的控件了,而这我认为也是这个项目工程的核心灵魂。

1. 静态文本

  静态文本可能是这些控件当中最简单的控件了。直接在工具栏中将静态文本拖到对话框中,然后编辑Caption,使其显示不同的文字,如果没有其他什么要求,那它的使用到此为止,但如果想要调整显示文字的字体呢?就需要为静态文本添加变量,在程序中进行编辑。
在这里插入图片描述
如果出现上面的报错,就改一下静态文本的ID即可,不要用默认ID。

  之前编程的时候突然遇到静态文本添加变量的按钮是灰色的,但是可以添加类。经过新建一个工程然后仔细比对属性之后发现,如果对话框ID改变的话,就会导致这个问题,但是目前只遇到主对话框出现这个问题,其他对话框没有出现(对话框程序,不是单文档)。

附:如何设置静态文本显示字体?

2. 按钮

  对话框中的按钮使用非常简单,在对话框界面找到工具箱窗口,然后将其中的Button拖到对话框中,首先需要编辑Button的属性,一般来说就是按钮上显示的文字Caption和控件的ID
在这里插入图片描述
  设置好属性之后,就可以添加按钮的事件处理程序了,即按下这个按钮会执行哪些代码。方法就是右键按钮,选择“添加事件处理程序”:
在这里插入图片描述
在这里插入图片描述
在接下来的处理程序向导中,要选择消息类型(如单击,双击等)和所在的类(一般就选择按钮所在对话框对应的类,所以添加按钮之前要先给对话框添加一个类。)
然后就会自动跳转到对应的程序位置,编辑即可。

  创建完按钮之后,如果要删除按钮,千万别直接删除按钮,还要考虑代码部分的情况,所以在删除按钮之前,首先要先删除与之关联的消息处理程序。
  在按钮属性窗口中,点击事件处理程序(一个黄色的小闪电),找到添加的事件处理程序,然后删除,这样相关的代码就会被注释掉,编译也就不受影响了。
在这里插入图片描述

其他的控件也应该参考这种删除方式,不要贸然直接删掉,可能会导致编译不通过。

3. 文本编辑控件

  文本编辑控件,顾名思义,就是用来编辑输入文本的呗,但其实不够准确,因为它还可以显示文本,这一点需要注意。

  • 文本编辑控件在使用前要先建立一个变量,右键点击文本编辑框
    在这里插入图片描述
    在这里插入图片描述
    添加变量之后,会自动在该对话框对应的类中创建一个该变量类型的变量,所以才会有public和private的选项。
  • 文本编辑框常用的函数就是获取输入文本及设置输出文本(显示文本)
CEdit val; //对话框类中声明一个变量

//消息响应函数中
CString str_in, str_out;
val.GetWindowText(str_in);  //编辑框中输入的字符串被函数处理之后写入到变量str_in中。
val.SetWindowText(str_out);  //将str_out设置文本编辑框显示的字符串
  • 如果想让文本编辑框只显示不能输入怎么办?
    在属性栏中将Read Only设置为True。
    在这里插入图片描述
  • 如果想让文本编辑框识别换行符并多行显示怎么办?
    可以按照如下设置,然后在文本中使用“\r\n”换行
    在这里插入图片描述

编程相关

1. CString、string、char*互相转换

  前面提到,文本编辑框获取文本和设置文本得到的数据类型都是CString(据说这个数据类型实际上是根据string类型重新封装过的),而比较常用的数据类型都是string或者char*,所以涉及到一个数据类型转换的问题。

  • stringchar*相互转换
    这个其实是C++的内容,可以参考前面的教程,这里简单总结一下
/*char*到string*/
char str1[12];
....
string str2 = str1;   //char*到string直接赋值即可

/*string到char**/
string str3 = "Hello";
str3.c_str();  //得到的就是char*类型的字符串

  更加复杂的转换操作可以参考这篇教程

2. VS2005编译时出现报错“Failed to save the updated manifest to the file”

解决方法:删除解决方案,再重新编译
在这里插入图片描述

其他推荐学习教程

  • 9
    点赞
  • 134
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第1章 MFC概述 1 1.1 MFC是一个编程框架 1 1.1.1 封装 1 1.1.2 继承 2 1.1.3 虚拟函数和动态约束 2 1.1.4 MFC的宏观框架体系 2 1.2 MDI应用程序的构成 3 1.2.1 构成应用程序的对象 3 1.2.2 构成应用程序的对象之间的关系 5 1.2.3 构成应用程序的文件 5 第2章 MFC和Win32 9 2.1 MFC Object和Windows Object的关系 9 2.2 Windows Object 12 2.2.1 Windows的注册 12 2.2.2 MFC窗口类CWnd 15 2.2.3 在MFC下创建一个窗口对象 17 2.2.4 MFC窗口的使用 18 2.2.5 在MFC下窗口的销毁 19 2.3 设备描述表 20 2.3.1 设备描述表概述 20 2.3.2 设备描述表在MFC中的实现 22 2.3.3 MFC设备描述表类的使用 24 2.4 GDI对象 25 第3章 CObject类 28 3.1 CObject的结构 28 3.2 CObject类的特性 30 3.3 实现CObject特性的机制 32 3.3.1 DECLARE_DYNAMIC等宏的定义 32 3.3.2 CruntimeClass类的结构与功能 35 3.3.3 动态类信息、动态创建的原理 38 3.3.4 序列化的机制 39 第4章 消息映射的实现 42 4.1 Windows消息概述 42 4.1.1 消息的分类 42 4.1.2 消息结构和消息处理 42 4.2 消息映射的定义和实现 44 4.2.1 MFC处理的类消息 44 4.2.2 MFC消息映射的实现方法 45 4.2.3 在声明与实现的内部 46 4.2.3.1 消息映射声明的解释 47 4.2.3.2 消息映射实现的解释 49 4.2.4 消息映射宏的种类 51 4.3 CcmdTarget类 54 4.4 MFC窗口过程 55 4.4.1 MFC窗口过程的指定 56 4.4.2 对Windows消息的接收和处理 58 4.4.2.1 从窗口过程到消息映射 59 4.4.2.2 Windows消息的查找和匹配 60 4.4.2.3 Windows消息处理函数的调用 62 4.4.2.4 消息映射机制完成虚拟函数功能的原理 63 4.4.3 对命令消息的接收和处理 64 4.4.3.1 MFC标准命令消息的发送 64 4.4.3.2 命令消息的派发和消息的多次处理 67 4.4.3.3 一些消息处理类的OnCmdMsg的实现 69 4.4.3.4 一些消息处理类的OnCommand的实现 71 4.4.4 对控制通知消息的接收和处理 72 4.4.4.1 WM_COMMAND控制通知消息的处理 72 4.4.4.2 WM_NOTIFY消息及其处理: 73 4.4.4.3 消息反射 74 4.4.5 对更新命令的接收和处理 77 4.4.5.1 实现方法 77 4.4.5.2 状态更新命令消息 78 4.4.5.3 类CCmdUI 79 4.4.5.4 自动更新用户接口对象状态的机制 80 4.5 消息的预处理 82 4.6 MFC消息映射的回顾 83 第5章 MFC对象的创建 85 5.1 MFC对象的关系 85 5.1.1 创建关系 85 5.1.2 交互作用关系 86 5.2 MFC提供的接口 87 5.2.1 虚拟函数接口 87 5.2.2 消息映射方法和标准命令消息 91 5.3 MFC对象的创建过程 94 5.3.1 应用程序中典型对象的结构 94 5.3.1.1 应用程序类的成员变量 95 5.3.1.2 CDocument的成员变量 97 5.3.1.3 文档模板的属性 97 5.3.2 WinMain入口函数 99 5.3.2.1 WinMain流程 99 5.3.2.2 MFC空闲处理 101 5.3.3 SDI应用程序的对象创建 102 5.3.3.1 文档模板的创建 102 5.3.3.2 文件的创建或者打开 103 5.3.3.3 SDI边框窗口的创建 112 5.3.3.4 视的创建 115 5.3.3.5 窗口初始化 116 5.3.3.6 视的初始化 120 5.3.3.7 激活边框窗口(处理WM_ACTIVE) 121 5.3.3.8 SDI流程的回顾 122 5.3.4 MDI程序的对象创建 123 5.3.4.1 有别于SDI的主窗口加载过程 124 5.3.4.2 MDI子窗口、视、文档的创建 125 5.3.4.3 MDI子窗口的初始化和窗口的激活 127 第6章 应用程序的退出 131 6.1 边框窗口对WM_CLOSE的处理 131 6.2 窗口的销毁过程 135 6.2.1 DestroyWindow 135 6.2.2 处理WM_DESTROY消息 136 6.2.3 处理WM_NCDESTROY消息 136 6.3 SDI窗口、MDI主、子窗口的关闭 137 第7章 MFC的DLL 139 7.1 DLL的背景知识 139 7.2 调用约定 141 7.2.1 MFC的DLL应用程序的类型 142 7.3 DLL的几点说明 143 7.4 输出函数的方法 145 第8章 MFC的进程和线程 148 8.1 Win32的进程和线程概念 148 8.2 Win32的进程处理简介 148 8.2.1 进程的创建 148 8.2.2 进程的终止 149 8.3 Win32的线程 150 8.3.1 线程的创建 150 8.3.2 线程的终止 150 8.3.3 线程局部存储 151 8.4 线程同步 152 8.4.1 同步对象 152 8.4.2 等待函数 153 8.5 MFC的线程处理 154 8.5.1 创建用户界面线程 155 8.5.2 创建工作者线程 155 8.5.3 AfxBeginThread 155 8.5.4 CreateThread和_AfxThreadEntry 157 8.5.5 线程的结束 160 8.5.6 实现线程的消息循环 161 第9章 MFC的状态 163 9.1 模块状态 163 9.2 模块、进程和线程状态的数据结构 164 9.2.1 层次关系 164 9.2.2 CNoTrackObject类 166 9.2.3 AFX_MODULE_STATE类 166 9.2.4 _AFX_BASE_MODULE_STATE 169 9.2.5 _AFX_THREAD_STATE 169 9.2.6 AFX_MODULE_THREAD_STATE 171 9.3 线程局部存储机制和状态的实现 172 9.3.1 CThreadSlotData和_afxThreadData 173 9.3.1.1 CThreadSlotData的定义 173 9.3.1.2 CThreadSlotData的一些数据成员 174 9.3.1.3 _afxThreadData 175 9.3.2 线程状态_afxThreadState 176 9.3.3 进程模块状态afxBaseModuleState 178 9.3.4 状态对象的创建 180 9.3.4.1 状态对象的创建过程 180 9.3.4.2 创建过程所涉及的几个重要函数的算法 183 9.4 管理状态 184 9.4.1 模块状态切换 184 9.4.2 扩展DLL的模块状态 186 9.4.2.1 _AFX_EXTENSION_MODULE 187 9.4.2.2 扩展DLL的初始化函数 188 9.4.3 核心MFC DLL 190 9.4.4 动态链接的规则DLL的模块状态的实现 190 9.5 状态信息的作用 192 9.5.1.1 模块信息的保存和管理 192 9.5.2 MFC资源、运行类信息的查找 193 9.5.3 模块信息的显示 194 9.5.4 模块-线程状态的作用 196 9.5.4.1 只能访问本线程MFC对象的原因 196 9.5.4.2 实现MFC对象和Windows对象之间的映射 196 9.5.4.3 临时对象的处理 199 9.6 状态对象的删除和销毁 199 第10章 内存分配方式和调试机制 202 10.1 M内存分配 202 10.1.1 内存分配函数 202 10.1.2 C++的new 和 delete操作符 204 10.2 调试手段 204 10.2.1 C运行库提供和支持的调试功能 204 10.2.2 MFC提供的调试手段 205 10.2.3 内存诊断 208 第11章 MFC下的文件类 210 11.1 文件操作的方法 210 11.2 MFC的文件类 210 11.2.1 CFile的结构 211 11.2.1.1 CFile定义的枚举类型 211 11.2.1.2 CFile的其他一些成员变量 212 11.2.1.3 CFile的成员函数 212 11.2.2 CFile的部分实现 213 11.2.3 CFile的派生类 215 第12章 对话框和对话框类CDialog 217 12.1 模式和无模式对话框 217 12.1.1 模式对话框 217 12.1.2 无模式对话框 218 12.2 对话框的MFC实现 219 12.2.1 CDialog的设计和实现 219 12.2.1.1 CDialog的成员变量 219 12.2.1.2 CDialog的成员函数: 219 12.2.2 MFC模式对话框的实现 220 12.2.2.1 MFC对话框过程 220 12.2.2.2 模式对话框窗口过程 221 12.2.2.3 使用原对话框窗口过程作消息的缺省处理 225 12.2.2.4 Dialog命令消息和控制通知消息的处理 226 12.2.2.5 消息预处理和Dialog消息 228 12.2.2.6 模式对话框的消息循环 229 12.2.3 对话框的数据交换 233 12.2.3.1 数据交换的方法 233 12.2.3.2 CDataExchange 234 12.2.3.3 数据交换和验证函数 236 12.2.3.4 UpdateData函数 239 12.3 无模式对话框 240 12.3.1 CScrollView 240 12.3.2 CFormView 242 12.3.2.1 CFormView的创建 243 12.3.2.2 CFormView的消息预处理 245 12.3.2.3 CFormView的输入焦点 247 第13章 MFC工具条和状态栏 248 13.1 Windows控制窗口 248 13.2 MFC的工具条和状态栏类 249 13.2.1 控制窗口的创建 251 13.2.1.1 PreCreateWindow 251 13.2.1.2 控制条的窗口创建 253 13.2.2 控制条的销毁 259 13.2.3 处理控制条的位置 259 13.2.3.1 计算控制条位置的过程和算法 259 13.2.3.2 CFrameWnd的虚拟函数RecalcLayout 260 13.2.3.3 CWnd的成员函数RepositionBars 262 13.2.4 工具条、状态栏和边框窗口的接口 265 13.2.4.1 应用程序在状态栏中显示信息 265 13.2.4.2 状态栏显示菜单项的提示信息 268 13.2.4.3 控制条的消息分发处理 270 13.2.4.4 Tooltip 275 13.2.4.5 禁止和允许 279 13.2.4.6 显示或者隐藏工具栏和状态栏 285 13.2.5 泊位和漂浮 286 第14章 SOCKET类的设计和实现 288 14.1 WinSock基本知识 288 14.1.1 WinSock API 288 14.1.2 Socket的使用 290 14.2 MFC对WinSockt API的封装 291 14.2.1 CAsyncSocket 291 14.2.2 socket对象的创建和捆绑 292 14.2.3 异步网络事件的处理 296 14.3 CSocket 297 14.4 CSocketFile 299

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

记录无知岁月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值