模态对话框中错误的父 HWND
Wrong parent HWND in modal dialog
为什么我在此处将桌面作为我的模式对话框的父 HWND?
class CSaveProfileAsDlg:
public CSimpleDialog<IDD_DLG_RESOURCE>
{
....
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&)
{
...
HWND parent = GetParent(); // or GetAncestor(m_hWnd, GA_PARENT);
assert(parent != GetDesktopWindow()); // not ok
...
}
....
}
//somewhere in code
//m_hWnd is some valid HWND
assert(m_hWnd != GetDesktopWindow()); //ok
CSaveProfileAsDlg dlg;
dlg.DoModal(m_hWnd /*as a parent wnd*/);
我可以通过在 CSaveProfileAsDlg
ctor 中传递正确的 HWND 来 "solve" 它,但我想要正确的解决方案。
谢谢!
文档非常混乱,但我想我找到了问题所在。 DoModal
内部调用 ::DialogBox()
,其中一个参数采用名为 hWndParent
的 HWND
。来自 documentation:
hWndParent [in, optional]
Type: HWND
A handle to the window that owns the dialog box.
这里的关键词是"owns"这个词。关于 owned windows 的部分证实了这一点:
Dialog boxes and message boxes are owned windows by default. An application specifies the owner window when calling a function that creates a dialog box or message box.
所以我们实际上谈论的是所有者 window 而不是它的 parent。这是有道理的,因为对话框是自由浮动的 window,而不是 "parenthood" 所暗示的 window 层次结构的一部分。
您可以通过以下方式获得所有权 window:
HWND parent = ::GetWindow(m_hWnd, GW_OWNER);
我遇到了类似的问题。我想知道为什么 GetParent() return 总是不同的 CWnd*.
正确的解决方案很简单,只需将所需的 pWnd
传递给 dlg 构造函数即可。
会保存在CDialog成员变量m_pParentWnd
.
中
然后你总是可以在你的Dialog中用这个成员变量获取传递的pWnd。
//somewhere in code
//pWnd some valid CWnd pointer
CSaveProfileAsDlg dlg (pWnd); // relevant!
dlg.DoModal();
.
class CSaveProfileAsDlg:
public CSimpleDialog<IDD_DLG_RESOURCE>
{
....
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&)
{
...
CWnd* _pWnd = GetParent(); // not ok, returns probably CMainFrame or similiar
CWnd* pWnd = m_pParentWnd; // your parent Wnd
...
}
....
}
我有同一个应用程序的两个版本,其中一个禁用所有父弹出窗口 windows,就像调用 DoModal 时应该的那样。第二个版本仅禁用顶级 CMainFrame 并且真正的父级保持启用状态,因此我可以调用模态对话框两次或更多次。
这发生在 CWnd::GetSafeOwner_ 行:
hWnd = ::GetLastActivePopup(hWnd);
第一个版本 return 真正的父级,而第二个版本 return CMainFrame。
我花了一天时间,找不到这种行为的原因。但是我找到了解决方法:
调用 DoModal 时禁用 CMainFrame,这样我也可以禁用它的子项:
afx_msg void OnEnable(BOOL bEnable);
ON_WM_ENABLE()
void CMainFrame::OnEnable(BOOL bEnable)
{
std::for_each(m_bars.begin(), m_bars.end(),
[=](const std::pair<EBar, BaseBar*>& bar)
{
bar.second->EnableWindow(bEnable);
});
}
为什么我在此处将桌面作为我的模式对话框的父 HWND?
class CSaveProfileAsDlg:
public CSimpleDialog<IDD_DLG_RESOURCE>
{
....
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&)
{
...
HWND parent = GetParent(); // or GetAncestor(m_hWnd, GA_PARENT);
assert(parent != GetDesktopWindow()); // not ok
...
}
....
}
//somewhere in code
//m_hWnd is some valid HWND
assert(m_hWnd != GetDesktopWindow()); //ok
CSaveProfileAsDlg dlg;
dlg.DoModal(m_hWnd /*as a parent wnd*/);
我可以通过在 CSaveProfileAsDlg
ctor 中传递正确的 HWND 来 "solve" 它,但我想要正确的解决方案。
谢谢!
文档非常混乱,但我想我找到了问题所在。 DoModal
内部调用 ::DialogBox()
,其中一个参数采用名为 hWndParent
的 HWND
。来自 documentation:
hWndParent [in, optional]
Type: HWND
A handle to the window that owns the dialog box.
这里的关键词是"owns"这个词。关于 owned windows 的部分证实了这一点:
Dialog boxes and message boxes are owned windows by default. An application specifies the owner window when calling a function that creates a dialog box or message box.
所以我们实际上谈论的是所有者 window 而不是它的 parent。这是有道理的,因为对话框是自由浮动的 window,而不是 "parenthood" 所暗示的 window 层次结构的一部分。
您可以通过以下方式获得所有权 window:
HWND parent = ::GetWindow(m_hWnd, GW_OWNER);
我遇到了类似的问题。我想知道为什么 GetParent() return 总是不同的 CWnd*.
正确的解决方案很简单,只需将所需的 pWnd
传递给 dlg 构造函数即可。
会保存在CDialog成员变量m_pParentWnd
.
中
然后你总是可以在你的Dialog中用这个成员变量获取传递的pWnd。
//somewhere in code
//pWnd some valid CWnd pointer
CSaveProfileAsDlg dlg (pWnd); // relevant!
dlg.DoModal();
.
class CSaveProfileAsDlg:
public CSimpleDialog<IDD_DLG_RESOURCE>
{
....
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&)
{
...
CWnd* _pWnd = GetParent(); // not ok, returns probably CMainFrame or similiar
CWnd* pWnd = m_pParentWnd; // your parent Wnd
...
}
....
}
我有同一个应用程序的两个版本,其中一个禁用所有父弹出窗口 windows,就像调用 DoModal 时应该的那样。第二个版本仅禁用顶级 CMainFrame 并且真正的父级保持启用状态,因此我可以调用模态对话框两次或更多次。
这发生在 CWnd::GetSafeOwner_ 行: hWnd = ::GetLastActivePopup(hWnd);
第一个版本 return 真正的父级,而第二个版本 return CMainFrame。 我花了一天时间,找不到这种行为的原因。但是我找到了解决方法:
调用 DoModal 时禁用 CMainFrame,这样我也可以禁用它的子项:
afx_msg void OnEnable(BOOL bEnable);
ON_WM_ENABLE()
void CMainFrame::OnEnable(BOOL bEnable)
{
std::for_each(m_bars.begin(), m_bars.end(),
[=](const std::pair<EBar, BaseBar*>& bar)
{
bar.second->EnableWindow(bEnable);
});
}