八、為對話方塊新增類、物件(變數)以及訊息響應函式
1. 為對話方塊新增類:
a. 四種方法:
*1. 在對話方塊空白處右鍵→建立類嚮導;
*2. 在對話方塊空白處雙擊(推薦使用!方便快捷);
*3. 選單欄→檢視(View)→建立類嚮導;
*4. 快捷鍵Ctrl + W;
b. 如果該對話方塊還沒建立過類,則會彈出新增類對話方塊(Adding a Class),直接選擇OK即可;
c. 在新增類過程中(即在New Class對話方塊中)我們需要為在圖形介面下設計的對話方塊取一個類名,這裡我們取CStudentDlg:
i. C表示Class,即類,系統會為我們自動生成.cpp檔案,其名字會去掉C;
ii. Dlg就是Dialog的縮寫;
d. 在建立時可以看到Dialog ID系統已經自動填寫了IDD_STUDENTMANAGEMENT,即已經自動將建立的類和我們所設計的對話方塊關聯起來了;
e. 修改.cpp檔名:
i. 在檔名過長不方便時應該直接修改類名;
ii. 在檔名和已存在工程中的檔名衝突時可以考慮修改.cpp檔名,選擇Change按鈕進入修改即可;
2. 小結——從圖形到類物件的實質:
a. 即圖形只是一種抽象,但是到了程式裡面必須是要以資料描述的;
b. 因此要為圖形物件建立類,完成從圖形到資料描述(即程式碼描述)的過渡;
c. 而在MFC中建立圖形和類之間的聯絡的實質就是將類、變數等直接和圖形的ID建立聯絡;
d. 也就是說類名、變數名等是對資料的描述,而ID則是對圖形的描述,即前者是資料的代號,而後者是圖形的代號;
3. 為對話方塊中的控制元件新增成員變數:
a. 在圖形介面下控制元件是對話方塊的一部分,因此在資料描述中,空間就應該是對話方塊類的成員變數,即成員物件;
b. 開啟類嚮導後,選擇剛建立的對話方塊類,即ID為IDD_STUDENTMANAGEMENT,類名為CStudentDlg,選擇Member Variable選項卡;
c. 裡面已經直接列出了對話方塊中包含的控制元件的ID,但是新增的成員變數還是空白的;
d. 為每個ID所代表的的控制元件新增成員變數(即將圖形介面下的控制元件和資料層面上的成員變數建立聯絡),兩種方法:
*1. 用滑鼠點選相應的ID號,然後點選Add Variable;
*2. 直接雙擊目標ID號;
e. 接著就是輸入各個成員變數名即可,而對於型別,系統已經根據控制元件的型別為你自動選好了:
i. 編輯框對應變數的型別可定是CString的,因為框中輸入的肯定是字串;
ii. 單選框對應變數的型別是int型的,這樣可以方便使用switch語句判斷使用者選擇的是哪個單選框,規則是按照Tab順序0, 1, 2遞增;
iii. 複選框對應變數的型別是BOOL型的,是typedef過的int,同樣也定義了TRUE和FALSE巨集,其值分別為int型的1和0;
iv. 列表和組合框對應的變數型別是CString的,因為框中顯示的內容都是字串;
v. 對於字串變數,可以在Maximum Characters中填寫字串的最大長度;
f. 編輯完成確定後就會自動在類程式碼中生成這些變數的定義宣告,同時會自動生成CStudentDlg類的建構函式:
CStudentDlg::CStudentDlg(CWnd* pParent /*=NULL*/)
: CDialog(CStudentDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CStudentDlg)
m_art = FALSE;
m_clanguage = FALSE;
m_duty = _T("");
m_english = FALSE;
m_grade = -1;
m_ID = _T("");
m_major = _T("");
m_math = FALSE;
m_name = _T("");
m_philosophy = FALSE;
m_physics = FALSE;
//}}AFX_DATA_INIT
}
i. 可見預設建構函式是將所有的內容都初始化為空的;
ii. _T巨集,表示字串所用的字符集(以TCHAR *str = _T("abc")為例):
*1. 在ANSI模式下編譯就是:char *str = "abc";
*2. 在UNICODE模式下編譯就是:wchar_t *str = L"abc";
其中_t和L都表示UNICODE字符集;
g. 自動生成資料交換函式DoDataExchage:
void CStudentDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CStudentDlg)
DDX_Check(pDX, IDC_ART, m_art);
DDX_Check(pDX, IDC_CLANGUAGE, m_clanguage);
DDX_LBString(pDX, IDC_DUTY, m_duty);
DDX_Check(pDX, IDC_ENGLISH, m_english);
DDX_Radio(pDX, IDC_GRADE, m_grade);
DDX_Text(pDX, IDC_ID, m_ID);
DDX_CBString(pDX, IDC_MAJOR, m_major);
DDX_Check(pDX, IDC_MATH, m_math);
DDX_Text(pDX, IDC_NAME, m_name);
DDV_MaxChars(pDX, m_name, 50);
DDX_Check(pDX, IDC_PHILOSOPHY, m_philosophy);
DDX_Check(pDX, IDC_PHYSICS, m_physics);
//}}AFX_DATA_MAP
}
i. 該函式將會在填寫完對話方塊中的內容並點選OK退出對話方塊時呼叫;
ii. 作用就是將對話方塊內填寫的資料存入各個控制元件物件中以實現對使用者資料的讀取,專業地將就是實現後臺和對話方塊的資料交換;
iii. DDX_就是資料交換函式,即Do Data Exchange的縮寫,從引數可以看出將指定ID號所代表的控制元件中的資料存入指定的成員變數中去;
iv. 其還有一個功能,就是檢驗使用者輸入的資料是否合法,比如在為控制元件新增變數時如果設定過字串的最大長度,則在這裡則會以函式的形式體現出來,比如這裡的DDV_MaxChars函式,用來檢驗交換而來的m_name變數中字元數是否超過50個;
v. 所有資料檢驗函式都是以DDV_開頭的;
vi. DoDataExchange函式不是人為呼叫的,而是由UpdateData函式呼叫的,即對資料進行更新的一個函式,這很顯然,當用戶輸入完對話方塊中的內容並按OK按鈕退出時就應該呼叫UpdateData函式,其間接呼叫DoDataExchange函式實現用使用者輸入的資料對程式中的資料進行更新;
4. 為列表框和組合框新增初始化內容:
a. 即當用戶開啟對話方塊時,對話方塊物件需要自動對列表框和組合框中的內容進行初始化,即提供選項供使用者選擇;
b. 該項工作在OnInitDialog函式中完成,它同樣也是一個訊息相應函式,相應的訊息是WM_INITDIALOG;
c. 該訊息一般會在開啟對話方塊時傳送給相應的對話方塊;
d. 因此可以為相應對話方塊類新增相應該訊息的函式,該函式理所當然是對話方塊類的成員函式;
e. 在資源檢視中CStudentDlg類上右鍵→Add Windows Message Handler..(即新增Windows訊息響應);
f. 然後在左側雙擊WM_INITDIALOG將該訊息響應新增到右側存在的訊息響應中,此時已經為該類添加了一個響應WM_INITDIALOG訊息的函數了;
g. 最後點選Edit Existing進入編輯該函式的程式碼區;
h. OnInitDialog函式實現:
BOOL CStudentDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
//GetDlgItem函式的作用即使返回指定ID號的控制元件的指標
//由於該函式返回的指標型別是控制元件類的父類,即CStudentDlg類
//因此在這裡需要進行強制型別轉換(擴充套件轉換,但是是安全的)
CListBox *pList = (CListBox *)GetDlgItem(IDC_DUTY);
pList->AddString("普通成員");//控制元件的通用成員函式,向列表框和組合框中新增新的字串專案
pList->AddString("班長");
pList->AddString("副班長");
pList->AddString("學習委員");
pList->AddString("生活委員");
CComboBox *pCom = (CComboBox *)GetDlgItem(IDC_MAJOR);
pCom->AddString("通訊工程");
pCom->AddString("計算機應用");
pCom->AddString("電子技術");
pCom->AddString("圖書管理學");
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}