2010-04-28 12 views
2

(標題更新) 孩子this問題繼,現在我有一個更清晰的畫面是怎麼回事...在MFC應用程序沒有主窗口中創建多個對話,他們也成爲彼此

我有沒有主窗口的MFC應用程序,它暴露了一個API來創建對話框。當我反覆調用這些方法中的一些時,創建的對話框會彼此相關,而不是所有的對象都被授予桌面......我不知道爲什麼。

但無論如何,即使在創建後,我無法將父母更改回NULL或CWnd :: GetDesktopWindow()...如果我調用SetParent,然後調用GetParent,則沒有任何更改。

因此,除了真正奇怪的問題,爲什麼Windows將每個對話框神奇地養育到最後一個創建的對話框,是否有任何我能夠將這些窗口設置爲桌面的子項?


修訂:我已經找到了原因這一切,但不是解決辦法。

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();

從我的對話框構造函數的調用堆棧看起來是這樣的:

  • mfc80d.dll! CDialog的:CreateIndirect(常量DLGTEMPLATE * lpDialogTemplate = 0x005931a8,CWnd的* pParentWnd = 00000000,無效* lpDialogInit = 00000000,HINSTANCE__ * HINST = 0x00400000)
  • mfc80d.dll!CDialog的:CreateIndirect(void *的hDialogTemplate = 0x005931a8, *的CWnd = pParentWnd 00000000,HINSTANCE__ * HINST = 0x00400000)
  • mfc80d.dll!CDialog的:創建(爲const char * lpszTemplateName = 0x0000009d,CWnd的* pParentWnd = 00000000)
  • mfc80d.dll!CDialog的:創建(無符號int nIDTemplate = 157,CWnd * pParentWnd = 0x00000000)
  • MyApp.exe!CMyDlg :: CMyDlg(CWnd * pParent = 0x00000000)

在調試器中運行,如果我手動將pParentWnd更改回CDialog :: CreateIndirect中的0,一切正常......但我怎樣才能阻止它發生在第一個地方?

+0

對SetParent()的調用是否成功? – 2010-04-28 16:00:41

+0

http://stackoverflow.com/questions/2729371/creating-multiple-mfc-dialogs-through-com-strange-behaviour – 2010-04-28 19:18:16

+0

您可能已經複製了您的原始問題。請不要反覆提問相同的問題,請跟進您的原始線索。 – 2010-04-28 19:19:45

回答

5

的幾點思考:

首先,通過鏈條傳遞NULL父窗口的整個方式。當MFC試圖找到你的應用程序主窗口時,它會變成非NULL。

當我看到它,你有兩個緩解:

  1. 從桌面窗口中創建一個CWnd。 CWnd::GetDesktopWindow會爲您提供一個非NULL窗口,用作禁止AfxGetMainWnd調用的父窗口。
  2. 或者跟蹤到AfxGetMainWnd,找出它從哪裏讀取主窗口,並查看是否有某些設置可以阻止它查找對話窗口。

在最後的筆記。 MFC的術語是不幸的: - 在Windows上,只有子窗口具有父窗口。 Popup或dekstop窗口擁有所有者窗口。 CreateWindow接受一個接受所有者的參數,或接受所創建窗口的父親。這種區別很重要,因爲雖然父窗口可以更改,但所有者不能。 SetParent不會更改彈出窗口或重疊窗口的所有者窗口。

+1

感謝所有者Vs家長的澄清,我一直困惑的區別。 – 2010-04-29 10:24:33

+0

儘管我的答案是「答案」,但您可以獨立發現相同的問題,因此您可以擁有綠色的勾號 - 謝謝! – 2010-04-29 10:29:46

0

MFC一次只能創建一個窗口IIRC。至少在黑暗和遙遠的過去,當MFC創建一個Win32窗口時,它需要將MFC CWnd實例與該窗口相關聯。因爲窗口接收到的第一條消息不是WM_CREATE消息,並且LPVUSERDATA參數MFC將CWnd實例存儲在線程局部變量中 - 對於CWnd :: WindowProc的下一個調用將用於它開始嘗試訪問的窗口並非不合理的期望創建。

我不知道如何能真正寫代碼來顛覆這個過程。這一切都取決於你如何以不同的速度創造窗戶。

+0

其實我測試了一些,可以重現這一點,即使我添加延遲。看到我更新的帖子。事實上,我沒有父窗口似乎導致Windows找到最好的。 – 2010-04-29 09:05:49

1

好的,找到它了!

實際上有兩個問題。我作爲父母/所有者傳遞NULL ...但試圖通過CWnd::GetDesktopWindow()沒有幫助,所以我放棄了這個想法,直到找到CDialog::CreateIndirect的行爲。這讓我仔細看了一下代碼,最後我發現MyDialog::MyDialog(CWnd *pParent)super::Create(NULL),而不是super::Create(pParent) ......因爲我們總是把NULL傳遞給NULL,因爲錯誤從來沒有出現過。

所以再次,這個難題竟然只是一個錯字!

相關問題