- MFC教程
- MFC-首页
- MFC - 概述
- MFC - 环境设置
- MFC - VC++ 项目
- MFC - 入门
- MFC - Windows 基础知识
- MFC - 对话框
- MFC - Windows 资源
- MFC - 属性表
- MFC - 窗口布局
- MFC-控制管理
- MFC-Windows 控件
- MFC - 消息和事件
- MFC-Activex 控件
- MFC-文件系统
- MFC——标准I/O
- MFC - 文档视图
- MFC-字符串
- MFC-卡雷
- MFC - 链接列表
- MFC - 数据库类
- MFC-序列化
- MFC——多线程
- MFC-- 互联网编程
- MFC-GDI
- MFC - 库
- MFC 有用资源
- MFC - 快速指南
- MFC - 有用的资源
- MFC - 讨论
MFC - 快速指南
MFC - 概述
Microsoft 基础类 (MFC) 库提供了一组函数、常量、数据类型和类来简化为 Microsoft Windows 操作系统创建应用程序的过程。在本教程中,您将了解如何使用 MFC 启动和创建基于 Windows 的应用程序。
先决条件
我们假设您知道以下内容 -
- 关于 Windows 编程的一些知识。
- C++ 编程基础知识。
- 了解面向对象编程的基础知识。
什么是MFC?
Microsoft 基础类库 (MFC) 是用于在 Microsoft Windows 中进行编程的“应用程序框架”。MFC 提供了以下所需的大部分代码 -
- 管理 Windows。
- 菜单和对话框。
- 执行基本输入/输出。
- 存储数据对象的集合等。
通过将应用程序特定的代码添加到 MFC 框架中,您可以轻松地扩展或覆盖 C++ 应用程序中 MFC 框架的基本功能。
MFC框架
MFC 框架提供了一组可重用的类,旨在简化 Windows 编程。
MFC 为许多基本对象提供了类,例如日常编程中使用的字符串、文件和集合。
它还提供常见 Windows API 和数据结构的类,例如窗口、控件和设备上下文。
该框架还为更高级的功能(例如 ActiveX 和文档视图处理)提供了坚实的基础。
此外,MFC 还提供了一个应用程序框架,包括构成应用程序体系结构层次结构的类。
为什么选择MFC?
MFC 框架是一种强大的方法,可让您在 Windows 专家程序员的工作基础上进行构建。MFC框架具有以下优点。
它缩短了开发时间。
它使代码更加可移植。
它还提供了巨大的支持,而不会降低编程自由度和灵活性。
它可以轻松访问“难以编程”的用户界面元素和技术。
MFC 通过数据访问对象 (DAO) 和开放数据库连接 (ODBC) 简化了数据库编程,并通过 Windows 套接字简化了网络编程。
MFC - 环境设置
Microsoft Visual C++ 是用于为 Microsoft Windows 操作系统创建应用程序的编程环境。要在 C++ 应用程序中使用 MFC 框架,您必须安装 Microsoft Visual C++ 或 Microsoft Visual Studio。Microsoft Visual Studio 还包含 Microsoft Visual C++ 环境。
Microsoft 提供了 Visual Studio 的免费版本,其中还包含 SQL Server,可以从https://www.visualstudio.com/en-us/downloads/downloadvisual-studio-vs.aspx下载。
以下是安装步骤。
步骤 1 - 下载 Visual Studio 后,运行安装程序。将显示以下对话框。
步骤 2 - 单击安装开始安装过程。
步骤 3 - Visual Studio 安装成功后,您将看到以下对话框。
步骤 4 - 关闭此对话框并根据需要重新启动计算机。
步骤 5 - 从“开始”菜单打开 Visual studio,这将打开以下对话框。第一次开始时,需要一些时间准备。
步骤 6 - 接下来,您将看到 Visual Studio 的主窗口。
第 7 步- 您现在已准备好开始申请。
MFC - VC++ 项目
在本章中,我们将介绍不同类型的 VC++ 项目。Visual Studio 包括多种 Visual C++ 项目模板。这些模板有助于创建基本的程序结构、菜单、工具栏、图标、引用,并包含适合您要创建的项目类型的语句。以下是模板的一些显着特征。
它为许多此类项目模板提供了向导,并帮助您在创建项目时对其进行自定义。
创建项目后,您可以构建并运行应用程序。
您不必使用模板来创建项目,但在大多数情况下,使用项目模板更有效。
修改提供的项目文件和结构比从头开始创建它们更容易。
在 MFC 中,您可以使用以下项目模板。
先生。 | 项目模板和描述 |
---|---|
1 | MFC应用 MFC 应用程序是基于 Microsoft 基础类 (MFC) 库的 Windows 可执行应用程序。创建 MFC 应用程序的最简单方法是使用 MFC 应用程序向导。 |
2 | MFC ActiveX 控件 ActiveX 控制程序是模块化程序,旨在为父应用程序提供特定类型的功能。例如,您可以创建一个控件,例如在对话框、工具栏或网页中使用的按钮。 |
3 | MFC动态链接库 MFC DLL 是一个二进制文件,充当可由多个应用程序同时使用的共享函数库。创建 MFC DLL 项目的最简单方法是使用 MFC DLL 向导。 |
以下是一些通用模板,也可用于创建 MFC 应用程序 -
先生。 | 项目模板和描述 |
---|---|
1 | 空项目 项目是构建应用程序所需的一切的逻辑容器。然后,如果需要,您可以向解决方案添加更多新的或现有的项目。 |
2 | 自定义向导 当您需要创建新的自定义向导时,可以使用 Visual C++ 自定义向导工具。创建自定义向导的最简单方法是使用自定义向导。 |
MFC - 入门
在本章中,我们将查看一个工作 MFC 示例。要创建 MFC 应用程序,您可以使用向导来自定义项目。您还可以从头开始创建应用程序。
使用项目模板创建项目
以下是使用 Visual Studio 中提供的项目模板创建项目的步骤。
步骤 1 - 打开 Visual Studio 并单击“文件”→“新建”→“项目”菜单选项。
步骤 2 - 您现在可以看到“新建项目”对话框已打开。
步骤 3 - 从左侧窗格中,选择模板 → Visual C++ → MFC
步骤 4 - 在中间窗格中,选择 MFC 应用程序。
步骤 5 - 在“名称”字段中输入项目名称“MFCDemo”,然后单击“确定”继续。您将看到以下对话框。
步骤 6 - 单击“下一步”。
步骤 7 - 选择上面给出的对话框中显示的选项,然后单击下一步。
步骤 8 - 取消选中所有选项,然后单击“完成”按钮。
现在您可以看到 MFC 向导默认创建了此对话框和项目文件。
步骤 9 - 运行此应用程序,您将看到以下输出。
从头开始创建项目
您还可以从头开始创建 MFC 应用程序。要创建 MFC 应用程序,您需要执行以下步骤。
步骤 1 - 打开 Visual Studio 并单击“文件”→“新建”→“项目”菜单选项。
步骤 2 - 您现在可以看到“新建项目”对话框。
步骤 3 - 从左窗格中,选择模板 → Visual C++ → 常规。
步骤 4 - 在中间窗格中,选择空
步骤 5 - 在“名称”字段中输入项目名称“MFCDemoFromScratch”,然后单击“确定”继续。您将看到创建了一个空项目。
步骤 6 - 要使其成为 MFC 项目,请右键单击该项目并选择“属性”。
步骤 7 - 在左侧部分,单击配置属性 → 常规。
步骤 8 - 在“项目默认值”部分中选择“在共享 DLL 中使用 MFC”选项,然后单击“确定”。
步骤 9 - 因为它现在是一个空项目;我们需要添加一个 C++ 文件。因此,右键单击该项目并选择“添加”→“新项目...”
步骤 10 -在中间窗格中选择C++ 文件 (.cpp) ,然后在名称字段中输入文件名,然后单击添加按钮。
步骤 11 - 您现在可以看到在源文件文件夹下添加的main.cpp文件。
步骤 12 - 让我们在此文件中添加以下代码。
#include <iostream> using namespace std; void main() { cout << "***************************************\n"; cout << "MFC Application Tutorial"; cout << "\n***************************************"; getchar(); }
步骤 13 - 当您运行此应用程序时,您将在控制台上看到以下输出。
*************************************** MFC Application Tutorial ***************************************
MFC - Windows 基础知识
在本章中,我们将介绍 Windows 的基础知识。要创建程序(也称为应用程序),您需要从 MFC 的 CWinApp 派生一个类。CWinApp代表Windows 应用程序类。
让我们通过创建一个新的 Win32 项目来研究一个简单的示例。
步骤 1 - 打开 Visual Studio 并单击“文件”→“新建”→“项目”菜单选项。
步骤 2 - 您现在可以看到“新建项目”对话框。
步骤 3 - 从左窗格中,选择模板 → Visual C++ → Win32。
步骤 4 - 在中间窗格中,选择 Win32 项目。
步骤 5 - 在“名称”字段中输入项目名称“MFCWindowDemo”,然后单击“确定”继续。您将看到以下对话框。
步骤 6 - 单击“下一步”。
步骤 7 - 选择上面给出的对话框中所示的选项,然后单击完成。
步骤 8 - 创建一个空项目。
步骤 9 - 要使其成为 MFC 项目,请右键单击该项目并选择“属性”。
步骤 10 - 在左侧部分,单击配置属性 → 常规。
步骤 11 - 在“项目默认值”部分中选择“在共享 DLL 中使用 MFC”选项,然后单击“确定”。
步骤 12 - 添加新的源文件。
步骤 13 - 右键单击您的项目并选择添加 → 新项目...
步骤 14 - 在模板部分中,单击 C++ 文件 (.cpp)。
步骤 15 - 将名称设置为示例,然后单击添加。
窗口创建
任何应用程序都有两个主要部分 -
- 班级
- 框架或窗户
让我们使用以下步骤创建一个窗口 -
步骤 1 - 要创建应用程序,我们需要从 MFC 的 CWinApp 派生一个类。
#include class CExample : public CWinApp { BOOL InitInstance() { return TRUE; } };
步骤 2 - 我们还需要一个框架/窗口来显示应用程序的内容。
步骤 3 - 为此,我们需要添加另一个类并从 MFC 的CFrameWnd类派生它,并实现其构造函数并调用 Create() 方法,这将创建一个框架/窗口,如以下代码所示。
class CMyFrame : public CFrameWnd { public: CMyFrame() { Create(NULL, _T("MFC Application Tutorial")); } };
步骤 4 - 正如您所看到的,Create() 方法需要两个参数,类的名称(应作为 NULL 传递)和窗口的名称(将显示在标题栏上的字符串)。
主窗口
创建窗口后,为了让应用程序使用它,可以使用指针来显示用于创建窗口的类。在这种情况下,指针将为 CFrameWnd。要使用框架窗口,请将其指针分配给 CWinThread::m_pMainWnd 成员变量。这是在应用程序的 InitInstance() 实现中完成的。
步骤 1 - 这是 CExample 类中 InitInstance() 的实现。
class CExample : public CWinApp { BOOL InitInstance() { CMyFrame *Frame = new CMyFrame(); m_pMainWnd = Frame; Frame->ShowWindow(SW_NORMAL); Frame->UpdateWindow(); return TRUE; } };
步骤 2 - 以下是 Example.cpp 文件的完整实现。
#include <afxwin.h> class CMyFrame : public CFrameWnd { public: CMyFrame() { Create(NULL, _T("MFC Application Tutorial")); } }; class CExample : public CWinApp { BOOL InitInstance() { CMyFrame *Frame = new CMyFrame(); m_pMainWnd = Frame; Frame->ShowWindow(SW_NORMAL); Frame->UpdateWindow(); return TRUE; } }; CExample theApp;
步骤 3 - 当我们运行上述应用程序时,将创建以下窗口。
窗口样式
窗口样式是控制窗口外观、边框、最小化或最大化状态或其他调整大小状态等功能的特征。
先生。 | 风格与描述 |
---|---|
1 | WS_BORDER 创建一个有边框的窗口。 |
2 | WS_CAPTION 创建一个具有标题栏的窗口(隐含 WS_BORDER 样式)。不能与 WS_DLGFRAME 样式一起使用。 |
3 | WS_CHILD 创建一个子窗口。不能与 WS_POPUP 样式一起使用。 |
4 | WS_CHILDWINDOW 与 WS_CHILD 样式相同。 |
5 | WS_CLIPCHILDREN 当您在父窗口中绘制时,排除子窗口占用的区域。创建父窗口时使用。 |
6 | WS_CLIPSIBLINGS 相对于彼此剪辑子窗口;也就是说,当特定的子窗口收到绘制消息时,WS_CLIPSIBLINGS 样式会将所有其他重叠的子窗口剪切到要更新的子窗口区域之外。(如果未给出 WS_CLIPSIBLINGS 并且子窗口重叠,则当您在子窗口的客户区域内进行绘制时,也可以在相邻子窗口的客户区域内进行绘制。)仅与 WS_CHILD 样式一起使用。 |
7 | WS_DISABLED 创建一个最初被禁用的窗口。 |
8 | WS_DLGFRAME 创建一个具有双边框但没有标题的窗口。 |
9 | WS_GROUP 指定一组控件中的第一个控件,用户可以使用箭头键从一个控件移动到下一个控件。第一个控件之后使用 WS_GROUP 样式 FALSE 定义的所有控件都属于同一组。具有 WS_GROUP 样式的下一个控件开始下一组(即,一个组在下一个组开始的地方结束)。 |
10 | WS_HSCROLL 创建一个具有水平滚动条的窗口。 |
11 | WS_ICONIC 创建一个最初最小化的窗口。与 WS_MINIMIZE 样式相同。 |
12 | WS_最大化 创建最大尺寸的窗口。 |
13 | WS_MAXIMIZEBOX 创建一个具有最大化按钮的窗口。 |
14 | WS_最小化 创建一个最初最小化的窗口。仅适用于 WS_OVERLAPPED 样式。 |
15 | WS_MINIMIZEBOX 创建一个具有最小化按钮的窗口。 |
16 | WS_重叠 创建一个重叠的窗口。重叠窗口通常有标题和边框。 |
17 号 | WS_重叠窗口 创建具有 WS_OVERLAPPED、WS_CAPTION、WS_SYSMENU、WS_THICKFRAME、WS_MINIMIZEBOX 和 WS_MAXIMIZEBOX 样式的重叠窗口。 |
18 | WS_POPUP 创建一个弹出窗口。不能与 WS_CHILD 样式一起使用。 |
19 | WS_POPUPWINDOW 创建具有 WS_BORDER、WS_POPUP 和 WS_SYSMENU 样式的弹出窗口。WS_CAPTION 样式必须与 WS_POPUPWINDOW 样式结合使用才能使控制菜单可见。 |
20 | WS_SIZEBOX 创建一个具有大小边框的窗口。与 WS_THICKFRAME 样式相同。 |
21 | WS_SYSMENU 创建一个窗口,其标题栏中有一个控制菜单框。仅用于带有标题栏的窗口。 |
22 | WS_TABSTOP 指定任意数量的控件之一,用户可以使用 TAB 键在其中移动。TAB 键将用户移动到 WS_TABSTOP 样式指定的下一个控件。 |
23 | WS_THICKFRAME 创建一个带有粗框架的窗口,可用于调整窗口的大小。 |
24 | WS_TILED 创建一个重叠的窗口。重叠窗口有标题栏和边框。与 WS_OVERLAPPED 样式相同。 |
25 | WS_TILEDWINDOW 创建具有 WS_OVERLAPPED、WS_CAPTION、WS_SYSMENU、WS_THICKFRAME、WS_MINIMIZEBOX 和 WS_MAXIMIZEBOX 样式的重叠窗口。与 WS_OVERLAPPEDWINDOW 样式相同。 |
26 | WS_VISIBLE 创建一个最初可见的窗口。 |
27 | WS_VSCROLL 创建一个具有垂直滚动条的窗口。 |
步骤 1 - 让我们看一个简单的例子,我们将在其中添加一些样式。创建窗口后,为了将其显示给用户,我们可以对其应用 WS_VISIBLE 样式,此外,我们还将添加 WS_OVERLAPPED 样式。这是一个实现 -
class CMyFrame : public CFrameWnd { public: CMyFrame() { Create(NULL, _T("MFC Application Tutorial"), WS_VISIBLE | WS_OVERLAPPED); } };
步骤 2 - 当您运行此应用程序时,将创建以下窗口。
您现在可以看到最小化、最大化和关闭选项不再出现。
窗口位置
为了定位显示器上显示的内容,计算机使用类似于笛卡尔坐标系的坐标系,但原点位于屏幕的左上角。使用该坐标系,可以通过水平轴和垂直轴距屏幕左上角的距离来定位任意点。
Win32 库提供了一个名为 POINT 的结构,定义如下 -
typedef struct tagPOINT { LONG x; LONG y; } POINT;
'x'成员变量是从屏幕左边框到该点的距离。
“y”变量表示从屏幕上边框到该点的距离。
除了Win32 的POINT 结构之外,Microsoft 基础类(MFC) 库还提供了CPoint 类。
这提供了与 POINT 结构相同的功能。作为一个 C++ 类,它添加了定位点所需的更多功能。它提供了两个构造函数。
CPoint(); CPoint(int X, int Y);
窗户尺寸
虽然点用于定位屏幕上的对象,但每个窗口都有一个大小。大小提供了与对象相关的两种度量。
- 物体的宽度。
- 物体的高度。
Win32 库使用 SIZE 结构定义如下 -
typedef struct tagSIZE { int cx; int cy; } SIZE;
除了Win32的SIZE结构外,MFC还提供了CSize类。该类具有与 SIZE 相同的功能,但添加了 C++ 类的功能。它提供了五个构造函数,允许您以您选择的任何方式创建大小变量。
CSize(); CSize(int initCX, int initCY); CSize(SIZE initSize); CSize(POINT initPt); CSize(DWORD dwSize);
窗户尺寸
当窗口显示时,可以通过其相对于监视器边框的位置在屏幕上识别它。窗口还可以通过其宽度和高度来识别。这些特征由Create()方法的rect参数指定或控制。该参数是一个可以通过 Win32 RECT 结构创建的矩形。
typedef struct _RECT { LONG left; LONG top; LONG right; LONG bottom; } RECT, *PRECT;
除了 Win32 的RECT结构之外,MFC 还提供了 CRect 类,它具有以下构造函数 -
CRect(); CRect(int l, int t, int r, int b); CRect(const RECT& srcRect); CRect(LPCRECT lpSrcRect); CRect(POINT point, SIZE size); CRect(POINT topLeft, POINT bottomRight);
让我们看一个简单的例子,我们将在其中指定窗口的位置和大小
class CMyFrame : public CFrameWnd { public: CMyFrame() { Create(NULL, _T("MFC Application Tutorial"), WS_SYSMENU, CRect(90, 120, 550, 480)); } };
当您运行此应用程序时,将在屏幕的左上角创建以下窗口,如 CRect 构造函数的前两个参数中所指定。最后两个参数是窗口的大小。
Windows 家长
在现实世界中,许多应用程序都是由不同的Windows 组成的。当应用程序使用各种 Windows 时,大多数对象都依赖于某一特定 Windows。它可能是创建的第一个窗口或您指定的另一个窗口。这样的窗口称为父窗口。所有其他窗口都直接或间接依赖于它。
如果您创建的窗口依赖于另一个窗口,您可以指定它有一个父窗口。
这是通过 CFrameWnd::Create() 方法的 pParentWnd 参数完成的。
如果该窗口没有父窗口,则传递带有 NULL 值的参数。
让我们看一个只有一个窗口的示例,并且没有可用的父窗口,因此我们将传递带有 NULL 值的参数,如以下代码所示 -
class CMyFrame : public CFrameWnd { public: CMyFrame() { Create(NULL, _T("MFC Application Tutorial"), WS_SYSMENU, CRect(90, 120, 550, 480), NULL); } };
当您运行上述应用程序时,您会看到相同的输出。
MFC - 对话框
在本章中,我们将介绍对话框。Windows 应用程序经常通过对话框与用户通信。CDialog 类提供了管理对话框的接口。Visual C++ 对话框编辑器可以轻松设计对话框并创建其对话框模板资源。
创建对话框对象是一个两阶段的操作 -
构造对话框对象。
创建对话窗口。
让我们通过创建一个新的 Win32 项目来研究一个简单的示例。
步骤 1 - 打开 Visual Studio 并单击“文件”→“新建”→“项目”菜单选项。
步骤 2 - 您现在可以看到“新建项目”对话框。
步骤 3 - 从左窗格中,选择模板 → Visual C++ → Win32。
步骤 4 - 在中间窗格中,选择 Win32 项目。
步骤 5 - 在“名称”字段中输入项目名称“MFCDialogDemo”,然后单击“确定”继续。您将看到以下对话框。
步骤 6 - 单击“下一步”。
步骤 7 - 选择上面给出的对话框中显示的选项,然后单击完成。
步骤 8 - 创建一个空项目。
步骤 9 - 要使其成为 MFC 项目,请右键单击该项目并选择“属性”。
步骤 10 - 在左侧部分,单击配置属性 → 常规。
步骤 11 - 在“项目默认值”部分中选择“在共享 DLL 中使用 MFC”选项,然后单击“确定”。
步骤 12 - 添加新的源文件。
步骤 13 - 右键单击您的项目并选择添加 → 新项目。
步骤 14 - 在模板部分中,单击 C++ 文件 (.cpp)
步骤 15 - 将名称设置为示例,然后单击添加。
步骤 16 - 要创建应用程序,我们需要添加一个类并从 MFC 的 CWinApp 派生它。
#include <afxwin.h> class CExample : public CWinApp { public: BOOL InitInstance(); };
对话框创建
步骤 1 - 要创建对话框,请右键单击解决方案资源管理器中的资源文件文件夹,然后选择添加 → 资源。
步骤 2 - 在“添加资源”对话框中,选择“对话框”并单击“新建”。
步骤 3 - 对话框在实际以编程方式创建之前需要进行一些准备。
步骤 4 - 首先可以手动将对话框创建为文本文件(在资源文件中)。
步骤 5 - 您现在可以看到在资源文件下创建的 MFCDialogDemo.rc 文件。
步骤 6 - 资源文件在设计器中打开。同样可以作为文本文件打开。右键单击资源文件并选择打开方式。
步骤 7 - 选择源代码(文本)编辑器并单击添加按钮。
步骤 8 - 返回设计器并右键单击对话框并选择属性。
步骤 9 - 您需要从众多选项中进行选择。
步骤 10 - 与大多数其他控件一样,必须识别对话框。对话框的标识符(ID)通常以IDD_开头,让我们将ID更改为IDD_EXAMPLE_DLG。
对话框位置
对话框必须“物理”位于应用程序上。由于对话框通常被创建为其他控件的父级,因此其位置取决于其与其父窗口或桌面的关系。
如果查看“属性”窗口,您会看到两个字段:“X 位置”和“Y 位置”。
X 是从显示器左边框到对话框左边框的距离。
Y 是从显示器上边框到对话框上边框的距离。
默认情况下,这些字段设置为零。您也可以按照上图进行更改。
如果将这两个尺寸指定为 0,则将设置对话框的左边框和上边框,以便对象出现在屏幕的中间位置。
对话框尺寸
对话框的尺寸是指其宽度和高度。您可以在设计器窗口中使用鼠标调整宽度和高度的大小。
您可以在状态栏上看到宽度和高度的变化。
对话框方法
用于在屏幕上显示对话框的基类是CDialog类。要创建对话框,我们需要从 CDialog 派生一个类。CDialog 类本身提供了三个构造函数,如下所示 -
CDialog(); CDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL); CDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);
让我们创建另一个类 CExampleDlg 并从 CDialog 派生它。我们将实现其默认构造函数析构函数,如以下代码所示。
class CExampleDlg : public CDialog { public: enum { IDD = IDD_EXAMPLE_DLG }; CExampleDlg(); ~CExampleDlg(); }; CExampleDlg::CExampleDlg():CDialog(CExampleDlg::IDD) { } CExampleDlg::~CExampleDlg() { }
我们需要在 CExample::InitInstance() 方法上实例化此对话框,如以下代码所示。
BOOL CExample::InitInstance() { CExampleDlg myDlg; m_pMainWnd = &myDlg; return TRUE; }
模态对话框
有两种类型的对话框 -无模式和模式。模态对话框和非模态对话框的不同之处在于创建和显示它们的过程。
非模式对话框
对于无模式对话框,您必须在对话框类中提供自己的公共构造函数。
要创建无模式对话框,请调用公共构造函数,然后调用对话框对象的 Create 成员函数来加载对话框资源。
您可以在构造函数调用期间或之后调用 Create。如果对话框资源具有 WS_VISIBLE 属性,则对话框会立即出现。
如果没有,则必须调用其 ShowWindow 成员函数。
模态对话框
要创建模式对话框,请调用 CDialog 中声明的两个公共构造函数之一。
接下来,调用对话框对象的DoModal成员函数来显示对话框并管理与其交互,直到用户选择“确定”或“取消”。
DoModal 的这种管理使得对话框成为模态的。对于模式对话框,DoModal 加载对话框资源。
步骤 1 - 要将对话框显示为模式对话框,请在 CExample::InitInstance() 事件中使用对话框变量调用 DoModal() 方法 -
BOOL CExample::InitInstance() { CExampleDlg myDlg; m_pMainWnd = &myDlg; myDlg.DoModal(); return TRUE; }
步骤 2 - 这是Example.cpp 文件的完整实现。
#include <afxwin.h> #include "resource.h" class CExample : public CWinApp { public: BOOL InitInstance(); }; class CExampleDlg : public CDialog { public: enum { IDD = IDD_EXAMPLE_DLG }; CExampleDlg(); ~CExampleDlg(); }; CExampleDlg::CExampleDlg():CDialog(CExampleDlg::IDD) { } CExampleDlg::~CExampleDlg() { } BOOL CExample::InitInstance() { CExampleDlg myDlg; m_pMainWnd = &myDlg; myDlg.DoModal(); return TRUE; } CExample MyApp;
步骤 3 - 编译并执行上述代码后,您将看到以下对话框。
基于对话的应用程序
Microsoft Visual Studio 提供了一种更简单的方法来创建主要基于对话框的应用程序。以下是使用 Visual Studio 中提供的项目模板创建对话框基础项目的步骤 -
步骤 1 - 打开 Visual Studio 并单击“文件”→“新建”→“项目”菜单选项。您可以看到“新建项目”对话框。
步骤 2 - 从左窗格中,选择模板 → Visual C++ → MFC。
步骤 3 - 在中间窗格中,选择 MFC 应用程序。
步骤 4 - 在“名称”字段中输入项目名称“MFCModalDemo”,然后单击“确定”继续。您将看到以下对话框。
步骤 5 - 单击“下一步”。
步骤 6 - 选择上面对话框中显示的选项,然后单击下一步。
步骤 7 - 检查您在对话框中选择的所有选项,例如最大化和最小化框,然后单击下一步。
步骤 8 - 单击“下一步”。
步骤 9 - 它将生成这两个类。您可以更改类的名称,然后单击“完成”。
步骤 10 - 您现在可以看到 MFC 向导默认创建此对话框和项目文件。
步骤 11 - 当您运行此应用程序时,您将看到以下输出。
MFC - Windows 资源
资源是一种文本文件,允许编译器管理图片、声音、鼠标光标、对话框等对象。Microsoft Visual Studio 通过在用于编程的同一环境中提供必要的工具,使创建资源文件变得特别容易。这意味着,您通常不必使用外部应用程序来创建或配置资源文件。以下是与资源相关的一些重要功能。
资源是向用户提供信息的界面元素。
位图、图标、工具栏和光标都是资源。
可以操纵某些资源来执行操作,例如从菜单中选择或在对话框中输入数据。
应用程序可以使用Behave相互独立的各种资源,这些资源被分组到具有 *.rc 扩展名的文本文件中。
大多数资源是通过从“添加资源”对话框中选择所需的资源来创建的。
“添加资源”对话框提供了可根据要求使用的广泛资源列表,但如果您需要不可用的资源,则可以在执行程序之前将其手动添加到 *.rc 文件中。
身份标识
标识符是一个符号,它是一个常量整数,其名称通常以 ID 开头。它由两部分组成 - 映射到整数值(符号值)的文本字符串(符号名称)。
符号提供了一种在源代码中以及在资源编辑器中使用资源和用户界面对象时引用资源和用户界面对象的描述性方式。
创建新资源或资源对象时,资源编辑器会为资源提供默认名称(例如 IDC_DIALOG1),并为其分配一个值。
名称加值定义存储在 Resource.h 文件中。
步骤 1 - 让我们看看上一章中的CMFCDialogDemo示例,其中我们创建了一个对话框,其 ID 为IDD_EXAMPLE_DLG。
步骤2 - 转到解决方案资源管理器,您将在头文件下看到resource.h 文件。继续在编辑器中打开此文件,您还将看到对话框标识符及其整数值。
图标
图标是窗口上使用的代表应用程序的小图片。它用于两个主要场景。
在窗口框架上,它显示在标题栏上窗口名称的左侧。
在 Windows 资源管理器、桌面、我的电脑或控制面板窗口中。
如果您查看我们的 MFCModalDemo 示例,您将看到 Visual Studio 在标题栏上使用默认图标,如以下快照所示。
您可以按照以下步骤创建自己的图标 -
步骤 1 - 右键单击您的项目并选择“添加”→“资源”,您将看到“添加资源”对话框。
步骤 2 - 选择图标并单击新建按钮,您将看到以下图标。
步骤 3 - 在解决方案资源管理器中,转到资源视图并展开 MFCModalDemo > 图标。您将看到两个图标。IDR_MAINFRAME 是默认图标,IDI_ICON1 是新创建的图标。
步骤 4 - 右键单击新创建的图标并选择属性。
步骤 5 - IDI_ICON1 是该图标的 ID,现在让我们将此 ID 更改为 IDR_MYICON。
步骤 6 - 您现在可以根据您的要求在设计器中更改此图标。我们将使用相同的图标。
步骤 7 - 保存此图标。
步骤 8 - 转到 CMFCModalDemoDlg.cpp 文件中的 CMFCModalDemoDlg 构造函数,该构造函数将类似于以下代码。
CMFCModalDemoDlg::CMFCModalDemoDlg(CWnd* pParent /* = NULL*/) : CDialogEx(IDD_MFCMODALDEMO_DIALOG, pParent) { m_hIcon = AfxGetApp() -> LoadIcon(IDR_MAINFRAME); }
步骤 9 - 您现在可以看到默认图标已加载到构造函数中。让我们将其更改为 IDR_ MYICON,如以下代码所示。
CMFCModalDemoDlg::CMFCModalDemoDlg(CWnd* pParent /* = NULL*/) : CDialogEx(IDD_MFCMODALDEMO_DIALOG, pParent) { m_hIcon = AfxGetApp() -> LoadIcon(IDR_ MYICON); }
步骤 10 - 编译并执行上述代码后,您将看到对话框中显示新图标。
菜单
菜单允许您以逻辑且易于查找的方式排列命令。使用菜单编辑器,您可以直接使用与已完成的应用程序中的菜单栏非常相似的菜单栏来创建和编辑菜单。要创建菜单,请按照以下步骤操作 -
步骤 1 - 右键单击您的项目并选择添加 → 资源。您将看到“添加资源”对话框。
步骤 2 - 选择菜单并单击新建。您将在菜单栏上看到包含“在此处键入”的矩形。
步骤 3 - 编写一些菜单选项,如文件、编辑等,如下面的快照所示。
步骤 4 - 如果在资源视图中展开菜单文件夹,您将看到菜单标识符 IDR_MENU1。右键单击该标识符并将其更改为 IDM_MAINMENU。
步骤 5 - 保存所有更改。
步骤 6 - 我们需要将此菜单附加到我们的对话框中。在解决方案资源管理器中展开对话框文件夹,然后双击对话框标识符。
步骤 7 - 您将在属性中看到菜单字段。从下拉列表中选择菜单标识符,如上所示。
步骤 8 - 运行此应用程序,您将看到以下对话框,其中也包含菜单选项。
工具栏
工具栏是一个 Windows 控件,它允许用户通过单击按钮而不是使用菜单来在窗体上执行某些操作。
工具栏提供了一组方便的按钮,通过将最容易访问的操作作为按钮来简化用户的工作。
工具栏可以使此类常见操作更贴近用户。
工具栏通常显示在主菜单下。
它们可以配备按钮,但有时它们的按钮或某些按钮有标题。
工具栏还可以配备其他类型的控件。
要创建工具栏,请执行以下步骤。
步骤 1 - 右键单击您的项目并选择添加 → 资源。您将看到“添加资源”对话框。
步骤 2 - 选择工具栏并单击新建。您将看到以下屏幕。
步骤 3 - 在设计器中设计工具栏,如下面的屏幕截图所示,并指定 ID。
步骤 4 - 在 CMFCModalDemoDlg 类中添加这两个变量。
CToolBar m_wndToolBar; BOOL butD;
步骤 5 - 以下是 CMFCModalDemoDlg.h 文件中 CMFCModalDemoDlg 的完整实现 -
class CMFCModalDemoDlg : public CDialogEx { // Construction public: CMFCModalDemoDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data #ifdef AFX_DESIGN_TIME enum { IDD = IDD_MFCMODALDEMO_DIALOG }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected: HICON m_hIcon; CToolBar m_wndToolBar; BOOL butD; // Generated message map functions virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedOk(); };
步骤 6 - 更新 CMFCModalDemoDlg::OnInitDialog(),如以下代码所示。
BOOL CMFCModalDemoDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon if (!m_wndToolBar.Create(this) || !m_wndToolBar.LoadToolBar(IDR_TOOLBAR1)) //if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | // WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | // CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || // !m_wndToolBar.LoadToolBar(IDR_TOOLBAR1)) { TRACE0("Failed to Create Dialog Toolbar\n"); EndDialog(IDCANCEL); } butD = TRUE; CRect rcClientOld; // Old Client Rect CRect rcClientNew; // New Client Rect with Tollbar Added // Retrive the Old Client WindowSize // Called to reposition and resize control bars in the client area of a window // The reposQuery FLAG does not really traw the Toolbar. It only does the calculations. // And puts the new ClientRect values in rcClientNew so we can do the rest of the Math. GetClientRect(rcClientOld); RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0, reposQuery, rcClientNew); // All of the Child Windows (Controls) now need to be moved so the Tollbar does not cover them up. // Offest to move all child controls after adding Tollbar CPoint ptOffset(rcClientNew.left - rcClientOld.left, rcClientNew.top - rcClientOld.top); CRect rcChild; CWnd* pwndChild = GetWindow(GW_CHILD); //Handle to the Dialog Controls while (pwndChild) // Cycle through all child controls { pwndChild -> GetWindowRect(rcChild); // Get the child control RECT ScreenToClient(rcChild); // Changes the Child Rect by the values of the claculated offset rcChild.OffsetRect(ptOffset); pwndChild -> MoveWindow(rcChild, FALSE); // Move the Child Control pwndChild = pwndChild -> GetNextWindow(); } CRect rcWindow; // Get the RECT of the Dialog GetWindowRect(rcWindow); // Increase width to new Client Width rcWindow.right += rcClientOld.Width() - rcClientNew.Width(); // Increase height to new Client Height rcWindow.bottom += rcClientOld.Height() - rcClientNew.Height(); // Redraw Window MoveWindow(rcWindow, FALSE); // Now we REALLY Redraw the Toolbar RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control }
步骤 7 - 运行此应用程序。您将看到以下对话框,其中也包含工具栏。
加速器
访问键是一个字母,允许用户使用键盘而不是鼠标更快地执行菜单操作。这通常更快,因为用户不需要将鼠标放置在任何地方,从而减少了执行操作所需的时间。
步骤 1 - 要创建访问键,请在菜单项左侧键入与号“&”。
步骤 2 - 对所有菜单选项重复此步骤。运行此应用程序并按 Alt。您将看到所有菜单选项的第一个字母都带有下划线。
快捷键
快捷键是高级用户用来执行本来要在菜单项上执行的操作的键或键组合。大多数快捷键是同时按下 Ctrl 键和字母键的组合。例如,Ctrl + N、Ctrl + O 或 Ctrl + D。
要创建快捷方式,请在组成菜单标题的字符串的右侧,右键单击菜单项并选择属性。
在“标题”字段中,输入 \t,后跟所需的组合,如下所示,用于“新建”菜单选项。对所有菜单选项重复该步骤。
加速表
加速键表是一个项目列表,其中表中的每个项目都包含一个标识符、一个快捷键和一个指定加速键类型的常量。就像其他资源一样,可以在 .rc 文件中手动创建加速器表。以下是创建加速器表的步骤。
步骤 1 - 要创建加速器表,请右键单击解决方案资源管理器中的 *.rc 文件。
步骤 2 - 选择加速器并单击新建。
步骤 3 - 单击 ID 组合框的箭头并选择菜单项。
步骤 4 - 从修饰符下拉列表中选择 Ctrl。
步骤 5 - 单击“密钥”框并键入两个菜单选项各自的密钥。
我们还将添加新菜单项事件处理程序进行测试。右键单击“新建”菜单选项。
步骤 6 - 您可以指定类、消息类型和处理程序名称。现在,让我们保持原样,然后单击“添加和编辑”按钮。
步骤 7 - 选择添加事件处理程序。
步骤 8 - 您现在将看到添加在 CMFCModalDemoDlg.cpp 文件末尾的事件。
void CMFCModalDemoDlg::OnFileNew() { // TODO: Add your command handler code here MessageBox(L"File > New menu option"); }
步骤 9 -现在让我们添加一个消息框,它将显示简单的菜单选项消息。
要在工作中启动加速器表,请添加 HACCEL 变量和 ProcessMessageFilter,如以下 CMFCModalDemoApp 中所示。
class CMFCModalDemoApp : public CWinApp { public: CMFCModalDemoApp(); // Overrides public: virtual BOOL InitInstance(); HACCEL m_hAccelTable; // Implementation DECLARE_MESSAGE_MAP() virtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg); };
步骤 10 - 加载加速器并在 CMFCModalDemoApp::InitInstance() 中进行以下调用。
m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR1));
步骤 11 - 这是 ProcessMessageFilter 的实现。
BOOL CMFCModalDemoApp::ProcessMessageFilter(int code, LPMSG lpMsg) { if (code >= 0 && m_pMainWnd && m_hAccelTable) { if (::TranslateAccelerator(m_pMainWnd -> m_hWnd, m_hAccelTable, lpMsg)) return TRUE; } return CWinApp::ProcessMessageFilter(code, lpMsg); }
步骤 12 - 编译并执行上述代码后,您将看到以下输出。
步骤 13 - 按 Alt 按钮,然后按 F 键,然后按 N 键或 Ctrl + N。您将看到以下消息。
MFC - 属性表
属性表,也称为选项卡对话框,是包含属性页的对话框。每个属性页都基于对话框模板资源并包含控件。它包含在一个页面上,顶部有一个选项卡。该选项卡为页面命名并指示其用途。用户单击属性表中的选项卡来选择一组控件。
为了创建属性页,让我们通过创建基于对话框的 MFC 项目来研究一个简单的示例。
创建项目后,我们需要添加一些属性页。
Visual Studio 通过显示“添加资源”对话框、展开“对话框”节点并选择 IDD_PROPPAGE_X 项之一,可以轻松地为属性页创建资源。
步骤 1 - 在解决方案资源管理器中右键单击您的项目,然后选择添加 → 资源。
步骤 2 - 选择 IDD_PROPPAGE_LARGE 并单击新建。
步骤 3 - 让我们将该属性页的 ID 和标题分别更改为IDD_PROPPAGE_1和属性页 1,如上所示。
步骤 4 - 右键单击设计器窗口中的属性页。
步骤 5 - 选择添加类别选项。
步骤 6 - 输入类名称并从基类下拉列表中选择 CPropertyPage。
步骤 7 - 单击“完成”继续。
步骤 8 - 按照上述步骤添加一个 ID IDD_PROPPAGE_2 和标题属性页 2 的属性页。
步骤 9 - 您现在可以看到创建的两个属性页。为了实现其功能,我们需要一个属性表。
属性表将属性页组合在一起并将其作为实体。
要创建属性表,请按照以下步骤操作 -
步骤 1 - 右键单击您的项目并选择“添加”>“类”菜单选项。
步骤 2 - 从左侧窗格中选择 Visual C++ → MFC,在模板窗格中选择 MFC 类,然后单击添加。
步骤 3 - 输入类名称并从基类下拉列表中选择 CPropertySheet。
步骤 4 - 单击“完成”继续。
步骤 5 - 要启动此属性表,我们需要在主项目类中进行以下更改。
步骤 6 - 在 CMFCPropSheetDemo.cpp 文件中添加以下引用。
#include "MySheet.h" #include "PropPage1.h" #include "PropPage2.h"
步骤 7 - 修改 CMFCPropSheetDemoApp::InitInstance() 方法,如以下代码所示。
CMySheet mySheet(L"Property Sheet Demo"); CPropPage1 page1; CPropPage2 page2; mySheet.AddPage(&page1); mySheet.AddPage(&page2); m_pMainWnd = &mySheet; INT_PTR nResponse = mySheet.DoModal();
步骤 8 - 这是 CMFCPropSheetDemo.cpp 文件的完整实现。
// MFCPropSheetDemo.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "MFCPropSheetDemo.h" #include "MFCPropSheetDemoDlg.h" #include "MySheet.h" #include "PropPage1.h" #include "PropPage2.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMFCPropSheetDemoApp BEGIN_MESSAGE_MAP(CMFCPropSheetDemoApp, CWinApp) ON_COMMAND(ID_HELP, &CWinApp::OnHelp) END_MESSAGE_MAP() // CMFCPropSheetDemoApp construction CMFCPropSheetDemoApp::CMFCPropSheetDemoApp() { // support Restart Manager m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART; // TODO: add construction code here, // Place all significant initialization in InitInstance } // The one and only CMFCPropSheetDemoApp object CMFCPropSheetDemoApp theApp; // CMFCPropSheetDemoApp initialization BOOL CMFCPropSheetDemoApp::InitInstance() { // InitCommonControlsEx() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable // visual styles. Otherwise, any window creation will fail. INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); // Set this to include all the common control classes you want to use // in your application. InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); AfxEnableControlContainer(); // Create the shell manager, in case the dialog contains // any shell tree view or shell list view controls. CShellManager *pShellManager = new CShellManager; // Activate "Windows Native" visual manager for enabling themes in MFC controls CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows)); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need // Change the registry key under which our settings are stored // TODO: You should modify this string to be something appropriate // such as the name of your company or organization SetRegistryKey(_T("Local AppWizard-Generated Applications")); CMySheet mySheet(L"Property Sheet Demo"); CPropPage1 page1; CPropPage2 page2; mySheet.AddPage(&page1); mySheet.AddPage(&page2); m_pMainWnd = &mySheet; INT_PTR nResponse = mySheet.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK }else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel }else if (nResponse == -1) { TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\n"); TRACE(traceAppMsg, 0, "Warning: if you are using MFC controls on the dialog, you cannot #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS.\n"); } // Delete the shell manager created above. if (pShellManager != NULL) { delete pShellManager; } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; }
步骤 9 - 编译并执行上述代码后,您将看到以下对话框。该对话框包含两个属性页。
MFC - 窗口布局
控件的布局对于应用程序的可用性非常重要且至关重要。它用于在应用程序中排列一组 GUI 元素。选择布局时需要考虑一些重要事项 -
- 子元素的位置。
- 子元素的大小。
添加控件
让我们创建新的基于对话框的 MFC 项目 MFCLayoutDemo。
步骤 1 - 创建项目后,您将看到以下屏幕。
步骤 2 - 从对话框中删除 TODO。
步骤 3 - 从工具箱中拖动一些控件,您可以在左侧看到这些控件。
(我们将拖动一个静态文本和一个编辑控件,如下面的快照所示)。
步骤 4 - 将静态文本的标题更改为名称。
控制网格
控制网格是引导网格点,它可以帮助定位您在设计时添加的控件。
要启用控制网格,您需要单击工具栏中的“切换网格”按钮,如下图所示。
控制调整大小
将控件添加到对话框后,它会采用默认大小或您绘制它时使用的大小。为了帮助调整窗体或对话框上控件的大小,Visual Studio 提供了由黑点组成的可视网格。
要调整控件的大小,即为其指定特定的宽度或高度,请将鼠标放在其中一个手柄上,然后将其向所需的方向拖动。
现在,您可以借助此虚线网格来调整控件的大小。
控制位置
这