1. 程式人生 > >MFC介面程式設計基礎(10):基於對話方塊的MFC應用程式

MFC介面程式設計基礎(10):基於對話方塊的MFC應用程式

上一篇:MFC介面程式設計基礎(09):選單(二) 下一篇:MFC介面程式設計基礎(11):靜態文字框、命令按鈕和編輯框

MFC程式設計

MFC 是 Visual C++ 的核心。雖然在 Windows 應用程式中可以直接呼叫 API 函式,但是一般不經常直接呼叫,而是從 MFC 類建立物件並呼叫屬於這些物件的成員函式。MFC 是 Microsoft 公司提供的用來編寫 Windows 應用程式的 C++ 類庫,MFC 大約有 200 多個類,可以分成兩種:一是 Cobject 類的派生類,它們以層次結構的形式組織起來,幾乎每個子層次結構都與一個具體的 Windows 實體對應;二是非 Cobject 派生類,這些都是獨立的類,如表示點的 CPoint 類,表示矩形的 CRect 類。

在 Visual C++ 中,可以建立以下 3 類典型的 Windows 應用程式,它們都是通過 MFC AppWizard(exe) (以下簡稱 AppWizard )嚮導建立的:

  • 基於對話方塊的應用程式:這類程式適合於文件較少而互動操作較多的應用場合,如 Windows 自帶的計算器程式。
  • 單文件介面( SDI )應用程式:這類程式一次只能開啟一個文件,如 Windows 自帶的 Notepad 程式。
  • 多文件介面( MDI )應用程式:這類程式可以同時開啟多個文件並進行處理,處理的過程中很容易地進行切換,如 Microsoft Word 。

基於對話方塊的MFC應用程式

有兩種對話方塊: 模態對話方塊(Modal)和非模態對話方塊

  • 模態對話方塊
    當其顯示時,程式會暫停執行,直到關閉這個模態對話方塊之後,才能執行程式中的其他任務。我們平時遇到的對話方塊都是模態對話方塊。
    模態對話方塊的建立
    實現模態對話方塊的建立需要呼叫CDialog類的成員函式 DoModel(),該函式的功能就是建立並顯示一個對話方塊。
//彈出模態對話方塊,有阻塞(效果是彈出對話方塊後會停留在這個介面)
CTestDlg dlg;
dlg.DoModel();	//顯示模態對話方塊
  • 非模態對話方塊
    當非模態對話方塊顯示時,執行轉而執行程式中 的其他任務,而不用關閉這個對話方塊。典型的就是Windows記事本中提供的查詢對話方塊,開啟該對話方塊後仍可以與其他使用者介面物件進行互動,一遍查詢,一遍修改文章,這樣就大大方便了使用。
    非模態對話方塊的建立

    如果要建立非模態對話方塊在需要使用CDialog的Create成員函式。
BOOL Create(LPCSTR lpszTemplateName, CWnd* pParentWnd = NULL);
BOOL Create(UNIT nIDTemplate, CWnd* pParentWnd = NULL);

返回值:
如果對話方塊建立和初始化成功,則返回非零值,否則為0。
引數:
lpszTemplateName 對話方塊模板的名稱。
nIDTemplate 對話方塊資源的ID。
pParentWnd 指向含有對話方塊的父視窗物件的指標。如果為NULL,對話方塊物件的父視窗設定為應用的主視窗。
利用Create函式建立非模態對話方塊時,還需要呼叫ShowWindow函式將這個對話方塊顯示出來。

//彈出非模態對話方塊,無阻塞(效果是彈出對話方塊後會立馬關閉,一閃而過的樣子)
CTestDlg dlg;
dlg.Create(IDD_DIALOG1, this);//建立
dlg.ShowWindow(SW_SHOW);		//顯示 
//ShowWindow() 函式在  CWnd:ShowWindow() 中,因為CTestDlg 屬於CDialog 類,CDialog 的父類就是CWnd (類的層次結構圖中可查詢到)

執行程式發現仍然沒有彈出測試對話方塊,問題就出在建立的非模態對話方塊是一個區域性物件,函式結束後,對話方塊的生命週期也就結束了。在建立非模態對話方塊時不能將其定義為區域性物件。有兩種解決方法:

  • 1.把對話方塊物件定義為類的成員變數,主要按照以下兩個操作步驟:

    ①:在主對話方塊的 .h 檔案中新增成員變數,同時將事件處理程式中的 CTestDlg dlg; 註釋掉;

#include“TestDlg .h”
……
private:
	CTestDlg dlg;

