1. 程式人生 > >MFC建立模態對話方塊和非模態對話方塊的方法

MFC建立模態對話方塊和非模態對話方塊的方法

在MFC中對話方塊有兩種形式,一個是模態對話方塊(model dialog box),一個是非模態對話方塊(modeless dialog box)。本文對此分別簡述其建立方法。

一、模態對話方塊(model dialog box)

在程式執行的過程中,若出現了模態對話方塊,那麼主視窗將無法傳送訊息,直到模態對話方塊退出才可以傳送。
點選模態對話方塊中的OK按鈕,模態對話方塊會被銷燬。
建立一個模態對話方塊的程式碼如下所示:

//建立一個模態對話方塊
CTestDialog td;
td.DoModal(); 

其中CTestDialog為我自己所新建的和一個對話方塊資源相關聯的對話方塊類。
可以建立一個佈局模態對話方塊類變數,不用擔心它會隨著所在函式返回而被銷燬。因為DoModal()函式的一個功能是,當前只能執行此模態對話方塊,且停止主視窗的執行,直到模態對話方塊退出,才允許主視窗執行


DoModal()函式也有顯示對話方塊的功能,所以也無需呼叫其他函式來顯示對話方塊。

二、非模態對話方塊(modaless dialog box)

在程式執行的過程中,若出現了非模態對話方塊,主視窗還可以傳送訊息。
點選非模態對話方塊中的OK按鈕,非模態對話方塊沒有銷燬,只是隱藏了。若想點選OK按鈕時,非模態對話方塊也銷燬,那麼CTestDialog類必須過載其基類CDialog的虛擬函式OnOK(),在此函式裡呼叫DestroyWindow()來銷燬此對話方塊。

此處採用和上面一樣的方式來建立一個非模態對話方塊,程式碼如下:

CTestDialog td;
td.Create(IDD_DIALOG1); //建立一個非模態對話方塊
td.ShowWindow(SW_SHOWNORMAL); //顯示非模態對話方塊

那麼,在執行時,你會發現此對話方塊無法顯示。這是因為你宣告的對話方塊變數td是區域性變數,但這個函式返回時,td也被析構了,所以無法顯示此對話方塊。

建立非模態對話方塊,必須宣告一個指向CTestDialog類的指標變數,且需要顯示的呼叫ShowWindow()才能將對話方塊顯示出來。有兩種建立方法:

(1)採用區域性變數建立一個非模態對話方塊

//採用區域性變數建立一個非模態對話方塊
CTestDialog *pTD = new CTestDialog();
pTD->Create(IDD_DIALOG1); //建立一個非模態對話方塊
pTD->ShowWindow(SW_SHOWNORMAL); //顯示非模態對話方塊

因為指標在宣告的時候是被放在堆疊中,只有整個應用程式關閉後才會被銷燬,所以可以正常顯示對話方塊。
這種方法雖然不影響程式的執行,可是指標pTD所指向的記憶體卻導致不可用,這樣的程式設計很不好。

(2)採用成員變數建立一個非模態對話方塊
首先在你所要編寫的類的標頭檔案中宣告一個指標變數:

private:
CTestDialog *pTD;

然後再在相應的CPP檔案,在你要建立對話方塊的位置新增如下程式碼:

//採用成員變數建立一個非模態對話方塊
pTD = new CTestDialog(); //給指標分配記憶體
pTD->Create(IDD_DIALOG1); //建立一個非模態對話方塊
pTD->ShowWindow(SW_SHOWNORMAL); //顯示非模態對話方塊

最後在所在類的解構函式中收回pTD所指向的記憶體:

delete pTD;

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

眾所周知的,MFC中非模態對話方塊在顯示後,程式其他視窗仍能正常執行,可以響應使用者輸入,還可以相互切換。本文就來給大家講解一下非模態對話方塊的實現方法:

一、非模態對話方塊的對話方塊資源和對話方塊類

實際上,模態對話方塊和非模態對話方塊在建立對話方塊資源和生成對話方塊類上是沒有區別的,因此,在建立模態對話方塊時所建立的IDD_TIP_DIALOG對話方塊資源和CTipDlg類都不需要修改。

