在没有主窗口的MFC应用程序中创建多个对话框,它们彼此成为子级 [英] Creating multiple dialogs in an MFC app with no main Window, they become children of each other

查看:110
本文介绍了在没有主窗口的MFC应用程序中创建多个对话框,它们彼此成为子级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(标题已更新) 继这个问题之后,现在我有了一个更清晰的认识怎么回事...

(title updated) Following on from this question, now I have a clearer picture what's going on...

我有一个没有主窗口的MFC应用程序,该应用程序公开了一个用于创建对话框的API.当我反复调用其中一些方法时,创建的对话框是彼此父级的,而不是全部都父级为桌面的……我不知道为什么.

I have a MFC application with no main window, which exposes an API to create dialogs. When I call some of these methods repeatedly, the dialogs created are parented to each other instead of all being parented to the desktop... I have no idea why.

但是无论如何,即使在创建之后,我也无法将父级更改回NULL或CWnd :: GetDesktopWindow()...如果我先调用SetParent,再调用GetParent,则没有任何改变.

But anyway even after creation, I am unable to change the parent back to NULL or CWnd::GetDesktopWindow()... if I call SetParent followed by GetParent, nothing has changed.

因此,除了一个非常奇怪的问题:为什么Windows神奇地将每个对话框作为最后一个对话框的父对象,我是否还缺少将这些窗口设置为桌面的子窗口的任何内容?

So apart from the really weird question of why Windows is magically parenting each dialog to the last one created, is there anything I'm missing to be able to set these windows as children of the desktop?

更新:我已经找到了所有原因的原因,但没有找到解决方法.在我的对话框构造函数中,我们结束于:

UPDATED: I have found the reason for all this, but not the solution. From my dialog constructor, we end up in:

BOOL CDialog::CreateIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd,
    void* lpDialogInit, HINSTANCE hInst)
{
    ASSERT(lpDialogTemplate != NULL);

    if (pParentWnd == NULL)
        pParentWnd = AfxGetMainWnd();
    m_lpDialogInit = lpDialogInit;

    return CreateDlgIndirect(lpDialogTemplate, pParentWnd, hInst);
}

注意: if (pParentWnd == NULL)pParentWnd = AfxGetMainWnd();

我的对话框构造函数中的调用栈如下:

The call-stack from my dialog constructor looks like this:

  • mfc80d.dll! CDialog :: CreateIndirect (const DLGTEMPLATE * lpDialogTemplate = 0x005931a8,CWnd * pParentWnd = 0x00000000,void * lpDialogInit = 0x00000000,HINSTANCE__ * hInst = 0x00400000)
  • mfc80d.dll!CDialog :: CreateIndirect(void * hDialogTemplate = 0x005931a8,CWnd * pParentWnd = 0x00000000,HINSTANCE__ * hInst = 0x00400000)
  • mfc80d.dll!CDialog :: Create(const char * lpszTemplateName = 0x0000009d,CWnd * pParentWnd = 0x00000000)
  • mfc80d.dll!CDialog :: Create(unsigned int nIDTemplate = 157,CWnd * pParentWnd = 0x00000000)
  • MyApp.exe!CMyDlg :: CMyDlg(CWnd * pParent = 0x00000000)
  • mfc80d.dll!CDialog::CreateIndirect(const DLGTEMPLATE * lpDialogTemplate=0x005931a8, CWnd * pParentWnd=0x00000000, void * lpDialogInit=0x00000000, HINSTANCE__ * hInst=0x00400000)
  • mfc80d.dll!CDialog::CreateIndirect(void * hDialogTemplate=0x005931a8, CWnd * pParentWnd=0x00000000, HINSTANCE__ * hInst=0x00400000)
  • mfc80d.dll!CDialog::Create(const char * lpszTemplateName=0x0000009d, CWnd * pParentWnd=0x00000000)
  • mfc80d.dll!CDialog::Create(unsigned int nIDTemplate=157, CWnd * pParentWnd=0x00000000)
  • MyApp.exe!CMyDlg::CMyDlg(CWnd * pParent=0x00000000)

在调试器中运行,如果我在CDialog :: CreateIndirect中将pParentWnd手动更改回0,一切正常...但是如何首先停止它发生?

Running in the debugger, if I manually change pParentWnd back to 0 in CDialog::CreateIndirect, everything works fine... but how do I stop it happening in the first place?

推荐答案

一些想法:

首先,您要在整个链中为父窗口传递NULL.当MFC尝试找到您的应用程序主窗口时,它将变为非NULL.

First, you are passing NULL for the parent window the whole way through the chain. Its becomming non NULL when MFC tries to find your applications main window.

如我所见,您有两个缓解措施:

As I see it you have two mitigations:

  1. 从桌面窗口创建CWnd. CWnd :: GetDesktopWindow 将为您提供一个非NULL窗口,用作一个将禁止AfxGetMainWnd调用的父窗口.
  2. 或者跟踪到AfxGetMainWnd,找出它是从哪里读取主窗口的,并查看是否有一些设置可以阻止它找到您的对话框.
  1. Create a CWnd from the desktop window. CWnd::GetDesktopWindow will give you a non NULL window to use as a parent window that will inhibit the AfxGetMainWnd call.
  2. Or trace into AfxGetMainWnd, find out where it is reading the main window from, and see if there is some setting to prevent it finding your dialog window.

最后一点. MFC的术语很不幸:-在Windows上,只有子窗口具有父窗口.弹出窗口或桌面窗口具有所有者窗口. CreateWindow采用单个参数,该参数接受所有者或正在创建的窗口的父级.区别很重要,因为尽管可以更改父窗口,但所有者不能. SetParent不会更改弹出窗口或重叠窗口的所有者窗口.

On a final note. The MFC terminology is unfortunate :- On Windows, only child windows have parent windows. Popup or desktop windows have owner windows. CreateWindow takes a single parameter that accepts the owner, or parent of the window being created. The distinction is important because while a parent window can be changed, an owner cannot. SetParent will NOT change the owner window for a popup or overlapped window.

这篇关于在没有主窗口的MFC应用程序中创建多个对话框,它们彼此成为子级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