若只是這樣,當第一次點選按鈕時會彈出非模態對話方塊,也不會閃退,而當你關閉這個非模態對話方塊後再次點選按鈕,程式會崩潰,原因是 dlg.Create(IDD_DIALOG1, this); 執行了兩次,所以需要進行第②步操作
  ②:將建立視窗的函式移到主對話方塊的初始化函式OnInitDialog中,同時將事件處理程式中的dlg.Create(IDD_DIALOG1, this); 註釋掉,確保視窗只建立一次,因為建立多次會崩潰,最後實際上就是當每次點選按鈕,事件處理程式中只負責顯示視窗就OK了;

BOOL XXXXX:OnInitDialog()
{
	……
	//TODO:在此新增額外的初始化程式碼
	dlg.Create(IDD_DIALOG1, this);//建立
}
  • 2.將對話方塊物件定義為指標,在堆上分配記憶體

如果選擇在堆上分配記憶體,關閉對話方塊時就需要釋放堆記憶體,釋放的方式有兩種:

  • 將指標定義為對話方塊所屬的類的成員變數(比如視類),在指標所屬的類的解構函式中釋放
  • 在對話方塊類中過載PostNcDestroy虛擬函式,釋放this指標指向的記憶體。
void MyDialog::PostNcDestroy()
{
	// TODO:  在此新增專用程式碼和/或呼叫基類
	delete this;
	CDialogEx::PostNcDestroy();
}

建立基於對話方塊的 MFC 應用程式框架

程式的建立過程:

  • 選擇“檔案 | 新建 | 專案”選單;
  • 在“新建專案”對話方塊中,選擇“ MFC 應用程式 ”,輸入工程名稱,選擇“確定”。

在這裡插入圖片描述

  • 選擇“ 基於對話方塊”,即建立基於對話方塊的應用程式,選擇“完成”。
    在這裡插入圖片描述

對話方塊應用程式框架

用 AppWizard 建立基於對話方塊的應用程式框架(假定工程名為 Dialog )後,專案工作區上增加了一個“ 資源檢視 ”選項卡。
在這裡插入圖片描述

  • 資源檢視
    在 MFC中,與使用者進行互動的對話方塊介面被認為是一種資源。展開“ Dialog ”,可以看到有一個 ID 為 IDD_ DIALOG _DIALOG(中間部分(DIALOG)與專案名稱相同) 的資源,對應中間的對話方塊設計介面。不管在何時,只要雙擊對話方塊資源的 ID ,對話方塊設計介面就會顯示在中間。
    在MFC中對資源的操作通常都是通過一個與資源相關的類來完成的。
  • 類檢視
    在類檢視中,可以看到生成了3 個類: CAboutDlg 、 CDialogApp 和 CDialogDlg 。
    在這裡插入圖片描述
  • CAboutDlg:對應生成的版本資訊對話方塊。
  • CDialogApp:對話方塊類,從 Cdialog 繼承過來的,在程式執行時看到的對話方塊就是它的一個具體物件。
  • CDialogDlg:應用程式類,從 CWinApp 繼承過來,封裝了初始化、執行、終止該程式的程式碼。
    ※ DoDataExchange函式,該函式主要完成對話方塊資料的交換和校驗。
    ※ OnInitDialog函式:相當於對對話方塊進行初始化處理
    呼叫這個成員函式是對WM_INITDIALOG訊息作出的反應。這條訊息是在對話方塊即將顯示之前,在Create,CreateIndirect或DoModal呼叫期間發出的。
  • 對話方塊設計介面
    對話方塊設計介面是進行對話方塊設計的地方,可以將各種控制元件放置在這裡。
    在這裡插入圖片描述
  • 控制元件工具欄
    我們可以根據實際需求,在開發過程中選擇不同的控制元件,實現不同的功能。
    在這裡插入圖片描述

注1:當點選一個按鈕需要彈出一個另外一個對話方塊,通常分以下幾個步驟:
①:在資源檢視中的Dialog中新增一個新的對話方塊(即你點選按鈕需要顯示的這個對話方塊)
②:在生成的新對話方塊中右鍵->新增類(類名自定義),將其對應到一個類中,然後會生成對應的 .h /.cpp 檔案
③:在按鈕的時間處理程式中使用這個類,並通過這個類建立一個物件,然後操作物件讓對話方塊顯示出來(模態的或者非模態的)

注2:給按鈕新增點選事件的處理程式的常用三種方法:
①:點選按鈕右鍵屬性->控制事件(閃電圖示)->BN_CLICKED(單次點選)->下拉列表出現字樣然後點選進入編輯
②:點選按鈕右鍵屬性->新增事件處理程式->點選進入編輯訊息型別等等
③:雙擊此按鈕,直接建立一個事件處理程式

注3:在MFC中一個類的名稱通常以一個大寫的C開頭,但是在別的檔案中引用這個標頭檔案的時候不用帶C
例如:類名 CDlgExec ,只需 #include “DlgExec.h”

上一篇:MFC介面程式設計基礎(09):選單(二) 下一篇:MFC介面程式設計基礎(11):靜態文字框、命令按鈕和編輯框