本程序主要實現如下功能:
程序通過左邊的樹形控件顯示本地計算機中目錄的結構,右邊的列表控件則負責響應樹形控件中選擇的目錄節點并把此節點中的所有項在列表框中顯示出來,列表框支持奇偶行顏色設置,選中顏色設置和熱點顏色設置;
本程序支持顯示或不顯示隱藏文件和系統文件,支持文件的重命名、打開、復制、移動和刪除操作,刪除操作支持刪除到回收站和徹底刪除選擇。
同時支持地址欄跳轉功能。支持屬性欄的時間顯示
程序主界面:
?
1.?????? 模式與無模式對話框
本程序是基于對話框而設計的,對話框分為模式對話框和無模式對話框。對于模式對話框,當該對話框在關閉之前,用戶不能夠在同一應用程序中進行其它的操作,這類對話框如“打開文件”對話框等;而對于無模式對話框,當該對話框顯示后用戶可以進行其它的操作,這類對話框僅僅是一個彈出窗口,如“替換查找”對話框等。
新建一個MFC的Demo對話框程序,默認設置,Finished 完成新建。然后在資源視圖中再新建兩個Dialog,右鍵這新建的Dialog 把它們的Caption,改為ModeDlg 和NonModeDlg 把ID號分別改為IDD_MODEDLG 和IDD_NONMODEDLG ,改好后,ModeDlg 和NonModeDlg對話框模版就新建好了,那么如何來使用它們呢?若要在這些新建的對話框上進行消息響應,就要為這些對話框模版生成一個CDialog派生類才行,那么如何為ModeDlg和NonModeDlg生成它們的派生類呢?在ModeDlg對話框點擊右鍵,選擇類向導(Class Wizard)
,然后點擊添加類(Add class)新建一個CModeDlg類(即在彈出的MFC類向導對話中,在對話框的“類名”欄中輸入CModeDlg,并選擇該類的基類為CDialog類。單擊“完成”按鈕以新建CModeDlg類。)如圖:
?
同樣,在NonModeDlg對話框中右鍵,選擇類向導(Class Wizard)然后添加一個CNonModeDlg類。然后打開IDD_DEMO_DIALOG對話框,在它上面添加兩個按鈕,分別命名為ModeDlg和NonModeDlg ,同時這兩個按鈕的ID號分別換成IDC_MDlg ,IDC_NMDlg。然后右鍵點擊ModeDlg按鈕選擇添加事件句柄(Add Event Handler...),在彈出的事件句柄向導對話框中,為按鈕選擇單擊事件,所以消息類型選擇BN_CLICKED,按鈕是在IDD_DEMO_DIALOG對話框上,所以它的消息事件應該建立在CDemoDlg這個類里面,最后函數句柄的名稱默認即可。具體如圖:?
?
單擊添加并編輯以新建ModeDlg按鈕響應函數OnBnClickedMdlg,以同樣的方式為NonModeDlg按鈕在CDemoDlg類中添加BN_CLICKED事件句柄函數OnBnClickedNmdlg,
為了在CDemoDlg類中使用ModeDlg對話框和NonModeDlg的類,首先需要將它們的頭文件包含到DemoDlg.h文件中,即在DemoDlg.h文件添加:
#include"ModeDlg.h"
#include"NonModeDlg.h"
然后回到DemoDlg.cpp文件,在剛添加的ModeDlg按鈕響應函數中,創建CModeDlg類的實例,并調用DoModal函數顯示對話框,代碼如下:
void CDemoDlg::OnBnClickedMdlg()
{
??? CModeDlg dlg;? //創建CModeDlg類實例dlg
??? dlg.DoModal();? //調用DoModal()函數顯示對話框
}
下面在添加的NonModeDlg按鈕函數OnBnClickedNmdlg()來創建并顯示無模式對話框,創建無模式對話框,首先生成一個CNonModeDlg類的實例,然后調用Create()函數來創建無模式對話框,最后調用ShowWindow()來顯示無模式對話框,添加代碼如下:
void CDemoDlg::OnBnClickedNmdlg()
{
??? CNonModeDlg *pDlg = new CNonModeDlg();// 創建一個CNonModeDlg類的實例
??? pDlg->Create(IDD_NONMODEDLG,this); // 創建無模式對話框
??? pDlg->CenterWindow();? //對話框居中顯示
??? pDlg->ShowWindow(SW_SHOW); //顯示對話框
}
?
注意Create()函數中的第一個參數是無模式對話框的ID號,當編寫完
pDlg->Create(IDD_NONMODEDLG,this); 這行代碼后,提示IDD_NONMODEDLG 沒有定義,這是因為沒有包含Resouce.h頭文件,導致它找不到這個ID號,所以在DemoDlg.cpp中包含這個頭文件即可。
還需要注意的是,關閉調用DoModal()函數創建的模式對話框時,系統會自動回收模式對話框申請的資源,但是當關閉無模式對話框時,系統不會自動回收和釋放創建無模式對話框時所申請的資源,所以在無模式對話框被關閉時需要手動回收它創建時申請的資源,否則會造成內存泄露!那么如何手動來回收它申請的資源呢?
在“類視圖“窗口中選擇CNonModeDlg類,并單擊屬性窗口中的屬性按鈕,然后重寫PostNcDestroy函數。在該函數中添加一條delete語句以銷毀對話框,回收資源,代碼如下:
void CNonModeDlg::PostNcDestroy()
{
??? delete this;
??? CDialog::PostNcDestroy();
}
下面介紹一下本程序需要程序的控件,在后面的程序中用到時再做更詳細的使用說明。
?
控件名稱 | MFC類 | 說明 |
靜態控件 | CStatic | 用于顯示一些固定不變的文字或圖形 |
按鈕 | CButton | 用于產生某些命令消息,包括單選,復選和按鍵按鈕 |
編輯框 | CEdit | 用于完成文本和數字的輸入和編輯 |
列表框 | CListBox | 顯示一個列表,讓用戶從中選取一個或多個項 |
組合框 | CComboBox | 是一個列表框和編輯框組合的控件 |
列表控件 | CListCtrl | 包含圖標,標簽顯示內容的控件 |
樹形控件 | CTreeCtrl | 以樹結構形式顯示一組信息,能夠反映這些信息的結構 |
?
默認情況下,所有靜態控件的ID標識符都是IDC_STATIC,其表示是靜態的并且顯示的內容不能夠改變,不能夠為這類控件添加成員變量,消息響應函數等。如果需要動態地改變靜態控件上的顯示,則需要為這些控件重新指定一個非IDC_STATIC的ID標識符,然后才能在程序中為靜態控件添加成員變量,消息響應函數等。
可以調用CWnd類的GetDlgItem成員函數來獲取該控件的CWnd指針,或者通過調用GetDlgItemText或SetDlgItemText函數來改變靜態控件顯示的文本內容。
?
常見的按鈕主要有三種類型:按鍵按鈕、單選按鈕和復選按鈕。一般而言,需要為按鈕添加單擊事件BN_CLICKED消息的消息響應函數。同時可以調用CButton類的成員函數SetCheck和GetCheck分別來設置或獲取指定按鈕的選中狀態,原型如下:
void SetCheck(int nCheck);
int GetCheck() const;
其中nCheck和GetCheck函數返回的值可是:0表示不選中,1表示選中,2表示不確定(僅用于三態按鈕)。對于同組多個單選按鈕的選中狀態的設置或獲取,需要調用窗口類Cwnd的成員函數CheckRadioButton 和GetCheckedRadioButton ,原型如下:
void CheckRadioButton (int nIDFirstButton, int nIDLastButton,int nIDCheckButton);
int GetCheckedRadioButton(int nIDFirstButton,int nIDLastButton);
其中nIDFirstButton 和nIDLastButton 分別指定同組單選按鈕的第一個和最后一個按鈕的ID值;nIDCheckButton 用來指定要設置選中狀態的按鈕的ID值;函數GetCheckedRadioButton返回被選中的按鈕ID值。
在MFC中提供支持位圖按鈕的CBitmapButton類,它是CButton類的派生類,最多可以為位圖按鈕指定按鈕的正常、按下、獲得焦點和被禁用的四副狀態位圖。
在創建位圖按鈕時,首先需要為按鈕定義CBitmapButton類型的變量,然后調用CWnd類的成員函數SubclassDlgItem將變量關聯到按鈕控件上,再調用該類的的成員函數LoadBitmaps為按鈕加載相應狀態的位圖,最后還可以調用SizeToContent函數來調整按鈕的大小以適合位圖。這些函數的聲明如下:
BOOL SubclassDlgItem(UINT ID,CWnd* pParent);
BOOL LoadBitmaps(LPCTSTR lpszBitmapResource,
??????????????? LPCTSTR lpszBitmapResourceSel = NULL,
?????? ????????? LPCTSTR lpszBitmapResourceFocus = NULL,
??????????????? LPCTSTR lpszBitmapResourceDisabled =NULL);
?
BOOL LoadBitmaps(UINT nIDBitmapResource,
??????????????? UINT nIDBitmapResourceSel = 0,
??????????????? UINT nIDBitmapResourceFocus = 0,
??????????????? UINT nIDBitmapResourceDisabled = 0);
在創建位圖按鈕時,需要設置按鈕的OwnerDraw屬性為TRUE.
?
編輯框,作為一個讓用戶從鍵盤輸入和編輯文本的矩形框,當文本被修改或唄滾動時,會向父窗口發送一些消息,由此可以在屬性窗口中為編輯框控件添加這些消息的響應函數。
消息列表:
EN_CHANGE ?當編輯框中的文本已被修改,在新的文本顯示之后發送此消息
EN_HSCROLL 當編輯框的水平滾動條被使用,在更新顯示之前發送此消息
EN_KILLFOCUS 編輯框失去鍵盤輸入焦點時發送此消息
EN_MAXTEXT 文本數目達到了限制值時發送此消息
EN_SETFOCUS 編輯框得到鍵盤輸入焦點時發送此消息
EN_UPDATE 編輯框的文本已被修改,新的文本顯示之前發送此消息
EN_VSCROLL 當編輯框的垂直滾動條被使用,在更新顯示之前發送此消息
?
當編輯框顯示多行文本內容時,通常需要使用LineScroll 成員函數來滾動顯示文本,使用GetLineCount來獲取多行文本的行數。
int GetLineCount() const;
void LineScroll( int nLine, int nChars = 0);
其中, nLine 指定了縱向滾動的行數,nChars指定了水平滾動的字符數。但是如果指定了編輯框的對齊屬性,則nChars值無效。
?
列表框可分為單選,多選,擴展多選以及非選擇四種類型,默認風格下的單選列表框讓用戶一次只能選擇一個項;多選列表框則一次可以選擇多個項,而擴展多選列表框則充許用戶用鼠標拖動或其他特殊組合鍵進行選擇;非選列表框則不提供選擇功能。
?
當列表框創建之后,往往要添加、刪除、修改或獲取列表框中的列表項,這些操作都可調用MFC的CListBox類成員函數來實現。此外,列表框的項除了用字符串來標識外,還常常通過索引來確定。索引表明項目在列表框中排列的位置,它是以0為基準,即列表框中的第一項的索引是0,第二項為1等。列表框控件類CListBox常用的成員函數如下:
AddString? 向列表框中添加一個字符串
InsertString? 在列表框中指定位置插入一個字符串
DeleteString? 從列表框中刪除一個字符串
ResetContent 清空列表框所有入口
FindString 在列表框中刪除一個字符串
GetCurSel 返回列表框中當前選擇項的索引
SetCurSel 選擇一個列表框字符串
GetText? 從列表框中獲取某項的字符串
?
組合框是一個列表框和編輯框組合的控件。組合框大致可分為兩類,一類是對組合框中的列表框進行操作,另一類是對組合框中的編輯框進行操作,這些操作都可以調用CComboBox成員函數來實現,常用的成員函數如下:
AddString 在組合框中列表框的列表末尾添加一個字符串
DeleteString 刪除組合框中列表框中的一個字符串
InsertString 在組合框的列表框中插入一個字符串
ResetContent 刪除組合框中列表框和編輯框中的所有項
FindString 在組合框的列表框中查找具有指定前綴的第一個字符串
GetCurSel 取得組合框的列表框中當前選中項的索引
SetCurSel 在組合框的列表框中選擇一個字符串
GetLBText 從組合框的列表框中取得第一個字符串
GetCount 取得組合框的項數
?
最后再來談談DDX和DDV技術
MFC提供的DDX和DDV技術使用戶方便地對控件中的數據進行操作。DDX將數據成員變量與對話框中的控件相關聯,使得數據在控件之間或者控件與對話框之間能夠直接交換;DDV用于對控件中的數據進行校驗,以保證數據的合法性和有效性。
在為對話框資源創建對話框類時,MFC類向導將會自動為對話框類中添加數據交換函數DoDataExchange, 并在該函數中添加相應的數據交換函數或數據校驗函數。
需要注意的是,用戶不能直接調用DoDataExchange 函數,數據交換和校驗是由MFC負責處理的。數據交換和校驗機制都是由MFC框架實現的,MFC通過一組DDX交換函數和DDV驗證函數來實現控件數據的交換和數據的驗證。根據不同的控件類型,MFC提供了不同的數據交換函數,它們都是以DDX_作為前綴的。同樣數據校驗函數也都是以DDV_作為前綴,這些函數都不需要用戶自己添加,MFC會自動添加的。
?
需要注意的是: DoDataExchange 數據交換和數據校驗函數都具有雙向性。當為控件定義了數據變量后,可以通過CWnd::UpdateData函數實現對控件數據的輸入和讀取。當以TRUE參數調用UpdateData函數時,控件中的數據被保存到相關聯的成員變量中;如果以FALSE為參數調用UpdateData函數時,則成員變量的值將被傳遞到控件上。