[英]When an MFC dialog is hidden after DoModal, are its controls destroyed?
[英]MFC DoModal Dialog
好的,所以我承認我不知道 windows API 甚至 MFC。
當 go 多毛(文件名字符串中的非法字符)時彈出錯誤 window 並且我希望錯誤框是模態的。
對於我的生活,我無法弄清楚為什么它在碰到 doModal 時會崩潰。
這是我認為可以修復的代碼。 此代碼位於主 window 中按鈕的事件處理程序中。
CDialog *BadFileD = new CDialog();
BadFileD->Create(IDD_STATUS, this);
BadFileD->DoModal();
我只是邊緣性智障嗎?
MFC 對話框分兩種模式,模態對話框和非模態對話框。
(1) 模態對話框用法:
CDialog dlg;
dlg.DoModal();
(2) 無模式對話用法:
CMyDialog *pDlg = new CMyDialog();
pDlg->Create(ID_DLG, this);
pDlg->ShowWindows(SW_SHOW);
如您所見,我們需要一個新指針,但不要刪除它。 因此,您需要在我們的CMyDialog
class 中執行以下操作:
OnOk()
和OnCancel()
中添加DestroyWindow()
方法。PostNcDestroy()
方法中添加“ delete this;
”。 如果不這樣做,您的代碼可能會導致 memory 泄漏。 BadFileD
是 class 成員,您在析構函數中將其刪除。 我建議使用無模式對話框。
對於顯示模式對話框,您應該只使用 DoModal 方法
CDialog *BadFileD = new CDialog(IDD_STATUS, this);
BadFileD->DoModal();
您可以閱讀文章中的備注
如果您只想顯示一條錯誤消息,那么您可以使用AfxMessageBox()
而不是創建自己的對話框。 請參閱Microsoft 開發人員網絡 - AfxMessageBox 。
如果您想使用 MFC 項目來創建自己的對話框,您通常會:
但是,對於一個不需要支持 class 的復雜行為的簡單對話框,您可以跳過使用 class 向導創建封裝 class 的步驟,直接使用CDialog
。
需要回答的一個問題是對話的生命周期以及它是模態的還是非模態的。 模態對話框需要用戶做一些事情,以使應用程序繼續通過模態對話框。 無模式對話框不會像模式對話框那樣阻塞應用程序。 還有一種系統模式對話框樣式。
既然你說這將是一個模態對話框,那么生命周期就會很短,所以整個構建、顯示和銷毀可能都在一系列代碼行中。 例如,在帶有顯示模式對話框的命令處理程序的CView
class 中,您可能有:
void CViewThing::OnCommandMenuItem ()
{
CDialog BadFileD(IDD_STATUS);
int iRetStatus = BadFileD.DoModal();
// check for status such as IDOK, etc.
// do whatever is necessary.
}
上面所做的是使用對話框資源模板IDD_STATUS
創建一個對話框並將其顯示為模式對話框。 由於是本地object,當變量BadFileD
走出scope時,會觸發對話框析構函數,為你清理資源。
你也可以有一個無模式的對話框。 在無模式對話框的情況下,您需要考慮變量的生命周期,因為一旦變量超出 scope,析構函數將觸發並且對話框將消失。
因此,對於與某些視圖 class 一起使用的無模式對話框,可能提供某種工具箱, CDialog
變量將是正在使用它的CView
class 的成員。 無模式對話框創建后,通過使用CDialog
class的ShowWindow()
成員function(實際上是CWnd
CDialog
的成員)的成員來顯示或不顯示。
void CViewThing::OnCommandMenuItem ()
{
BadFileD.Create(IDD_STATUS, this);
BadFileD.ShowWindow(SW_SHOW); // display the dialog
}
在CViewThing
class 中,您將擁有一個成員變量CDialog BadFileD;
.
其他注意事項
在上述所有示例中,我們都沒有使用指針,因此當CDialog
變量退出 scope 時,要么退出成員 function,要么當 object 使用對話框被破壞時。 這個 object 管理是為我們完成的。
對於無模式對話框,您必須考慮的一件事是當您不再需要它時如何將其銷毀。
由於模態對話框通常是一個短期的 object,通常作為堆棧上的局部變量創建,因此您通常只需將 go 放在 scope 之外,以處理所有與破壞有關的事情。
但是,無模式對話框的生命周期要求在不再需要對話框時使用DestroyWindow()
方法來銷毀對話框。 請參閱Microsoft 開發人員網絡 - 銷毀對話框。
第三種使用場景——嵌入對話框
對話框的第三種用法有時會派上用場,將對話框嵌入另一個 window 作為控件。
在上面的示例中,對話框模板指定了對話框的WS_POPUP
樣式,這是對話框的標准樣式,因為使用對話框的正常方式是顯示為單獨的 window。
但是,如果您將WS_POPUP
樣式更改為WS_CHILD
,您可以將對話框嵌入到另一個 window 作為控件。 您可以刪除其他樣式設置,例如WS_SYSMENU
、 DS_MODALFRAME
和WS_CAPTION
並從對話框模板中刪除CAPTION
行以進一步更改對話框。 所以你最終會得到類似的東西:
IDD_STATUS DIALOGEX 0, 0, 435, 266
STYLE DS_SETFONT | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "this is some static text to display on this dialog.",IDC_STATIC,81,63,200,32
END
然后只需使用生成的對話框,類似於使用ShowWindow()
的無模式對話框。
如果您需要在其容器 window 中重新定位嵌入對話框,您可以使用SetWindowPos()
方法來執行此操作。 例如,以下內容會將對話框 window 在其包含的 window 內移動到距包含 window 的左側 20 個像素和距頂部 10 個像素的位置。
BadFileD.SetWindowPos(NULL, 20, 10, 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.