MFC 對話框編程 -- 總結

一、創建對話框對象

1.首先利用資源編輯器創建對話框資源,並針對該對話框資源定義一個對話框類:class   CTestDlg :  public CDialog

2.創建話話框對象

模態對話框的創建:

    如:

     CTestDlg    dlg;

     dlg.DoModal();

 

非模態對話框創建:

   如:

   CTestDlg    dlg;

   dlg.Create(IDD_DIALOG, this);

  

但這樣是得不到一個正常顯示的非模態對話框的。因爲模態與非模態對話框的實現方式並不相同,這裏我們還要注意幾點。

  1. 非模態對話框創建完成後是隱藏着的,必須調用ShowWindow來進行顯示。
  2. 對於模態對話框,當執行到DoModal 函數以創建對話框時,程序會暫停執行,直至模態對話框關閉。所以創建模態對話框可以採用局部對象。
    但是,對於非模態對話框,當執行Create函數時並不會暫停執行,當執行到大括號"}後Dlg局部對象被銷燬生命週期結束,於是異常出現了。
    解決方法有兩個:
        一、在View類中定義一個CTestDlg 成員變量。
        二、動態創建一個CTestDlg 變量,並重寫CTestDlg 類的 PostNcDestroy函數,在該函數裏銷燬對象 delete    this;
  3. 無論創建的是模態對話框,還是非模態對話框,當我們單擊確定或取消按鈕後對話框都會消失。但這時低層的操作卻是不同的。
    對於模態對話框,此時對話框對象的確是被銷燬了,但對於非模態對話框,這時只是隱藏起來不再顯示。這需要我們自己調用DestoryWindow函數來進行銷燬工作。
    這時我們必須重寫 CTestDlg 的 OnOK 、 OnCancel 兩個函數(這兩個是基類CDialog的虛函數),在這兩個函數內調用DestroyWindow函數,並注意不再調用基類CDialog相應的函數。

正確地創建非模態對話框的代碼如下:

CTestDlg   *pDlg = new CTestDlg;
pDlg->Create(IDD_DIALOG, this);
pDlg->ShowWindow(SW_SHOW);   

同時,在CTestDlg 類的 PostNcDestroy函數中銷燬對象:delete   this;

 

二、動態創建按鈕

1. 在對話框類CTestDlg 中定義一個 CButton 類對象,作爲其成員變量。

2. 在相應的消息處理中,調用 CButton類的Create函數創建按鈕。

要注意兩點:

  • 如果在調用CButton::Create創建按鈕時沒有指定WS_VISIBLE 風格,那麼隨後一定要調用這個按鈕對象的ShowWindow函數,來將該按鈕顯示出來。
  • 爲防止該CButton關聯多個按鈕,這裏需要進行一些設置,如下:
    if (!m_btn.m_hwnd)
    {
          // CButton 對象m_btn 未關聯一個按鈕
          m_btn.Create(....);
    }
    else
    {
          // CButton 對象m_btn 已關聯一個按鈕
          其他操作...
    }
    當然,方法並不只這一種。但這是最漂亮的方法。

 

三、設置控件文本文字

1.下面列舉幾個用來設置控件文本文字的函數:

// 取得對話框中指定控件的窗口句柄。控件通過ID標識來指定
CWnd*         GetDlgItem( int nID ) const;
void CWnd::GetDlgItem( int nID, HWND* phWnd ) const;

// 取得窗口文本
int      GetWindowText( LPTSTR lpszStringBuf, int nMaxCount ) const;
void   GetWindowText( CString& rString ) const;

// 設置窗口文本
void  SetWindowText( LPCTSTR lpszString );

// 取得指定控件窗口文本。控件通過ID標識來指定
int    GetDlgItemText( int nID, LPTSTR lpStr, int nMaxCount ) const;
int    GetDlgItemText( int nID, CString& rString ) const;

// 設置指定控件窗口文本。控件通過ID標識來指定
void SetDlgItemText( int nID, LPCTSTR lpszString );

// 取得指定控件窗口文本,並轉化爲UINT 類型返回。控件通過ID標識來指定
UINT GetDlgItemInt( int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE ) const;

// 設置指定控件窗口文本,由UINT類型轉化爲字符 。控件通過ID標識來指定
void  SetDlgItemInt( int nID, UINT nValue, BOOL bSigned = TRUE );

2.可以爲對話框控件關聯一個變量,在CTestDlg 類的DoDataExchange來完成數據的更新與交換。

