模态对话框中的父HWND错误

时间:2017-03-14 09:04:52

标签: c++ windows window atl

为什么我将桌面作为我的模态对话框的父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*/);

我可以解决&#34;通过在CSaveProfileAsDlg ctor中传递更正HWND,但我希望得到正确的解决方案。

谢谢!

3 个答案:

答案 0 :(得分:2)

文档非常令人困惑,但我认为我发现了问题。 DoModal在内部调用::DialogBox(),其中一个参数采用名为HWND的{​​{1}}。来自documentation

  

hWndParent [in,optional]
  输入: HWND
  拥有对话框的窗口的句柄。

这里的关键字是“拥有”这个词。关于owned windows的部分确认了这一点:

  

默认情况下,对话框和消息框是拥有的窗口。应用程序在调用创建对话框或消息框的函数时指定所有者窗口。

所以我们实际上谈的是所有者窗口而不是它的父窗口。这是有道理的,因为对话框是一个自由浮动的窗口,而不是“父母身份”所暗示的窗口层次结构的一部分。

您可以使用以下方式获取拥有窗口:

hWndParent

答案 1 :(得分:0)

我有一个类似的问题。我想知道为什么GetParent()总是返回不同的CWnd *。

正确的解决方案很简单,只需将所需的pWnd传递给dlg构造函数。
它将存储在CDialog成员变量m_pParentWnd中。
然后,您始终可以在对话框中使用此成员变量获取传递的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
    ...
  }
 ....
}

答案 2 :(得分:0)

我有同一个应用程序的两个版本,其中一个禁用了调用DoModal时应禁用的所有父弹出窗口。第二个版本仅禁用顶级CMainFrame,并且真正的父级保持启用状态,因此我可以调用模式对话框两次或更多次。

这发生在CWnd :: GetSafeOwner_中,行: hWnd = :: GetLastActivePopup(hWnd);

第一个版本返回实际父级,而第二个版本返回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);
    });
}