当前位置: 首页 > news >正文

MFC 主程序显示 模态对话框

两种创建模式完整可运行代码

前置约定

  • 子对话框类:CChildDlg(Child 无边框样式,用于嵌入 Static 容器)
  • 容器控件 ID:IDC_CONTAINER(非默认 IDC_STATIC)
  • 父窗口类:CMainDlg

模式 1:栈对象成员变量(推荐,常驻嵌入)

1. 父窗口头文件 CMainDlg.h

cpp

运行

#include "ChildDlg.h" class CMainDlg : public CDialogEx { // ... private: // 栈对象,全局生命周期,无需手动释放 CChildDlg m_childDlg; protected: virtual BOOL OnInitDialog(); afx_msg void OnSize(UINT nType, int cx, int cy); DECLARE_MESSAGE_MAP() };

2. 父窗口 OnInitDialog 创建嵌入窗口

cpp

运行

BOOL CMainDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 获取容器控件坐标 CWnd* pContainer = GetDlgItem(IDC_CONTAINER); CRect rcContainer; pContainer->GetWindowRect(&rcContainer); ScreenToClient(&rcContainer); // 创建子对话框(仅执行一次) m_childDlg.Create(IDD_CHILD_DLG, this); // 绑定容器作为父窗口,真正嵌入 m_childDlg.SetParent(pContainer); // 填满容器区域 m_childDlg.MoveWindow(0, 0, rcContainer.Width(), rcContainer.Height()); m_childDlg.ShowWindow(SW_SHOW); return TRUE; }

3. 窗口缩放自适应 OnSize

cpp

运行

void CMainDlg::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); // 判断子窗口是否创建成功 if (!m_childDlg.GetSafeHwnd()) return; CWnd* pContainer = GetDlgItem(IDC_CONTAINER); CRect rcClient; pContainer->GetClientRect(&rcClient); m_childDlg.MoveWindow(&rcClient); }

4. 手动隐藏 / 销毁(可选)

cpp

运行

// 仅隐藏,保留句柄,下次直接Show m_childDlg.ShowWindow(SW_HIDE); m_childDlg.ShowWindow(SW_SHOW); // 彻底销毁(一般不需要,析构自动释放) m_childDlg.DestroyWindow();

优点

栈对象随父窗口自动析构,无内存泄漏;代码极简,适合常驻内嵌界面。


模式 2:堆指针(动态创建 / 销毁,按需切换界面)

1. 父窗口头文件 CMainDlg.h

cpp

运行

#include "ChildDlg.h" class CMainDlg : public CDialogEx { // ... private: // 堆指针,手动管理生命周期 CChildDlg* m_pChildDlg = nullptr; protected: virtual BOOL OnInitDialog(); afx_msg void OnBtnCreateChild(); afx_msg void OnBtnDestroyChild(); virtual ~CMainDlg(); // 析构兜底释放 DECLARE_MESSAGE_MAP() };

2. 动态创建子窗口(按钮触发)

cpp

运行

void CMainDlg::OnBtnCreateChild() { // 防止重复创建 if (m_pChildDlg != nullptr && m_pChildDlg->GetSafeHwnd()) return; CWnd* pContainer = GetDlgItem(IDC_CONTAINER); CRect rcContainer; pContainer->GetWindowRect(&rcContainer); ScreenToClient(&rcContainer); // new 堆分配 m_pChildDlg = new CChildDlg(this); m_pChildDlg->Create(IDD_CHILD_DLG, this); m_pChildDlg->SetParent(pContainer); m_pChildDlg->MoveWindow(0, 0, rcContainer.Width(), rcContainer.Height()); m_pChildDlg->ShowWindow(SW_SHOW); }

3. 手动销毁子窗口(按钮触发)

cpp

运行

void CMainDlg::OnBtnDestroyChild() { if (m_pChildDlg == nullptr) return; // 销毁窗口 + 释放堆内存 m_pChildDlg->DestroyWindow(); delete m_pChildDlg; m_pChildDlg = nullptr; }

4. 父窗口析构函数(兜底防内存泄漏)

cpp

运行

CMainDlg::~CMainDlg() { // 窗口关闭时强制释放 if (m_pChildDlg != nullptr) { m_pChildDlg->DestroyWindow(); delete m_pChildDlg; m_pChildDlg = nullptr; } }

5. 自适应缩放 OnSize(同栈对象逻辑)

cpp

运行

void CMainDlg::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); if (m_pChildDlg == nullptr || !m_pChildDlg->GetSafeHwnd()) return; CWnd* pContainer = GetDlgItem(IDC_CONTAINER); CRect rcClient; pContainer->GetClientRect(&rcClient); m_pChildDlg->MoveWindow(&rcClient); }

适用场景

需要频繁切换、打开 / 关闭内嵌子界面;多个不同子对话框动态切换容器。


两种模式核心区别总结

表格

模式内存管理创建时机销毁方式适用场景
栈成员变量自动释放,无泄漏父窗口初始化一次性创建父窗口销毁自动释放长期固定内嵌界面
堆指针 new必须手动 delete,否则泄漏按钮 / 事件按需创建手动 DestroyWindow+delete动态切换、临时内嵌界面

关键注意事项

  1. 子对话框资源必须设置:Style=ChildBorder=None,否则无法嵌入;
  2. 容器控件 ID 不能是默认IDC_STATIC,否则无法获取句柄;
  3. 模态对话框DoModal()不能嵌入控件,仅支持Create()非模态子窗口。
http://www.jsqmd.com/news/1094382/

相关文章:

  • Untrunc视频修复工具终极指南:三步拯救损坏的MP4视频文件
  • Anthropic零感层:大模型服务栈的协议级坍缩与上下文治理革命
  • WPF LiveCharts 实时数据流卡顿?五大优化策略解锁流畅绘图
  • 基于图像验证的反钓鱼技术:从视觉特征到工程实践
  • 企业官网做 GEO 时,Schema JSON-LD 应该怎么配合?
  • 计算机毕业设计之基于SSM框架的连锁酒店经销商订货系统的设计与实现
  • 新衣洗几次就变旧
  • ChatGPT Plus开通即亏?资深AI工程师用Python自动化监控+日志分析,揭露你被忽略的3个使用临界点
  • AI 多功能石英钟智能功率 MOSFET 完整选型方案
  • N_m3u8DL-RE架构解析与企业级流媒体下载实战指南
  • 计算机毕业设计之基于SSM框架的高校运动会管理系统的设计与实现
  • 如何在5分钟内将任何单张图片转换为专业PSD分层文件:Layerdivider智能图像分层技术解析
  • GEE实战:从CHIRPS数据集中批量下载多时间尺度降水数据
  • MicroPython BLE HID库:零基础打造终极蓝牙控制设备的完整指南
  • Twitch视频下载终极指南:轻松保存你喜爱的直播内容
  • 国产工业 DC-DC 模块电源硬件选型技术解析:URB1215ZP-10WR3 与钡特电源 VB10-12S15P 厂家口碑推荐,10W 隔离电源参数对照
  • MCMS v5.4.1文件上传漏洞深度剖析:从代码审计到RCE攻击链构建
  • 气体检测核心器件国产替代:从“卡脖子”到“全自主”还有多远?
  • 2026车间夏季薄款工装,透气清爽干活更带劲
  • openCode vs Cursor,我为什么最终选了 openCode
  • ChatGPT函数调用可靠性SLO达成率低于89%?用这6个可观测性埋点+Prometheus告警模板,1小时定位根因
  • 一套注塑模具从设计到量产的数字化验证实录:蓝光3D扫描如何“兜底”质量?
  • ChatGPT Plus退订失败?92%用户踩中的5大隐形障碍,含Apple Family Sharing绑定冲突、Stripe支付网关冻结、OpenAI账户状态校验异常(附实时检测命令行工具)
  • YgoMaster终极指南:3种方式快速搭建本地游戏王PvP对战环境
  • 深入AMD Ryzen内核:SMU Debug Tool完整使用指南
  • 自建房装电梯,如何判断一台电梯真正靠谱?
  • 2026高端FPGA硬件平台深度解析与前瞻部署指南
  • Git里的origin到底是什么意思?
  • Java 开发工具 IDEA 2025.2 社区版完整安装实操指南
  • SSRF漏洞深度解析:从原理到高级绕过与防御实战