C++MFC編程筆記day08 MFC對話框的使用
一 MFC對話框
1 分類
模式和非模式
2 相關類
CDialog類-父類是CWnd,本質上是一個窗口,對話框類的父類。
CCommonDialog類以及子類-通用對話框,顏色對話框、文件對話框、
查找替換對話框、字體設置對話框、打印設置對話框和
打印對話框。
CPropertyPage類-屬性頁對話框。
3 在Win32向導中,使用MFC的類創建對話框程序
3.1 模式對話框
3.1.1 創建和顯示對話框
CDialog::DoModal()
3.1.2 對話框的關閉(無需用戶處理)
CDialog::OnOK/OnCancel
3.2 非模式對話框
3.2.1 創建和顯示對話框
類似於一般窗口的創建過程
3.2.2 對話框的關閉
1 重寫CDialog::OnOK/OnCancel函數,在函數中:
DestroyWindow()
2 重寫CWnd::PostNcDestroy函數,在函數中:
delete this;
3.3 創建單文檔程序,使用菜單分別打開模式/非模式對話框
對比運行時的效果
3.4 跟蹤DoModal()函數的執行過程
3.4.1 查找和加載對話框資源
3.4.2 將父窗口設置為不可用狀態
3.4.3 創建對話框
3.4.4 進入對話框的消息循環
3.4.5 當點擊OK或則Cancel按鈕後,退出循環
3.4.6 隱藏了對話框窗口,將父窗口設置為可用狀態
3.4.7 銷毀對話框
3.4.8 釋放對話框資源
3.4.9 返回DoModal()函數的返回值
示例:
新建win32 應用程序 ,然後改為支持MFC,並手動創建代碼:
// DlgApp.cpp : Defines the entry point for the application.
//
#include "stdafx.h"//#include
#include "resource.h"
class CMyDlg:public CDialog
{
public:
CMyDlg():CDialog(IDD_DIALOG1){}//關聯對話框資源ID
//以下3函數,使用非模式對話框時要重寫實現
virtual void PostNcDestroy( );
virtual void OnOK( );
virtual void OnCancel();
};
void CMyDlg::OnOK()
{
CDialog::OnOK();
DestroyWindow();
}
void CMyDlg::OnCancel()
{
CDialog::OnCancel();
DestroyWindow();
}
void CMyDlg::PostNcDestroy()
{
CWnd::PostNcDestroy();
delete this;
}
class CDlgApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
CDlgApp theApp;
BOOL CDlgApp::InitInstance()
{
/* 模式對話框
CMyDlg dlg;
m_pMainWnd=&dlg;
dlg.DoModal();//創建和顯示模式對話框
*/
//非模式對話框
CMyDlg *pDlg=new CMyDlg;
pDlg->Create(IDD_DIALOG1);//對話框資源ID
m_pMainWnd=pDlg;
pDlg->ShowWindow(SW_SHOW);
return TRUE;
}
二 對話框的數據交換技術(DDX)
引入它的目的是方便操作控件和獲取/設置控件的值
可以將控件與對話框的成員變量綁定,通過操作對話框的成員變量來
達到操作控件的目的。
1 相關函數
1.1 一系列的綁定函數
DDX_Control ,綁定控件類型的變量
DDX_Text ,綁定值類型的變量
例如,對話框中有一個編輯框控件,ID,ID_EDIT1
對話框類中的變量,CString m_strText;//值類型的變量
int m_nText;//值類型的變量
CEdit m_wndText;//控件類型的變量
1.2 對話框數據交換函數,包含1.1綁定函數
CWnd::DoDataExchange
1.3 當值類型(CString)成員變量與控件之間有數據交換時,調用以下函數:
UpdateData()
UpdateData(TRUE)-控件的值傳遞給成員變量
UpdateData(FALSE)-成員變量的值放到控件上顯示
2 使用
3 原理
3.1 DDX_Control-控件類型的綁定函數
DDX_Control(CDataExchange* pDX, ...)
{
//1根據控件的ID,得到控件的句柄
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
//2 將控件類型的變量與控件的句柄建立映射關系
rControl.SubclassWindow(hWndCtrl)
{
Attach(hWndCtrl);
}
}
3.2 DDX_Text-值類型的綁定函數
DDX_Text(CDataExchange* pDX, int nIDC,...)
{
//1根據控件的ID,得到控件的句柄
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
//2 變量與控件相互賦值
if (pDX->m_bSaveAndValidate)
{
int nLen = ::GetWindowTextLength(hWndCtrl);
::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
value.ReleaseBuffer();
}
else
{
AfxSetWindowText(hWndCtrl, value);
}
}
4 函數的調用關系,為什麼我們會在CMyDlg::OnInitDialog(),首先
調用它的父類CDialog::OnInitDialog()?
只有調用CDialog::OnInitDialog(),對話框顯示前,才能將
控件與變量綁定。具體的調用關系:
CDialog::OnInitDialog()
{
UpdateData(FALSE);
{
DoDataExchange(pDx);
{
DDX_Control();
DDX_Text();
}
}
}
示例,建立win32 應用程序,然後手動改為支持MFC,再寫代碼:
// DlgDDX.cpp : Defines the entry point for the application.
//
#include "stdafx.h"//#include
#include "resource.h"
class CMyDlg:public CDialog
{
public:
CMyDlg():CDialog(IDD_DIALOG1){}//關聯對話框資源ID
//以下3函數,非模式對話框時要重寫實現
virtual void PostNcDestroy( );
virtual void OnOK( );
virtual void OnCancel();
virtual BOOL OnInitDialog();
virtual void DoDataExchange(CDataExchange* pDX);
CButton m_wndOK;//與ok按鈕綁定的控件
CString m_wndEdit1;
};
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX,IDOK,m_wndOK);//界面上控件與成員變量綁定
DDX_Text(pDX,IDC_EDIT1,m_wndEdit1);
}
void CMyDlg::OnOK()
{
UpdateData(TRUE);
AfxMessageBox(m_wndEdit1);
//CDialog::OnOK();
//DestroyWindow();
}
void CMyDlg::OnCancel()
{
CDialog::OnCancel();
DestroyWindow();
}
void CMyDlg::PostNcDestroy()
{
CWnd::PostNcDestroy();
delete this;
}
//對話框初始化
BOOL CMyDlg::OnInitDialog()
{
if(!CDialog::OnInitDialog())
{
return FALSE;
}
CWnd* pbtn = GetDlgItem(IDCANCEL);//獲取控件
pbtn->EnableWindow(FALSE);//設置為不可用
m_wndOK.MoveWindow(0,0,100,100,TRUE);//操作綁定的成員變量等於操作控件
m_wndOK.SetWindowText("DDX_OK");
m_wndEdit1="123";
UpdateData(FALSE);
return TRUE;
}
class CDlgApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
CDlgApp theApp;
BOOL CDlgApp::InitInstance()
{
///* 模式對話框
CMyDlg dlg;
m_pMainWnd=&dlg;
dlg.DoModal();//創建和顯示模式對話框
//*/
return TRUE;
}
三 實現登錄功能
在主窗口顯示前,設置登陸對話框,登陸通過了,才顯示主窗口:
CDialogLogin dlglogin;
if(IDOK!=dlglogin.DoModal()) return false;
添加控件與值綁定:
Ctrl+w ,選擇 member variables 選項卡,添加與控件對應的變量。
登陸對話框處理:
void CDialogLogin::OnOK()
{
UpdateData(TRUE);//更新控件值到變量中
if(m_UserName=="123" && m_UserPwd=="123")//模擬登陸
{
CDialog::OnOK();
}
else
{
AfxMessageBox("用戶名或密碼錯誤!");
}
}
示例:
1、創建MFC對話框應用程序
2、添加對話框,ID為IDD_DIALOG_LOGIN,並修改界面控件。
3、雙擊對話框標題,選擇Create a new class,添加對應的類,類名為 CDialogLogin。
4、ctrl+w添加成員綁定:
5、在app的IninInstance函數中,加入代碼:
CDialogLogin dlglogin;
if(IDOK!=dlglogin.DoModal()) return false;
意思是,如果登陸框沒有返回IDOK就不顯示主框架窗口。
添加點擊確定按鈕時的消息映射:
//CDialogLogin中實現點擊登陸的代碼:
void CDialogLogin::OnOK()
{
UpdateData(TRUE);
if(m_UserName=="123" && m_UserPwd=="123")//模擬登陸
{
CDialog::OnOK();//默認關閉對話框,返回IDOK
}
else
{
AfxMessageBox("用戶名或密碼錯誤!");
}
}