二、建立及顯示非模態對話方塊的步驟

需要修改的是,對話方塊類例項的建立和顯示,也就是之前在CAdditionDlg::OnBnClickedAddButton()函式體中新增的對話方塊顯示程式碼。下面是具體步驟:

1. 在AdditionDlg.h中包含CTipDlg標頭檔案並定義CTipDlg型別的指標成員變數。詳細操作方法是,在AdditionDlg.cpp中 刪除之前新增的#include "TipDlg.h",而在AdditionDlg.h中新增#include "TipDlg.h",這是因為我們需要在AdditionDlg.h中定義CTipDlg型別的指標變數,所以要先包含它的標頭檔案;然後在 AdditionDlg.h中為CAdditionDlg類新增private成員變數CTipDlg  *m_pTipDlg;。

2.在CAdditionDlg類的建構函式中初始化成員變數m_pTipDlg。如果cpp檔案中函式太多,我們可以在Class View上半個檢視中找到CAdditionDlg類,再在下半個檢視中找到其建構函式雙擊,中間客戶區域即可馬上切到建構函式的實現處。在建構函式體中 新增m_pTipDlg = NULL;,這是個好習慣,在任何指標變數使用前都初始化,可以避免因誤訪問重要記憶體地址而 破壞此地址的資料。

3.新增非模態對話方塊的建立和顯示代 碼。VC++中註釋單行程式碼使用“//”,註釋多行程式碼可以在需註釋的程式碼開始處新增“/*”,結束處新增“*/”。修改後的 CAdditionDlg::OnBnClickedAddButton()

函式如下:

void CAdditionDlg::OnBnClickedAddButton() 
{ 
  // TODO: Add your control notification handler code here 
  /*INT_PTR nRes;       // 用於儲存DoModal函式的返回值 
  CTipDlg tipDlg;      // 構造對話方塊類CTipDlg的例項 
  nRes = tipDlg.DoModal(); // 彈出對話方塊 
  if (IDCANCEL == nRes)   // 判斷對話方塊退出後返回值是否為IDCANCEL,如果是則return,否則繼續向下執行 
    return;*/ 
 
  // 如果指標變數m_pTipDlg的值為NULL,則對話方塊還未建立,需要動態建立 
  if (NULL == m_pTipDlg) 
  { 
    // 建立非模態對話方塊例項 
    m_pTipDlg = new CTipDlg(); 
    m_pTipDlg->Create(IDD_TIP_DIALOG, this); 
  } 
  // 顯示非模態對話方塊 
  m_pTipDlg->ShowWindow(SW_SHOW); 
 
  // 將各控制元件中的資料儲存到相應的變數 
  UpdateData(TRUE); 
 
  // 將被加數和加數的加和賦值給m_editSum 
  m_editSum = m_editSummand + m_editAddend; 
 
  // 根據各變數的值更新相應的控制元件。和的編輯框會顯示m_editSum的值 
  UpdateData(FALSE); 
}

4.因為此非模態對話方塊例項是動態建立的,所以需要手動刪除此動態物件來銷燬對話方塊。我們在 CAdditionDlg類的解構函式中新增刪除程式碼,但是MFC並沒有自動給出解構函式,這時需要我們手動新增,在對話方塊物件析構時就會呼叫我們自定義 的析構函數了。在AdditionDlg.h檔案中為CAdditionDlg新增解構函式宣告:~CAdditionDlg();,然後在 AdditionDlg.cpp檔案中新增解構函式的實現,函式體如下:

  CAdditionDlg::~CAdditionDlg() 
  { 
    // 如果非模態對話方塊已經建立則刪除它 
    if (NULL != m_pTipDlg) 
    { 
      // 刪除非模態對話方塊物件 
      delete m_pTipDlg; 
    } 
  } 

這樣,非模態對話方塊建立和顯示的程式碼就新增修改完了。
這只是一個簡單的例子,到這裡相信大家對於對話方塊的使用更上了一個臺階了,可以在不同的情況下可以選擇使用模態對話方塊和非模態對話方塊了。