如何通过编程设置无模式对话框使其完全不显示(无瞬间闪烁)
解决无模式对话框闪烁并完全隐藏的问题
问题描述
应用中有两个基于模态对话框的编辑器,测试时需在一个编辑器内调用另一个编辑器(以无模式对话框加载)获取数据,但该无模式对话框会出现闪烁。尝试提前修改窗口样式去除WS_VISIBLE无效,推测是Create方法加载资源时覆盖了样式修改。
原测试代码:
void CChristianLifeMinistryEditorDlg::EditDutyAssignments() { auto pDlgReport = std::make_unique<CCreateReportDlg>(); if (pDlgReport != nullptr && m_pEntry != nullptr) { pDlgReport->SetFileToOpen(L"d:\test.srr", L"test.srr"); pDlgReport->Create(IDD_DIALOG_CREATE, this); pDlgReport->ShowWindow(SW_HIDE); // Do stuff pDlgReport->DestroyWindow(); } }
尝试无效的代码:
// 错误:Create前窗口句柄未生成,修改无效 DWORD dwStyle = ::GetWindowLong(pDlgReport->GetSafeHwnd(), GWL_STYLE); dwStyle &= ~WS_VISIBLE; //remove WS_VISIBLE ::SetWindowLong(pDlgReport->GetSafeHwnd(), GWL_STYLE, dwStyle); pDlgReport->Create(IDD_DIALOG_CREATE, this); pDlgReport->ShowWindow(SW_HIDE);
原因分析
你之前的代码错误在于:在Create调用前修改窗口样式完全无效,此时窗口尚未创建,GetSafeHwnd()返回NULL,样式修改根本没有作用。而Create方法会严格按照对话框资源的属性生成窗口,若资源中Visible属性为True,窗口创建时会瞬间显示,进而导致闪烁。
有效解决方案
方案1:修改对话框资源属性(最直接)
打开Visual Studio资源编辑器,找到IDD_DIALOG_CREATE对话框:
- 在属性面板中找到「Visible」选项,设置为
False。
这样窗口创建时默认就不会显示,从根源避免闪烁问题。
方案2:在对话框类的OnInitDialog中隐藏窗口
在CCreateReportDlg类的OnInitDialog函数中,窗口初始化完成后立即隐藏:
BOOL CCreateReportDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 直接隐藏窗口 ShowWindow(SW_HIDE); // 可选:同时移除WS_VISIBLE样式,确保后续不会意外显示 DWORD dwStyle = GetWindowLongPtr(m_hWnd, GWL_STYLE); dwStyle &= ~WS_VISIBLE; SetWindowLongPtr(m_hWnd, GWL_STYLE, dwStyle); return TRUE; }
注:若仅需隐藏,只调用ShowWindow(SW_HIDE)即可;移除样式是为了防止其他代码意外触发窗口显示。
方案3:修正代码顺序,在Create后立即修改样式
调整代码顺序,在窗口创建完成后再修改样式并隐藏:
void CChristianLifeMinistryEditorDlg::EditDutyAssignments() { auto pDlgReport = std::make_unique<CCreateReportDlg>(); if (pDlgReport != nullptr && m_pEntry != nullptr) { // 注意:路径中的反斜杠需转义,否则会被识别为转义字符 pDlgReport->SetFileToOpen(L"d:\\test.srr", L"test.srr"); // 先创建窗口 pDlgReport->Create(IDD_DIALOG_CREATE, this); // 移除WS_VISIBLE样式 DWORD dwStyle = ::GetWindowLongPtr(pDlgReport->GetSafeHwnd(), GWL_STYLE); dwStyle &= ~WS_VISIBLE; ::SetWindowLongPtr(pDlgReport->GetSafeHwnd(), GWL_STYLE, dwStyle); // 确保窗口隐藏 pDlgReport->ShowWindow(SW_HIDE); // Do stuff pDlgReport->DestroyWindow(); } }
同时注意修正路径中的转义问题:原代码L"d:\test.srr"会被解析为d:test.srr(\t被识别为制表符),需改为L"d:\\test.srr"。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

