原文地址: https://blog.csdn.net/ling_xiao007/article/details/51721363
6.1 對話框基本知識
對話框是一個窗口沉馆,與對話框資源相關(guān)的類為CDialog斥黑,由CWnd類派生而來锌奴。可以將對話框看成是一個大容器憾股,在它上面能夠放置各種標(biāo)準(zhǔn)和擴(kuò)展控件鹿蜀,是用戶與程序進(jìn)行交互的重要手段。在MFC中荔燎,所有的控件都是由CWnd派生而來耻姥,因此,控件實際上也是窗口有咨。
6.1.1常用控件
6.1.2對話框的種類
1)模式對話框:當(dāng)其顯示時,程序會暫停執(zhí)行蒸健,直到關(guān)閉這個對話框后座享,才能繼續(xù)執(zhí)行程序中其他任務(wù)婉商。例如“文件/打開” 對話框。
2)無模式對話框:當(dāng)其顯示時,允許轉(zhuǎn)而執(zhí)行程序中其他任務(wù),而不用關(guān)閉這個對話框。該類型對話框不會壟斷用戶的操作,用戶仍可以與其他界面對象進(jìn)行交互肥印。例如“查找”對話框敷硅。
6.2對話框的創(chuàng)建和顯示
在MFC中對資源的操作通常都是通過一個與資源相關(guān)的類來完成诫硕。可以在新建的對話框資源上雙擊完成添加。看到對話框id已經(jīng)默認(rèn)填寫八秃。這是在ClassViea選項卡就可以看到這個新類上忍。
構(gòu)造函數(shù)如下秕豫,首先調(diào)用基類的構(gòu)造函數(shù)歌径,并傳遞兩個參數(shù)克锣,IDD成員以及父窗口指針验残。在頭文件可以看打這個對話框資源的ID胆绊。
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_DIALOG1, pParent)
{
}
// 對話框數(shù)據(jù)
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG1 };
#endif
另一個函數(shù)是DoDataExchange肢础,完成對話框數(shù)據(jù)的交換和校驗慨蛙。
現(xiàn)在有了一個類和IDD_DIALOG1資源相關(guān)聯(lián)通砍。接卸來希望顯示虎忌,為此增加一個菜單項挑围,用戶點擊顯示對話框。在【幫助】下添加【對話框】寓搬,去掉Pop-up,ID設(shè)置為ID_DIALOG。
6.2.1模態(tài)對話框
創(chuàng)建模式對話框需要調(diào)用CDialog類的成員函數(shù):DoModal,該函數(shù)的功能就是創(chuàng)建并顯示一個模式對話框。為此視類添加ID_DIALOG響應(yīng)函數(shù)如下猪钮。
void CMyMFCAppView::OnDialog()
{
//TODO: 在此添加命令處理程序代碼
CTestDlg dlg;
dlg.DoModal();
}
6.2.2非模態(tài)對話框
創(chuàng)建無模式對話框需要調(diào)用CDialog類的成員函數(shù):BOOL Create(UINT nIDTemplate, CWnd* pParentWnd = NULL);第一個參數(shù)可以是資源ID魄懂,也可以是名稱篡腌,第二個指定父窗口。當(dāng)利用Create函數(shù)創(chuàng)建無模式對話框時睛约,還需要調(diào)用ShowWindow函數(shù)將這個對話框顯示出來。且不能設(shè)為局部變量加Detach方式材蹬。有兩種方式辉川,其一是將其定義為視類的成員變量,其二是將其定義為指針塞颁,分配在堆上澡腾,需要在視類析構(gòu)函數(shù)delete釋放,或者重構(gòu)CTestDlg類虛函數(shù)PostNcDestory渺绒。
void CMyMFCAppView::OnDialog()
{
//TODO: 在此添加命令處理程序代碼
CTestDlg *dPlg = new CTestDlg;
dPlg->Create(IDD_DIALOG1, this);
dPlg->ShowWindow(SW_SHOW);
}
void CTestDlg::PostNcDestroy()
{
//TODO: 在此添加專用代碼和/或調(diào)用基類
delete this;
CDialogEx::PostNcDestroy();
}
若要在程序中主動銷毀無模式對話框(例如在沒有 “確定”和“取消”按鈕的情況下銷毀對話框)氮采,需調(diào)用函數(shù)DestroyWindow。
6.3動態(tài)創(chuàng)建按鈕
實現(xiàn)一個功能伯铣,單擊對話框中某個按鈕腔寡,在對話框動態(tài)創(chuàng)建一個新按鈕。
1)為IDD_DIALOG1創(chuàng)建一個對話框資源却舀,ID屬性設(shè)置為IDC_BTN_ADD,Caption為Add袭艺。
2)添加自定義私有變量CButton類的m_btn绸吸。
3)CTestDlg類為IDC_BTN_ADD響應(yīng)BN_CLICKED消息。WS_VISIBLE沒有則需要ShowWindow函數(shù)设江。
m_btn.Create("New", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0,0, 100, 100), this, 123);
4)位CTestDlg類添加私有成員變量或者靜態(tài)局部變量BOOL類m_bIsCreated锦茁,用來標(biāo)識是否已經(jīng)創(chuàng)建。亦可以用一個成員變量m_hWnd
void CTestDlg::OnClickedBtnAdd()
{
//TODO: 在此添加控件通知處理程序代碼
if (FALSE == m_bIsCreated)
{
m_btn.Create("New", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, CRect(0,0, 100, 100), this, 123);
m_bIsCreated = TRUE;
}
else
{
m_btn.DestroyWindow();
m_bIsCreated = FALSE;
}
}
void CTestDlg::OnClickedBtnAdd()
{
//TODO: 在此添加控件通知處理程序代碼
if (!m_btn.m_hWnd)
m_btn.Create("New", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0,0, 100, 100), this, 123);
else
m_btn.DestroyWindow();
}
6.4控件的訪問
6.4.1靜態(tài)文本控件
實現(xiàn)點擊”Number1:”叉存,文本變成“數(shù)值1:”码俩。
1)首先設(shè)置ID號為IDC_NUMBER1以區(qū)分三個靜態(tài)文本。
2)響應(yīng)IDC_NUMBER1的BN_CLICKED消息歼捏。
3)控件也是窗口稿存,所以可以利用CWnd的成員函數(shù)GetWindowText。
4)靜態(tài)文本在默認(rèn)狀態(tài)下不可以發(fā)送通告消息瞳秽,在屬性對話框選定Notify選項瓣履。
void CTestDlg::OnStnClickedNumber1()
{
//TODO: 在此添加控件通知處理程序代碼
CString str;
if (GetDlgItem(IDC_NUMBER1)->GetWindowText(str), str == "Number1:")
GetDlgItem(IDC_NUMBER1)->SetWindowText("數(shù)值1:");
else
GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1:");
}
6.4.2 編輯框控件
1)GetDlgItem + Get/SetWindowText.重要函數(shù):CWnd* GetDlgItem(int nID) const;該函數(shù)返回一個指向由參數(shù)nID指定的控件對象的指針。
int num1, num2, num3;
char c1[10], c2[10], c3[10];
GetDlgItem(IDC_EDIT1)->GetWindowText(c1,10);
GetDlgItem(IDC_EDIT2)->GetWindowText(c2,10);
num1 = atoi(c1);
num2 = atoi(c2);
num3 = num1 + num2;
itoa(num3, c3, 10);
GetDlgItem(IDC_EDIT3)->SetWindowText(c3);
2) Get/SetDlgItemText练俐。該函數(shù)返回對話框中指定nID的控件上的文本袖迎。也就是說:GetDlgItemText函數(shù)把方法1中介紹的GetDlgItem和GetWindowText這兩個函數(shù)的功能組合起來了。
int num1, num2, num3;
char c1[10], c2[10], c3[10];
GetDlgItemText(IDC_EDIT1, c1, 10);
GetDlgItemText(IDC_EDIT2, c2, 10);
num1 = atoi(c1);
num2 = atoi(c2);
num3 = num1 + num2;
itoa(num3, c3, 10);
SetDlgItemText(IDC_EDIT3, c3);
3)Get/SetDlgItemInt腺晾。該函數(shù)首先獲得對話框中指定nID的控件上的文本燕锥,然后將其轉(zhuǎn)換為一個整型數(shù)值返回。
int num1, num2, num3;
num1 = GetDlgItemInt(IDC_EDIT1);
num2 = GetDlgItemInt(IDC_EDIT2);
num3 = num1 + num2;
SetDlgItemInt(IDC_EDIT3,num3);
4)MFC的DDX數(shù)據(jù)交換——控件和整型變量關(guān)聯(lián)悯蝉。最簡單的訪問控件的方式:通過類向?qū)Ч樾危趯υ捒蚝瘮?shù)DoDataExchange內(nèi)部實現(xiàn)對話框控件與對話框類的成員變量相關(guān)聯(lián)。類別為Value鼻由。為了讓數(shù)據(jù)交換生效暇榴,需調(diào)用UpdateData函數(shù)。(DDX對話框數(shù)據(jù)交換嗡靡,DDV對話框數(shù)據(jù)校驗)
UpdateData(); //成員變量從對話框控件中獲取數(shù)據(jù)
m_num3 = m_num1 + m_num2;
UpdateData(FALSE); //以成員變量的值初始化對話框控件
5)MFC的DDX數(shù)據(jù)交換——控件和控件變量關(guān)聯(lián)跺撼。類別為Control。CEdit派生于CWnd類讨彼,所以可以調(diào)用GetWindowText等函數(shù)歉井。
int num1, num2, num3;
char c1[10], c2[10], c3[10];
m_edit1.GetWindowText(c1,10);
m_edit2.GetWindowText(c2,10);
num1 = atoi(c1);
num2 = atoi(c2);
num3 = num1 + num2;
itoa(num3, c3, 10);
m_edit3.SetWindowText(c3);
6)發(fā)送消息——SendMessage。Windows程序是基于消息的系統(tǒng)哈误,因此哩至,只要獲取設(shè)置窗口文本的消息躏嚎,就可以通過SendMessage來發(fā)送這條消息,從而獲取/設(shè)置窗口的文本菩貌。
int num1, num2, num3;
char c1[10], c2[10], c3[10];
::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd, WM_GETTEXT, 10, (LPARAM)c1);
::SendMessage(m_edit2.m_hWnd, WM_GETTEXT,10, (LPARAM)c2);
num1 = atoi(c1);
num2 = atoi(c2);
num3 = num1 + num2;
itoa(num3, c3, 10);
m_edit3.SendMessage(WM_SETTEXT, 0,(LPARAM)c3);
7)發(fā)送消息——SendDlgItemMessage卢佣。直接給對話框的子控件發(fā)送消息:
LRESULTSendDlgItemMessage(int nID, UINT message, WPARA wParam = 0, LPARAM lParam = 0)
該函數(shù)功能相當(dāng)于把上面GetDlgItem和SendMessage這兩個函數(shù)的組合。
int num1, num2, num3;
char c1[10], c2[10], c3[10];
SendDlgItemMessage(IDC_EDIT1, WM_GETTEXT, 10, (LPARAM)c1);
SendDlgItemMessage(IDC_EDIT2, WM_GETTEXT, 10, (LPARAM)c2);
num1 = atoi(c1);
num2 = atoi(c2);
num3 = num1 + num2;
itoa(num3, c3, 10);
SendDlgItemMessage(IDC_EDIT3, WM_SETTEXT, 0, (LPARAM)c3);