這裏我們需要重點說明 DoDataExChange 函數:
首先引用MSDN的一段解釋吧:Called by the framework to exchange and validate dialog data。意指框架調用此函數來改寫與確認對話框數據。

其實DoDataExChange函數主要是通過DDX_TEXT(....)  或 DDX_CONTROL(....) 來實現數據的實時關聯的。
我從我的MSDN中隨便拿來一個定義:

void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, BYTE& value );

其實這個要關聯的話也很簡單,沒有那麼複雜。如下:

value = GetDlgItemInt(nIDC);
SetDlgItemInt(nIDC, value);


而DoDataExchange 函數是在UpdateData函數內部調用的。
該函數只有一個布爾型參數,它決定了數據傳送的方向:

  • 調用UpdateData(TRUE)    , 將數據從對話框的控件中傳送到對應的數據成員中。
  • 調用UpdateData(FALSE)  , 則將數據從數據成員中傳送給對應的控件。

UpdateData(FALSE) 是將變量的值傳到控件.
UpdateData(TRUE)  是從控件中取值到關聯的變量

 

四、對話框伸縮功能的實現

只關聯到兩個函數:

// 取得指定窗口邊框摺尺寸

void GetWindowRect( LPRECT lpRect ) const;

// 設置指定窗口(控件)的位置同尺寸

BOOL SetWindowPos( const CWnd* pWndInsertAfter, intx, inty, int cx, intcy, UINTnFlags );

 

 

 

五、逃跑按鈕的實現

1. 創建一個基於對話框的MFC 程序,刪除原有的控件後,再添加兩個按鈕,更改兩按鈕名爲"你能抓到我嗎?"

2.打開類視圖,定義一個新類CNewButton,這個新類的基類爲CButton。併爲此類添加一個成員變量:CNewButton   *m_pbtn;

3.打開資源視圖,分別爲兩個按鈕創建兩個CNewButton類關聯變量:m_btn1, m_btn2;

4.在CXXXDlg中改寫其OnInitDialog函數。主要添加:

           m_btn1.m_pbtn = &m_btn2;

           m_btn2.m_pbtn = &m_btn1;

5.對於CNewButton 類,必定其OnMouseMove函數。主要添加:

           ShowWindow(SW_HIDE);

           m_pbtn->ShowWindow(SW_SHOW);

 

編譯,連接。 OK

 

六、屬性頁、屬性表單與嚮導的建立

1.創建屬性頁

打開資源編輯器,點擊Dialog 資源並在列出的選項中,選擇:IDD_PROPPAGE_LARGE。建立屬性頁資源。

之後,我們就可以其上添加其他控件來完善我們的屬性頁。關於屬性頁的完善操作我們在後面會談到。

屬性頁資源完善後,再爲每一個屬性頁關聯一個類。

2.創建屬性表單

打開類視圖,添加新類CPropSheet,其基類爲CPropertySheet。

之後再爲其添加屬性頁類對象,並在其構造函數中利用AddPage函數將屬性頁添加到表單上。

3.消息響應

再主菜單的最後再增加一個菜單項,併爲此菜單添加消息響應函數。

在此響應函數中創建屬性表單:

CPropSheet     propSheet(TEXT("屬性表單"));

propSheet.DoModal();

4.嚮導的創建

創建一個嚮導類型的對話框,應該遵循創建一個標準屬性表單的步驟來實現。

但在調用屬性表單對象的DoModal函數之前,應該先調用SetWizardMode函數,來聲明建立的是一個作爲嚮導的屬性表單。

所以,應在DoModal函數之前添加如下代碼:

propSheet.SetWizardMode();

5.屬性頁的完善操作

首先我們要注意到屬性頁,在三個不同時期的關鍵性操作:

  1. 當屬性表單中的某屬性頁被選中,從而成爲一個活動的頁面時,應用程序框架就會調用OnSetActive函數。
    OnSetActive 是其基類的一個虛函數,我們可以重寫這個函數並在其中進行一些操作。
  2. 假設當前我們處於屬性表單中的某屬性頁,當我們點擊下一步並將進入下一個屬性頁時,應用程序框架會調用OnWizardNext函數。
    OnWizardNext 是其基類的一個虛函數,我們可以重寫這個函數並在其中進行一些操作。
    類似的還有OnWizardBack 同 OnWizardFinish函數。
  3. 當一個屬性頁被創建時,會調用其OnInitDialog函數。
    我們可以在這個函數裏對屬性頁中的控件進行一些操作。如爲列表框或下拉框添加字符串等。

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章