欢迎光临
我们一直在努力

Windows学习笔记-10(初步使用MFC)

一、创建MFC项目的基本步骤

1、#include<afxwind.h>

2、创建一个类继承自 CWinApp

3、重写Initlnstance的虚函数

4、全局范围内定义一个唯一的CWinApp子类对象。

二、操作示例

1、先创建一个空项目,在资源文件处添加一个Dialog对话框,右键添加MFC类:

2、然后添加一个源文件,编写CWinApp派生类和创建其对象:

// 引入MFC核心头文件,提供MFC应用程序所需的基本类(如CWinApp、CWinThread等)
#include <afxwin.h>
// 引入自定义对话框类CMainDlg的头文件,该对话框将作为应用程序的主窗口
#include "CMainDlg.h"

// 定义应用程序类,继承自MFC的CWinApp类
// CWinApp是MFC应用程序的基类,每个MFC应用程序都必须有一个派生自CWinApp的类
class myApp : public CWinApp
{
public:
// 重写InitInstance函数,这是MFC应用程序的入口点
// 当应用程序启动时,MFC框架会自动调用此函数
BOOL InitInstance() override
{
// 调用基类的InitInstance,执行MFC框架所需的初始化
CWinApp::InitInstance();

// 创建主对话框对象(CMainDlg类的实例)
// CMainDlg是自定义的对话框类,通常通过资源编辑器创建对话框模板
CMainDlg mainDlg;

// 将主对话框设置为应用程序的主窗口
// m_pMainWnd是CWinApp的成员变量,指向应用程序的主窗口
m_pMainWnd = &mainDlg;

//也可使用new在堆上创建对象
//CMainDlg* pMainDlg = new CMainDlg;
//m_pMainWnd = pMainDlg;

// 以模态方式显示主对话框
// DoModal()会显示对话框并进入消息循环,直到对话框关闭
// 在此期间,用户可以与对话框进行交互
mainDlg.DoModal();

// 返回TRUE表示初始化成功,应用程序可以继续运行
// 如果返回FALSE,MFC框架会自动终止应用程序
return TRUE;
}
};

// 创建全局应用程序对象theApp
// MFC要求必须有一个全局的CWinApp派生类对象
// 当程序启动时,MFC框架会自动识别该对象并调用其InitInstance函数
myApp theApp;

无注释代码:

#include<afxwin.h>
#include"CMainDlg.h" //引入创建对话框的MFC类

class myApp : public CWinApp
{
public:
BOOL InitInstance() override
{
CWinApp::InitInstance();
CMainDlg mainDlg;
m_pMainWnd = &mainDlg;
mainDlg.DoModal();
return TRUE;
}
};

myApp theApp;

