首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

MFC 無模式對話框的建立與生命週期管理

     編輯:關於VC++

在 Windows 程式設計中,對話框是使用者介面的核心元素之一。根據行為模式不同,對話框分為「模式」與「無模式」兩種類型。模式對話框會獨佔使用者輸入焦點,必須關閉後才能操作其他視窗;而無模式對話框則允許使用者同時與其他視窗互動,行為類似於獨立的彈出視窗。本文將深入探討 MFC 架構下無模式對話框的建立、顯示與物件銷毀機制,並提供兩種實用的記憶體管理策略。

無模式對話框的建立與顯示

建立無模式對話框需呼叫 CDialog::Create() 方法載入對話框資源,並以 ShowWindow(SW_SHOW) 使其顯示。若僅呼叫 Create() 而未顯示,對話框將保持不可見狀態。典型程式碼如下:

void CYourView::OnOpenDlg(void)
{
    // 假設 IDD_TEST_DLG 為已定義的對話框資源 ID
    CTestDlg *dlg = new CTestDlg;
    dlg->Create(IDD_TEST_DLG, NULL);
    dlg->ShowWindow(SW_SHOW);
    // 此處不可呼叫 delete dlg;
}

關鍵在於:對話框物件以動態配置方式建立(new),且在函數結束時不得立即刪除。若物件被銷毀而視窗仍在顯示,將導致存取違規錯誤。因此,核心問題在於:何時、由誰負責銷毀該物件?

策略一:對話框自我銷毀

此法讓對話框在關閉時自行銷毀物件。重寫 OnOK()、OnCancel() 呼叫父類別方法後執行 DestroyWindow() 強制銷毀視窗;再對映 WM_DESTROY 訊息,在處理函數中執行 delete this 刪除自身。

void CTestDlg1::OnOK()
{
    CDialog::OnOK();
    DestroyWindow();
}

void CTestDlg1::OnCancel()
{
    CDialog::OnCancel();
    DestroyWindow();
}

void CTestDlg1::OnDestroy()
{
    CDialog::OnDestroy();
    AfxMessageBox(_T("call delete this"));
    delete this;
}

此策略精髓在於:視窗銷毀時同步刪除物件。外部隨時呼叫 DestroyWindow() 即可觸發完整銷毀流程(DestroyWindow() 會引發 OnDestroy())。

策略二:透過父視窗訊息通知銷毀

適用於需由外部統一管理對話框生命週期的情境。步驟如下:

  1. 自訂訊息 WM_DELETE_DLG 用於通知銷毀。
  2. 對話框建構式保存父視窗指標 m_pParent(不可為暫時性指標)。
  3. OnDestroy() 中以 PostMessage() 發送訊息給父視窗,將 this 指標作為 WPARAM 傳遞。
  4. 父視窗以 ON_MESSAGE 對映處理函數,接收訊息後執行 delete。
// 對話框類別
void CTestDlg2::OnDestroy()
{
    CDialog::OnDestroy();
    m_pParent->PostMessage(WM_DELETE_DLG, (WPARAM)this);
}

// 父視窗類別
afx_msg LONG OnDelDlgMsg(WPARAM wP, LPARAM lP);

ON_MESSAGE(WM_DELETE_DLG, OnDelDlgMsg)

LONG CMyView::OnDelDlgMsg(WPARAM wP, LPARAM lP)
{
    delete (CTestDlg2*)wP;
    return 0;
}

此法善用 Windows 訊息機制解耦物件生命週期,符合事件驅動程式設計慣例。

資料即時回傳:無模式對話框的進階應用

無模式對話框另一優勢在於能即時將使用者輸入同步至其他視窗。例如:使用者在對話框編輯文字,按下按鈕後透過 SendMessage() 將資料指標傳送給檢視視窗,檢視視窗接收訊息更新顯示內容並呼叫 Invalidate() 重繪。

// 對話框端
void CTestDlg2::OnCommBtn()
{
    char szOut[30];
    GetDlgItemText(IDC_OUT, szOut, 30);
    m_pParent->SendMessage(WM_DLG_NOTIFY, (WPARAM)szOut);
}

// 檢視視窗端
ON_MESSAGE(WM_DLG_NOTIFY, OnDlgNotifyMsg)

LONG CMyView::OnDlgNotifyMsg(WPARAM wP, LPARAM lP)
{
    m_szOut = (char*)wP;
    Invalidate();
    return 0;
}

此模式展示了無模式對話框作為「浮動工具面板」的典型用法,廣泛應用於屬性設定、即時預覽等場景。

總結

無模式對話框的核心難點在於物件生命週期管理。本文提出的兩種策略——「自我銷毀」與「父視窗代管」——分別適合獨立運作與集中管理的架構需求。搭配訊息機制實現跨視窗資料同步,可構建靈活、響應迅速的使用者介面。掌握這些技巧,能讓 MFC 開發者更從容地處理複雜視窗交互邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved