1. Windows應用程序工作的基本流程是從用戶那裏得到數據,經過相應的處理之後,現把處理結果輸出到屏幕,打印機或者綿輸出設備。這就需要用到Windows應用程序的用戶接口對話框。對話框就是一個窗口,它不僅可以接收消息,而且還可以被移動和關閉,甚至可以在它的客戶區中進行繪圖。相當於一個窗口,在它上面能夠旋轉各種標準控件和擴展控件。都是由CWnd類派生來
2. 對話框的類型:模態(Model)對話框和非模態(Modeless)對話框
(1)模態對話框:指當其顯示時,程序會暫停執行,直到關閉這個模態對話框後,才能繼續執行程序中其它任務。
當一個模態對話框打開時,用戶只能與該對話框進行交互,而其它用戶界面對象接收不到輸入信息。
(2)非模態對話框:當其顯示時,允許執行程序中其它任務,而不用關閉這個對話框。
在MFC中,對資源的操作通常都是通過一個與資源相關的類來完成。對話框資源對應CDialog基類。
3. 在對話框資源界面,選擇[View]->[ClassWizard]菜單命令,(也可以新建的對話框資源上雙擊鼠標左鍵),選擇一個基類,創建關於它的類。其中一般有兩個函數一個是構造函數(可用於初始化成員變量),另外一個是DoDataExchange主要用來完成對話框數據的交換和校驗,要想在其它窗口的事件中顯示該對話框就涉及到創建對話框的模式(模態與非模態)
(1)模態對話框的創建
創建模態對話框要調用CDialog類的成員函數:DoModel(),創建一個模態對話框,其返回值作爲CDialog類的另一個成員函數:EndDialog的參數,後者的功能就是關閉模態對話框。
Void CMyboleView::OnDialog(){
CTestDlg dlg;//視類中源文件要包含這個類的頭文件
dlg.DoModal();//創建一個模態對話框,
}
(2)非模態對話框的創建
需要利用CDialog類的Create成員函數。
BOOL Create(LPCTSTR lpszTemplateName, CWnd* pParaentWnd = NULL);
BOOL Create(UINT nIDTemplate, Cwnd* pParentWnd = NULL);
lpszTemplateName對話框模板的名稱,nIDTemplate對話框模板的ID,pParentWnd對話框的父窗口,如果是NULL則父窗口就是主應用程序窗口
注意:當創建非模態對話框時,還需要調用ShowWindow函數顯示對話框,而模態的不需要
Void CMyboleView::OnDialog(){
CTestDlg *pDlg = new CTestDlg;//定義成指針,在堆上分配內存(或定義爲全局變
//量,在堆上分配的內存如不主動銷燬則與程序生命週期一樣,
pDlg->Create(IDD_DIALOG1, this);//創建一個非模態對話框,使用對話框ID,
//父窗口是調用OnDalog函數的窗口
pDlg->ShowWindow(SW_SHOW);//顯示窗口
}
4. 動態添加Button
void CDlg::OnBtnAdd()
{
if (!IsCreated/*m_btn.h_Wnd*/)//也可使用m_btn對象中的成員變量判斷句柄是否有值
{
m_btn.Create("New", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0, 0, 100, 100), this, 123);//在對話框上動態添加一個按鈕
IsCreated = TRUE;//判斷是否已經創建了按鈕,是的話銷燬,現點擊可再重新創建
}
else
{
m_btn.DestroyWindow();//銷燬窗口,因爲按鈕也是從CWnd繼承來
IsCreated = FALSE;
}
}
5. 控件的訪問
獲取對話框上的項目指針:GetDlgItem()
獲取窗口信息:GetWindowText()
更改窗口信息:SetWindowText()
直接取得對指定話框上項目的信息:GetDlgItemText() 想當於GetDlgItem()和GetWindowText()合用。
同理有SetDlgItemText() 相當於GetDlgItem()和SetItemText() 合用。
GetDlgItemInt(),SetDlgItemInt()等等,S/GetDlgItemInt()可以處理有符號的整數。
字符到數組的轉換:atoi() 轉換一個類型到指定類型時,用 類型的第一個字母 to 指定類型的一個字母。
在DoExchange函數裏,放置以DDX_爲前綴的函數,來關聯一個控件和變量,DDV_爲前綴的函數,用來校驗一個控件內容。DDX_(對話框數據交換) DDV_(對話框數據校驗)
注意,在用數據變量關聯控件的方式時,千萬注意要使用UpdateData()!
也可以用一個控件變量關聯一個控件,用它的成員函數,來對控件進行操作,例如:CEDIT.GetWindowText()
SendMessage()的用法,比較好用,注意,發送消息,是控件向系統發送,由系統處理。
SendDlgItemMessage()。
SendMessage(),Windows程序都基於消息的,爲了獲取或設置窗口的文本,只要知道獲取或設置窗口文本的消息,就可以通過SendMessage來發送這條消息,從而獲取或設置控件的文本。獲取窗口文本的消息是WM_GETTEXT發送該消息後,系統將把指定窗口的文本複製到調用者提供的一個緩存中,在這個消息兩個附加參數中,wParam指定將複製的字符數據,lParm就是調用者提供的用來保存窗口文本的緩存地址。WM_SETTEST消息wParam參數沒用,值爲0,lParam參數指定用來設置文本字符串地址;SendDlgItemMessage()
幾種控件操作的代碼:
void CTestDlg::OnBtnAdd()
{
//點擊後創建一個新的按鈕
// if (!m_btn)
// {
// m_btn.Create("新按鈕", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, CRect(0, 0, 100, 20), this, 123);
// }
// if (!m_btn.m_hWnd)
// {
// m_btn.Create("新按鈕", BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD, CRect(0, 0, 100, 20), this, 123);
// }
// else{
// m_btn.DestroyWindow();
// }
/*對話框控件訪問方式
(1):GetDlgItem()->G(S)etWidowText()方式
*/
/*int num1, num2, num3;
char ch1[10], ch2[10], ch3[10];
GetDlgItem(IDC_NUM1)->GetWindowText(ch1, 10);
GetDlgItem(IDC_NUM2)->GetWindowText(ch2, 10);
num1 = ::atoi(ch1);
num2 = ::atoi(ch2);
num3 = num1 + num2;
::itoa(num3, ch3, 10);
GetDlgItem(IDC_NUM3)->SetWindowText(ch3);
*/
/*對話框控件訪問方式
(2):G(S)etDlgItemInt()方式
*/
/*int num1, num2, num3;
num1 = GetDlgItemInt(IDC_NUM1, NULL, TRUE);
num2 = GetDlgItemInt(IDC_NUM2, NULL, TRUE);
num3 = num1 + num2;
SetDlgItemInt(IDC_NUM3, num3, TRUE);
*/
/*對話框控件訪問方式
(3):G(S)etDlgItemText()方式
*/
/*int num1, num2, num3;
char ch1[10], ch2[10], ch3[10];
GetDlgItemText(IDC_NUM1, ch1, 10);
GetDlgItemText(IDC_NUM2, ch2, 10);
num1 = ::atoi(ch1);
num2 = ::atoi(ch2);
num3 = num1 + num2;
::itoa(num3, ch3, 10);
SetDlgItemText(IDC_NUM3, ch3);
*/
/*對話框控件訪問方式
(4):將控件和整型變量相關聯,然後調用UpdateData(TRUE)初始化或校驗數據,在操作完成後調用UpdateData(FALSE);實現對話框數據初始化
*/
/*注意,該方法有數據校驗的功能,在添加變量時可以指定數據值的範圍
UpdateData(TRUE);//獲取編輯框中的數據
m_num3 = m_num2 + m_num1;//數據操作(+)
UpdateData(FALSE);//初始化編輯框3中的數據,即將變量中的數據顯示到控件中
*/
/*對話框控件訪問方式
(5):將控件和控件變量相關聯,然後調用控件變量的G(S)etWindowext方法
*/
/*int num1, num2, num3;
char ch1[10], ch2[10], ch3[10];
m_cNum1.GetWindowText(ch1, 10);
m_cNum2.GetWindowText(ch2, 10);
num1 = ::atoi(ch1);
num2 = ::atoi(ch2);
num3 = num1 + num2;
::itoa(num3, ch3, 10);
SetDlgItemText(IDC_NUM3, ch3);
*/
/*對話框控件訪問方式
(6):SendMessage(),平臺SDK的函數,發送WM_GETTEXT/WM_SETTEXT消息
*/
/*int num1, num2, num3;
char ch1[10], ch2[10], ch3[10];
::SendMessage(GetDlgItem(IDC_NUM1)->m_hWnd, WM_GETTEXT, 10, (LPARAM)ch1);
::SendMessage(GetDlgItem(IDC_NUM2)->m_hWnd, WM_GETTEXT, 10, (LPARAM)ch2);
num1 = ::atoi(ch1);
num2 = ::atoi(ch2);
num3 = num1 + num2;
::itoa(num3, ch3, 10);
::SendMessage(GetDlgItem(IDC_NUM3)->m_hWnd, WM_SETTEXT, 10, (LPARAM)ch3);
GetDlgItem(IDC_NUM1)->SendMessage(WM_GETTEXT, 10, (LPARAM)ch1);
*/
/*對話框控件訪問方式
(8):SendDlgItemMessage()
*/
int num1, num2, num3;
char ch1[10], ch2[10], ch3[10];
SendDlgItemMessage(IDC_NUM1, WM_GETTEXT, 10, (LPARAM)ch1);
SendDlgItemMessage(IDC_NUM2, WM_GETTEXT, 10, (LPARAM)ch2);
num1 = ::atoi(ch1);
num2 = ::atoi(ch2);
num3 = num1 + num2;
::itoa(num3, ch3, 10);
SendDlgItemMessage(IDC_NUM3, WM_SETTEXT, 0, (LPARAM)ch3);
SendDlgItemMessage(IDC_NUM3, EM_SETSEL, 0, -1);
GetDlgItem(IDC_NUM3)->SetFocus();
// GetDlgItem(IDC_NUM1)->GetWindowText(ch1, 10);
// GetDlgItem(IDC_NUM2)->GetWindowText(ch2, 10);
// num1 = ::atoi(ch1);
// num2 = ::atoi(ch2);
// num3 = num1 + num2;
// itoa(num3, ch3, 10);
// GetDlgItem(IDC_NUM3)->SetWindowText(ch3);
// CString str1, str2, str3;
// int num1, num2, num3;
// GetDlgItem(IDC_NUM1)->GetWindowText(str1);
// GetDlgItem(IDC_NUM2)->GetWindowText(str2);
// num1 = ::atoi(str1);
// num2 = ::atoi(str2);
// num3 = num1 + num2;
// str3.Format("%d", num3);
// GetDlgItem(IDC_NUM3)->SetWindowText(str3);
// UpdateData();
// m_num3 = m_num1 + m_num2;
// UpdateData(FALSE);
}
說明:
(1)itoa函數:將整型轉換成字符
(2)atoi函數:將字符轉換成整型
(3)SendMessage函數:要使用SDK函數,前面加::表示全局函數,第一個參數句柄可以先獲取控件句柄然後再取出其m_hWnd窗口句柄變量,如果控件綁定變量,使用變量的SendMessage函數則不需要句柄值
6. 伸縮對話框
改變窗口的大小Wnd::SetWindowPos()對話框從父類繼承來的函數。
判斷一個矩形是否爲空:IsRectEmpty(),IsRectNull()。
前者是判斷矩形面積是否爲空,後者是判斷矩形的四個座標值是否爲0,不關心是否能做爲一個矩形。
·····SetWindowPos()改變窗口的大小和Z次序的排列。 ·····
7. 焦點的問題
SetFocus()
SetWindowLong
::GetNextWindow()
::GetWindow()
::GetNextDlgTabItem()
CWnd::GetWindow()
CWnd::GetNextWindow
CWnd::GetNextDlgTabItem()
缺省OK按鈕的ID爲IDOK,
VC++環境下打開對話框資源編輯器,選擇[Layout]->[Tab order]可以查看和調整對話框上控件的tab順序;
8. 在用變量來更新控件值,更新控件數據與獲取控件數據都要注意一點:
無論是獲取數據還是更新窗口上的數據都是要進行數據交換,要使用UpdateData函數,
Void CTestDlg::OnBtnAdd(){
UpdateData();//使控件變量獲取控件上的數據
m_num3 = m_num1 + m_num2;//三個變量都是綁定控件的,對應控件中的值
UpdateData(FALSE);//函數默認參數爲TRUE,要更新控件數據設置爲FALSE
}
9. 如何改變按鈕的字體?在對話框的屬性中改變字體的屬性即可
10. 逃跑按紐的實現
(1)從CButton派生一個類,CWeixinBtn
(2)將IDC_EDIT1關聯成員變量m_btn1,類型爲CWeixinBtn,注意要包含頭文件。
(3)在CWeixinBtn中加一個指針成員變量CWeixinBtn *pWeixinBtn,然後將其地址初始化。
(4)在新類中增加鼠標移動的消息處理。
11.屬性表單
(1)插入屬性頁資源。Insert->new Resource->Dialog
(2)當選擇Classwizard菜單時,系統提示是否爲創建新的類,我們將其從CPropertyPage派生!這樣可以爲方便爲其
增加消息響應函數。
(3)插入新的從CPropertySheet派生的類,在類中增加3個CPropertyPage的實例。
(4)在view中增加菜單項,當點擊時顯示屬性表單,出現中文亂碼,修改CPropertyPage屬性爲中文,另外將其字體
設爲宋體。
(5)在CPropertyPage中設置SetWizardButtons可將其屬性改爲上一步、完成!
(6)爲IDC_RADIO1關聯成員變量,需要先設置Group屬性才行。另外別忘記調用UpdateData().
(7)爲CPropertyPage增加虛函數,OnWizardNext,如果用戶點擊下一步時,不想讓他進入下一步,剛返回-1!
(8)將用戶的選擇輸出到屏幕上,此時可以在View中增加幾個成員變量,用來接收用戶選擇的數據。
注意: memset()的用法! memset(m_bLike,0,sizeof(m_bLike));將所指定長度設置爲0
ZeroMemory(m_bLike, sizeof(m_bLike));同上效果