关键点说明:

  • MFC应用程序结构:

    • 每个MFC应用程序必须有一个CWinApp派生类

    • 必须重写InitInstance()函数,这是应用程序的入口点

    • 需要定义一个全局的应用程序对象

  • 程序执行流程:

  • 程序启动,MFC框架初始化

  • 框架自动调用theApp.InitInstance()

  • 在InitInstance()中创建并显示主对话框

  • 用户与对话框交互,直到关闭对话框

  • DoModal()返回,InitInstance()返回TRUE

  • 应用程序继续运行(虽然主窗口已关闭,但进程仍在)

  • 注意事项:

    • 这段代码创建的是模态对话框,对话框关闭后应用程序也会退出

    • 如果要创建非模态对话框,需要使用Create()和ShowWindow()方法

    • MFC应用程序通常使用资源文件(.rc)定义对话框布局

    • CMainDlg类需要在CMainDlg.h中定义,并继承自CDialog或CDialogEx

  • 3、设置需要的组件,指定同一组控件的第一个控件(将其组设置为true,比如这里的第一个Radio和第一个CheckBox):

    4、右键组件,添加事件处理程序

    这里给两个按钮添加单击事件处理程序

    为了获取控件的状态,可以给其添加控件变量(这里给第一个Radio和三个checkbox都选择类型为值,第四个checkbox选择为控件类型,为了演示使用的不同):

    按住Ctrl + D键可查看Tab键对应的顺序,该顺序和组的第一个控件决定分组,点击可进行修改:

    5、实现事件处理程序

    // CMainDlg.cpp: 实现文件
    //

    #include "afxdialogex.h"
    #include "CMainDlg.h"
    #include "resource.h"

    // CMainDlg 对话框

    IMPLEMENT_DYNAMIC(CMainDlg, CDialogEx)

    CMainDlg::CMainDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG1, pParent)
    , radio1(FALSE)
    , m_check1(FALSE)
    , m_check2(FALSE)
    , m_check3(FALSE)
    {

    }

    CMainDlg::~CMainDlg()
    {
    }

    void CMainDlg::DoDataExchange(CDataExchange* pDX)
    {
    CDialogEx::DoDataExchange(pDX);
    DDX_Radio(pDX, IDC_RADIO1, radio1);
    DDX_Check(pDX, IDC_CHECK1, m_check1);
    DDX_Check(pDX, IDC_CHECK2, m_check2);
    DDX_Check(pDX, IDC_CHECK3, m_check3);
    DDX_Control(pDX, IDC_CHECK4, m_check4);
    }

    BEGIN_MESSAGE_MAP(CMainDlg, CDialogEx)
    ON_BN_CLICKED(IDC_BUTTON1, &CMainDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON2, &CMainDlg::OnBnClickedButton2)
    END_MESSAGE_MAP()

    // CMainDlg 消息处理程序

    void CMainDlg::OnBnClickedButton1()
    {
    CString strbuff;
    UpdateData();
    GetDlgItemText(IDC_RADIO1 + radio1, strbuff);
    MessageBox(strbuff);

    }

    void CMainDlg::OnBnClickedButton2()
    {
    CString resbuff, tempbuff;
    UpdateData();
    if (m_check1 == BST_CHECKED)
    {
    GetDlgItemText(IDC_CHECK1, tempbuff);
    resbuff = resbuff + tempbuff;
    }
    if (m_check2 == BST_CHECKED)
    {
    GetDlgItemText(IDC_CHECK2, tempbuff);
    resbuff = resbuff + tempbuff;
    }
    if (m_check3 == BST_CHECKED)
    {
    GetDlgItemText(IDC_CHECK3, tempbuff);
    resbuff = resbuff + tempbuff;
    }
    if (m_check4.GetCheck() == BST_CHECKED)
    {
    m_check4.GetWindowTextW(tempbuff);
    resbuff = resbuff + tempbuff;
    }

    MessageBox(resbuff);
    }

    添加注释:

    // CMainDlg.cpp: 实现文件
    //

    // 引入必要的头文件
    #include "afxdialogex.h" // MFC扩展对话框类的头文件
    #include "CMainDlg.h" // 当前对话框类的头文件
    #include "resource.h" // 资源ID定义头文件,包含对话框、控件等资源ID

    // CMainDlg 对话框

    // IMPLEMENT_DYNAMIC宏实现运行时类型信息(RTTI)
    // 允许MFC框架在运行时动态创建和识别CMainDlg类
    IMPLEMENT_DYNAMIC(CMainDlg, CDialogEx)

    // 构造函数
    // pParent: 父窗口指针,默认为nullptr表示无父窗口
    CMainDlg::CMainDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG1, pParent) // 调用基类构造函数,指定对话框资源ID
    , radio1(FALSE) // 初始化单选按钮变量为FALSE(未选中)
    , m_check1(FALSE) // 初始化复选框1变量为FALSE(未选中)
    , m_check2(FALSE) // 初始化复选框2变量为FALSE(未选中)
    , m_check3(FALSE) // 初始化复选框3变量为FALSE(未选中)
    {
    // 构造函数体,这里为空,所有初始化在初始化列表中完成
    }

    // 析构函数
    CMainDlg::~CMainDlg()
    {
    // 清理资源,这里为空,因为没有动态分配的资源需要清理
    }

    // DoDataExchange函数:MFC对话框数据交换(DDX)和数据验证(DDV)的核心函数
    // pDX: CDataExchange对象指针,控制数据交换方向(对话框→变量或变量→对话框)
    void CMainDlg::DoDataExchange(CDataExchange* pDX)
    {
    // 首先调用基类的DoDataExchange
    CDialogEx::DoDataExchange(pDX);

    // DDX_Radio: 关联单选按钮组与整型变量
    // IDC_RADIO1: 单选按钮组的第一个按钮ID
    // radio1: 关联的整型变量,存储选中的单选按钮索引(0表示第一个,1表示第二个,依此类推)
    DDX_Radio(pDX, IDC_RADIO1, radio1);

    // DDX_Check: 关联复选框与BOOL变量
    // IDC_CHECK1: 复选框1的资源ID
    // m_check1: 关联的BOOL变量,存储复选框1的状态(TRUE=选中,FALSE=未选中)
    DDX_Check(pDX, IDC_CHECK1, m_check1);
    DDX_Check(pDX, IDC_CHECK2, m_check2);
    DDX_Check(pDX, IDC_CHECK3, m_check3);

    // DDX_Control: 关联控件与控件类对象(用于直接访问控件成员函数)
    // IDC_CHECK4: 复选框4的资源ID
    // m_check4: CButton类对象,可以直接调用CButton的成员函数
    // 注意:与前三个复选框不同,这里使用DDX_Control而不是DDX_Check
    // 这意味着m_check4是一个控件对象,而不是简单的BOOL值
    DDX_Control(pDX, IDC_CHECK4, m_check4);
    }

    // 消息映射宏:将Windows消息映射到类的处理函数
    // BEGIN_MESSAGE_MAP(当前类, 基类)
    BEGIN_MESSAGE_MAP(CMainDlg, CDialogEx)
    // ON_BN_CLICKED: 按钮点击事件映射
    // IDC_BUTTON1: 按钮1的资源ID
    // &CMainDlg::OnBnClickedButton1: 对应的处理函数
    ON_BN_CLICKED(IDC_BUTTON1, &CMainDlg::OnBnClickedButton1)

    // IDC_BUTTON2: 按钮2的资源ID
    ON_BN_CLICKED(IDC_BUTTON2, &CMainDlg::OnBnClickedButton2)
    END_MESSAGE_MAP() // 消息映射结束

    // CMainDlg 消息处理程序

    // 按钮1的点击事件处理函数
    void CMainDlg::OnBnClickedButton1()
    {
    CString strbuff; // 用于存储控件文本的字符串对象

    // UpdateData: 更新对话框数据
    // 参数为TRUE(默认)时:将控件值读取到关联的变量中
    // 参数为FALSE时:将变量值更新到控件显示
    UpdateData(); // 默认参数为TRUE,读取控件值到变量

    // 获取选中的单选按钮的文本
    // IDC_RADIO1 + radio1: 计算选中的单选按钮的ID
    // radio1变量存储选中的单选按钮索引(0,1,2…)
    // GetDlgItemText: 获取指定ID控件的文本
    GetDlgItemText(IDC_RADIO1 + radio1, strbuff);

    // 显示包含选中单选按钮文本的消息框
    MessageBox(strbuff);
    }

    // 按钮2的点击事件处理函数
    void CMainDlg::OnBnClickedButton2()
    {
    CString resbuff; // 结果字符串,存储所有选中复选框的文本
    CString tempbuff; // 临时字符串,存储单个复选框的文本

    UpdateData(); // 读取控件值到变量

    // 检查第一个复选框是否被选中
    // m_check1是BOOL变量,通过DDX_Check关联
    // BST_CHECKED是Windows常量,表示选中状态
    if (m_check1 == BST_CHECKED)
    {
    GetDlgItemText(IDC_CHECK1, tempbuff); // 获取复选框1的文本
    resbuff = resbuff + tempbuff; // 追加到结果字符串
    }

    // 检查第二个复选框是否被选中
    if (m_check2 == BST_CHECKED)
    {
    GetDlgItemText(IDC_CHECK2, tempbuff);
    resbuff = resbuff + tempbuff;
    }

    // 检查第三个复选框是否被选中
    if (m_check3 == BST_CHECKED)
    {
    GetDlgItemText(IDC_CHECK3, tempbuff);
    resbuff = resbuff + tempbuff;
    }

    // 检查第四个复选框是否被选中
    // m_check4是CButton对象,通过DDX_Control关联
    // GetCheck(): CButton成员函数,返回复选框状态
    if (m_check4.GetCheck() == BST_CHECKED)
    {
    // GetWindowTextW: 获取控件文本的宽字符版本
    m_check4.GetWindowTextW(tempbuff);
    resbuff = resbuff + tempbuff;
    }

    // 显示包含所有选中复选框文本的消息框
    MessageBox(resbuff);
    }

    关键点说明:

    1. DDX机制(对话框数据交换)

    • DDX_Radio: 处理单选按钮组

      • 第一个参数是单选按钮组的起始ID

      • 关联变量存储选中按钮的索引(0-based)

    • DDX_Check: 处理复选框的选中状态

      • 关联变量为BOOL类型

    • DDX_Control: 关联控件与控件类对象

      • 允许直接调用控件类的成员函数

    2. 两种处理复选框的方式对比

    方式代码示例特点适用场景
    DDX_Check DDX_Check(pDX, IDC_CHECK1, m_check1); 简单的BOOL变量 只需获取选中状态
    DDX_Control DDX_Control(pDX, IDC_CHECK4, m_check4); CButton对象 需要调用控件方法(如GetCheck())

    3. UpdateData()函数

    • UpdateData(TRUE): 控件值 → 变量(读取数据)

    • UpdateData(FALSE): 变量值 → 控件(更新显示)

    4. 单选按钮组处理技巧

    // 通过基ID + 索引的方式访问组内按钮
    GetDlgItemText(IDC_RADIO1 + radio1, strbuff);

     

     

    赞(0)
    未经允许不得转载:171主机测评 » Windows学习笔记-10(初步使用MFC)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址