最近更新于 2025-03-01 09:45
测试环境
对话框
特性 | 模态对话框(Modal) | 非模态对话框(Modeless) |
---|---|---|
阻塞性 | 阻塞主界面操作,必须先处理对话框 | 非阻塞,用户可以同时操作主界面和其他窗口 |
焦点 | 强制用户集中注意力处理对话框内容 | 用户可以自由切换焦点,灵活性高 |
使用场景 | 简单的交互,如确认操作、输入必要信息 | 复杂的交互,如工具窗口、持续可用的功能 |
示例 | 删除确认框、登录框、错误提示框 | 查找和替换窗口、属性面板、帮助窗口 |
模态对话框示例
新建一个 MFC应用
应用程序类型:基于对话框
在资源视图展开项目,在当前项目资源的 Dialog 下可以看到两个,上面一个是创建的关于窗口,下面那个就是右侧正在预览的窗口
在右侧预览窗口中点击一下,把鼠标焦点切换到这个窗口中,然后按Ctrl
+A
全选,然后按Del
删除掉这些控件
在工具箱视图中拖动一个Button控件到窗口中
在新建的这个按钮上右键属性,在属性的描述文字修改,此处的内容就是按钮上显示的内容
在资源视图的Dialog上右键插入
会新建一个对话框IDD_DIALOG1,双还是一样的操作,全选删除窗口中的默认控件。
拖一个Static Text进去
和上面按钮同样的操作方式可以修改它显示的内容
在这个窗口上右键添加类
为这个窗口创建一个类,自己命名,这里我取为ModalDialog(对于 C++ 我一般使用 .hpp 扩展名,可以用默认的 .h,后面引用这个头文件保持一致就行)
然后左侧双击可以切换打开开始创建的主窗口
在按钮上右键属性,在按钮属性里点击闪电图标
在BN_CLICKED(点击事件)后展开点Add添加事件回调方法
就自动创建了CmodalDialogProjectDlg::OnBnClickedButton1方法
在这个源文件里面添加引用上面创建的 ModalDialog 头文件
回到刚才创建的方法那里,在里面写入代码,实现弹出创建的模态对话框
ModalDialog dlg;
dlg.DoModal();
按F5
调试运行
非模态对话框示例
继续在上面的项目中修改,同样的方式再添加一个对话框窗口 IDD_DIALOG2,并为其创建类 ModelessDialog(自己命名)
在主窗口中再添加一个按钮
为这个按钮添加点击事件回调方法
再类声明中添加一个成员属性,用于存储非模态对话框,另外添加一个析构函数用于释放
private:
CDialogEx* pModelessDialog = nullptr;
public:
~CmodalDialogProjectDlg();
然后回到回调方法处,注意引用创建的非模态对话框的头文件,再写入
if (this->pModelessDialog == nullptr)
{
this->pModelessDialog = new ModelessDialog(this);
this->pModelessDialog->Create(IDD_DIALOG2);
}
this->pModelessDialog->ShowWindow(SW_SHOW);
然后添加析构函数的定义
CmodalDialogProjectDlg::~CmodalDialogProjectDlg()
{
// 检查非模态对话框指针是否已分配
if (this->pModelessDialog != nullptr)
{
// 如果非模态对话框已经创建且未销毁,则先销毁它
if (::IsWindow(this->pModelessDialog->m_hWnd))
{
this->pModelessDialog->DestroyWindow();
}
// 释放内存
delete this->pModelessDialog;
this->pModelessDialog = nullptr;
}
}
CDialogEx 是创建的自定义对话框的父类,在类声明中就声明一个变量,然后在触发打开非模态对话框的地方,先检查是否还未创建,在需要用的时候才创建一个非模态对话框,然后显示就行。下一次需要使用也可以不用创建了,直接打开显示就行。
先点出非模态对话框,主窗口是不被阻塞的,可以继续操作点出模态对话框,此时主窗口就会被模态对话框阻塞了