第一卷 改進應用程序界麵
序
在"消息與命令"一章中,初步介紹了在MFC應用程序中如何使用菜單和工具欄進行工作。實際上,有關改進程序界麵方麵的知識還有很多。本章中詳細介紹如何改進應用程序的界麵,使之具有更好的用戶交互性。
第一章 控製條類
在Windows應用程序中,工具條、狀態條或對話框條等是經常可見的,為用戶提供了快速選擇程序功能的能力。在MFC基本類庫中,工具條、狀態條和對話框條都是控製條的子類。MFC對控製條提供了很好的支持,在下麵的幾節中,我們將比較詳細地介紹控製條的有關知識。
8.1.1 控製條
控製條類(CControlBar)是工具條類(CToolBar)、狀態條類(CStatusBar)和對話框條類(CDialogBar),以及Visual C++ 6.0中新增的集合條類(CReBar)的父類,同時,CControlBar類由CWnd類派生,圖8-1顯示了有關CControlBar的繼承關係。
圖8-1 CControlBar類的繼承關係
由於CControlBar類是CWnd類的子類,因此,控製條通常都是一個停泊在主框架窗口四周的小窗口。控製條可以包含基於hWnd句柄的控件,這些控件都是Windows窗口,可以產生和響應Windows消息;控製條也可以包含非基於hWnd句柄的項,這些項通常有應用程序類或主框架窗口類來管理。比如說,列表框和文本框就是基於hWnd句柄的控件,而狀態條麵板和圖象按鈕則是非基於hWnd句柄的項。
CControlBar類為其子類提供了基本的功能,如在父窗口中的合適位置停泊等。由於控製條通常都是其父框架窗口的一個子窗口,因此,它是視圖或MDI子窗口的"同胞"。控製條對象使用其父框架窗口的客戶區域的信息來定位其自身,因此,其父框架窗口的客戶區域將隨著控製條的停泊位置的改變而改變。
8.1.2 工具條
工具條是經常使用的一種控製條,通常包含一係列的位圖按鈕,點擊按鈕等價與從菜單中選擇相應的命令。工具條通常都停泊在框架窗口的頂部,但實際上,MFC的工具條可以停泊在框架窗口的任何靠邊的位置,也可以浮動於自己的小框架窗口中,甚至可以浮動於應用程序的窗口中,可以改變其大小,可以用鼠標拖動到任何位置。圖8-2和圖8-3分別顯示了工具條停泊在窗口頂部和以浮動窗口顯示時的情形。
圖8-2 工具條停泊在窗口頂部 圖8-3 工具條以浮動窗口顯示
用戶通過CToolBar類管理自己的工具條,但是從MFC4.0開始,CToolBar類被重新定義為使用工具條控件(CToolBarCtrl類)來建立。工具條控件被Windows 95和Windows NT 3.51或其更高的版本所支持。由於利用了操作係統級的支持,這一重新定義使得MFC可以用較少的代碼來管理工具條,同時也增強了工具條的功能。用戶可以CToolBar類的成員函數來操作工具條,或者通過獲得一個CToolBarCtrl的指針而直接對工具條進行操作。
8.1.3 狀態條
狀態條是應用程序中經常使用的另外一種控製條,通常包含多個麵板,用做文本輸出或指示器。狀態條一般都停泊在框架窗口的底部,而且也無須改變其位置。圖8-4是利用AppWizard生成的應用程序中的缺省的狀態條。
圖8-4 狀態條停泊在窗口的底部
與工具條類似,狀態條(CStatusBar)也被重新定義為使用狀態條控件(CStatusBarCtrl)來建立。
8.1.4 對話框條
對話框條是一種基於對話框資源的控製條,其作用類似於一個無模式對話框,在對話框條中可以包含任何Windows控件,甚至可以設置這些控件的製表順序。圖8-5顯示了一個典型的對話框條,這就是Visual C++集成開發環境的WizardBar。
圖8-5 典型的對話框條
8.1.5 集合條
集合條是Visual C++ 6.0中新增的,也是一種控製條。集合條中可以包含多種子窗口類型,通常都是一些控件,如按鈕、文本編輯框等。集合條能將其子窗口在特定的位圖背景上顯示出來。使用集合條可以創建漂亮的程序界麵。圖8-6中顯示了一個典型的集合條,這就是Internet Explorer 4.0的界麵。
圖8-6 典型的集合條
集合條(CReBar)也使用了集合條控件(CReBarCtrl)來建立。
在使用控製條的時候,很少直接使用CControlBar類或直接從CControlBar類派生子類,更多的是使用其子類或從其子類派生自己的類。
以上簡要介紹了控製條類極其子類的一些基本的知識,從下一節開始具體介紹如何使用這些控製條。對於對話框條,我們僅介紹其創建方法,其使用方法可以參照無模式對話框;重點介紹的是工具條、狀態條和集合條。
第二章 工具條和狀態條
在"消息與命令"一章中,介紹了如何初步地使用工具條,僅僅介紹了如何修改工具條資源,如何將工具條按鈕與菜單命令聯係起來,如何改變工具條按鈕的狀態等等,而且使用的是AppWizard為用戶創建的缺省的工具條。在本節中,將詳細解釋應用程序框架是如何建立工具條的,如何創建新的定製的工具條,如何控製工具條的顯示與隱藏等知識,以及如何使用狀態條,如何向狀態條中添加新的麵板,如何控製狀態條的顯示等。
8.2.1 缺省的工具條與狀態條
在利用AppWizard生成應用程序的時候,隻要在步驟4選中了Docking toolbar和Initial status bar選項,AppWizard為用戶生成的應用程序就擁有一個缺省的工具條和狀態條。
1.建立新的項目
為了便於說明,需要建立一個例子程序TestBars。利用AppWizard生成該應用程序框架。在創建過程中,按以下步驟操作:
(1)選擇單文檔界麵,選中文檔/視圖結構支持,同時選擇資源類型為英語。
(2)由於本程序不需要支持任何數據庫技術,選擇None。
(3)由於本程序不需要支持任何形式的複合文檔,選擇None;同時本程序也不需要包含ActiveX控件,故清除缺省對ActiveX controls的選中。
(4)本程序不涉及有關打印的知識,故清除Print and print preview選項;但需要缺省的工具條和狀態條,故選中Docking toolbar和Initial status bar選項;工具條風格選擇Normal;其餘接受缺省選擇即可。
(5)接受缺省選擇。
(6)單擊Finish按鈕完成設置,在新項目信息對話框中列出了本TestBars程序的有關已設定的信息,如圖8-7所示。
圖8-7 新項目信息
建立項目後,用戶可以立即編譯和運行TestBars應用程序,現在的程序版本就已經具有了缺省的工具條和狀態條,如圖8-8所示。
圖8-8 TestBars程序已經擁有缺省的工具條和狀態條
在"消息與命令"一章中講述工具條的基本使用時提到,首先工具條有一個指定其按鈕形式的資源,該資源實際上是一幅位圖。但工具條是如何由資源創建為工具條對象並顯示在窗口的頂部的呢?下麵就來解釋工具條的創建過程。
2.工具條的建立
每個工具條都對應著一個工具條對象,一般說來,工具條都隸屬於其父窗口,這裏就是主框架窗口,因此,工具條對象應該是主框架窗口的成員。狀態條也是如此。在主框架窗口類的定義中,確實可以發現對工具條對象和狀態條對象的定義,如程序清單8-1所示。
程序清單8-1 CMainFrame類中定義了工具條對象和狀態條對象
class CMainFrame : public CFrameWnd
{
......
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
......
};
在CMainFrame類中,定義了一個CStatusBar類對象m_wndStatusBar,一個CToolBar類對象m_wndToolBar。僅僅定義了工具條對象是不夠的,還需要初始化該對象。由於工具條是主框架窗口的內嵌對象,因此MFC在創建主框架窗口的時候就創建了工具條對象,同樣地,在銷毀主框架窗口的時候就銷毀了工具條。狀態條的情況是類似的。
工具條的創建在CMainFrame類的OnCreate()函數中進行。程序清單8-2中列出了OnCreate()函數的代碼。
程序清單8-2 OnCreate()函數
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP|CBRS_GRIPPER| CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar
");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar
");
return -1; // fail to create
}
// TODO: Delete these three lines if you don't want the toolbar to
// be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
創建工具條對象的代碼作為一個if語句的條件,以檢查創建過程是否正確進行。如果不進行正確性檢測的話,可以將創建過程分解為調用兩個函數,如下所示。
m_wndToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE | CBRS_TOP| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ;
m_wndToolBar.LoadToolBar(IDR_MAINFRAME);
首先調用CToolBar的CreateEx()函數創建一個Windows工具條並將其與m_wndToolBar對象關聯在一起。CreateEx()函數的原型如下:
BOOL CreateEx(CWnd* pParentWnd, DWORD dwCtrlStyle = TBSTYLE_FLAT, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP, CRect rcBorders = CRect(0, 0, 0, 0), UINT nID = AFX_IDW_TOOLBAR);
注意CreateEx()函數的參數。pParentWnd是一個指向父窗口的指針,這裏使用了關鍵字this,即將當前對象,也就是主框架窗口作為本工具條的父窗口。
參數dwCtrlStyle指定在建立內嵌CToolBarCtrl對象時所用的風格。缺省的風格是TBSTYLE_FLAT。
參數dwStyle指定工具條的風格。dwCtrlStyle參數與dwStyle參數可取的值比較多,而且相互關聯,因此本書中隻對使用到的風格略作說明,對於其他可選風格的詳細信息,用戶在使用時請查閱Visual C++的聯機手冊。
參數rcBorders指定工具條窗口邊框的寬度。缺省值為CRect(0,0,0,0),即工具條窗口沒有邊框。
參數nID指定工具條的標識符。
AppWizard創建的缺省工具條使用的風格的說明列於表8-1中。
表8-1 缺省工具條使用到的風格
所用風格
說 明
TBSTYLE_FLAT
創建一個平麵工具條
WS_CHILD
創建一個子窗口
WS_VISIBLE
創建的工具條初始即可見
CBRS_TOP
工具條位於父窗口的頂部
CBRS_GRIPPER
工具條具有控製棒
CBRS_TOOLTIPS
工具條按鈕具有提示信息(鼠標經過時顯示在一個小窗口中)
CBRS_FLYBY
工具條按鈕具有提示信息(顯示在狀態條的左部)
CBRS_SIZE_DYNAMIC
工具條的大小動態可調
除了CreateEx()函數之外,CToolBar類還有另外的一個函數Create()也可以創建工具條對象,其原型如下:
BOOL Create( CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_TOP, UINT nID = AFX_IDW_TOOLBAR );
其參數的意義大致同CreateEx()函數。
在創建了工具條對象後,就要將其與相應的工具條資源聯係起來,這項工作由CToolBar類的LoadToobar()函數完成。LoadToobar()函數的原型如下:
BOOL LoadToolBar( UINT nIDResource );
參數nIDResource指定所用資源的標識符。
在顯示工具條之前還有一項工作,就是確定工具條的停泊位置。與此有關的代碼是:
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
確定工具條的停泊位置需要三個步驟:
(1)確定工具條可以停泊的位置,也就是說,確定工具條本身希望停泊在主框架窗口的位置。至於能否停泊在指定的位置,還需要主框架窗口的支持。由CToolBar類的EnableDocking()函數進行設置,這裏使用CBRS_ALIGN_ANY作為參數說明工具條期望停泊的位置可以是窗口的任一邊。
(2)確定主框架窗口中可以停泊工具條的位置。由CWnd類的EnableDocking()函數指定,這裏使用CBRS_ALIGN_ANY作為參數說明主框架窗口允許工具條停泊在其窗口中的任一邊。
(3)停泊工具條在指定位置,由CWnd類的DockControlBar()函數完成。
至此已經完成了工具條的對象創建、資源關聯和位置確定等所有的準備工作,這樣在程序顯示主框架窗口的時候,工具條也就被顯示出來。
3.狀態條的建立
狀態條的建立過程與工具條是類似的。在缺省的情況下,狀態條的建立由以下代碼完成:
m_wndStatusBar.Create(this);
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));