直播中
微軟在www.microsoft.com/visualc已經(jīng)推出Visual C++6.0預(yù)覽版幾個月了。正式版預(yù)計到今年年底發(fā)布。同時,預(yù)覽版顯示出版本6將包含大量的改進(jìn)和提高,包括支持Internet控件,例如扁平工具條等。雖然改進(jìn)的控件包與Internet無關(guān),但它首先出現(xiàn)在Internet Explorer中,因此它就被取做這個名字了。事實上,官方發(fā)布的預(yù)覽版的標(biāo)題是“針對Internet Explorer 4.0的Visual C++ 5.0技術(shù)預(yù)覽”。
在以前關(guān)于MFC工具條類的討論專題中,我曾答應(yīng)提供一個在版本6中工具條的外觀演示。有一個很好的消息,那就是你現(xiàn)在用CToolBar所作的所有工作在新的版本中都是有效的,包括那些在以前的欄目中所描述的一些擴(kuò)展功能。因此,你將很容易修改現(xiàn)存的程序以獲得象Internet Explorer和Visual Studio中那樣“酷”的界面。此外,并沒有什么壞消息。
工具條的新特色
早在版本
4中,CToolBar就已被MFC庫完全實現(xiàn)了。一旦公用控件動態(tài)鏈接庫(命名為comctl32.dll)變得無所不在了,CToolBar就成了如今已包含在操作系統(tǒng)中的工具條控件的代名詞了。然而,CToolBar并沒有揭示公用工具條控件的所有能力。如今,通過CreateEx()函數(shù),它成功了。公用控件動態(tài)鏈接庫現(xiàn)在包含了至少三類風(fēng)格:最初的、在
Internet Explorer 3.0中加入的以及在Internet Explorer 4.0中加入的。雖然這些版本理論上是向下兼容的,但某些專業(yè)人員曾寫出一些不能在后來版本中正常運行的應(yīng)用程序,這可能是這些程序采用了一些沒有公開的功能,而這些功能并沒有被包含在所有的版本中。Visual C++程序員沒有這樣的經(jīng)歷,因為在Visual C++4.0或5.0中comctl32.dll并不是一個可以再分發(fā)的組件,它在安裝Internet Explorer時被更新,因此MFC程序員無法依靠最新版本的某些功能來用于他們的程序。這就是CToolBar僅僅具有最初的DLL的有限功能的原因。CToolBar能夠?qū)崿F(xiàn)最新的特色意味著微軟將在Visual C++6.0中包含最新的DLL并將其作為一個可以再分發(fā)的組件。
絕大多數(shù)新特色將由在調(diào)用CreateEx()和其它CToolBar成員函數(shù)時指定的新的風(fēng)格標(biāo)志來確定。下面是commctrl.h的一部分,它定義了TBSTYLE類標(biāo)識符:
#define TBSTYLE_BUTTON 0x0000 #define TBSTYLE_SEP 0x0001 #define TBSTYLE_CHECK 0x0002 #define TBSTYLE_GROUP 0x0004 #define TBSTYLE_CHECKGROUP (TBSTYLE_GROUP | TBSTYLE_CHECK) #if (_WIN32_IE >= 0x0300) #define TBSTYLE_DROPDOWN 0x0008 #endif #if (_WIN32_IE >= 0x0400) #define TBSTYLE_AUTOSIZE 0x0010 #define TBSTYLE_NOPREFIX 0x0020 #endif #define TBSTYLE_TOOLTIPS 0x0100 #define TBSTYLE_WRAPABLE 0x0200 #define TBSTYLE_ALTDRAG 0x0400 #if (_WIN32_IE >= 0x0300) #define TBSTYLE_FLAT 0x0800 #define TBSTYLE_LIST 0x1000 #define TBSTYLE_CUSTOMERASE 0x2000 #endif #if (_WIN32_IE >= 0x0400) #define TBSTYLE_REGISTERDROP 0x4000 #define TBSTYLE_TRANSPARENT 0x8000 #define TBSTYLE_EX_DRAWDDARROWS 0x00000001 #endif
你會注意到其中的一些采用了條件編譯,依賴于_WIN32_IE的值,它缺省指的是Internet Explorer 4.0(即取值為0x0400)。對于Internet Explorer 3.0(即取值為0x0300)以前的版本,大多數(shù)的TBSTYLE標(biāo)識符指的是按鈕或是一組按鈕。Internet Explorer 3.0引入了扁平鈕、文本標(biāo)簽、下拉列表和自定義繪制。Internet Explorer 4.0增強(qiáng)了下拉列表和自定義繪制功能,并且增加了支持OLE拖動目標(biāo)到一個工具條。
扁平鈕和把手
在過去的
18個月中我常常被問及該如何獲得象Internet Explorer和Visual Studio中的工具條一樣不使用浮雕按鈕而是用扁平鈕并且?guī)в斜阌谝苿雍投ㄎ坏陌咽帜菢涌岬慕缑妗_@些特色并不被MFC所支持,因此最簡單獲取的方法就是購買一個擴(kuò)展庫。而對于Visual C++ 6.0來說卻無須多此一舉,因為它使得CToolBar類實現(xiàn)了對扁平鈕、把手和其它新的視覺效果的支持。在預(yù)覽版中,
AppWizard并不會自動包括這些新特色,但它們卻很容易被加入。表1顯示了AppWizard創(chuàng)建的主框架窗口的OnCreate()函數(shù),表2顯示了需要做哪些修改以獲得具有扁平鈕和把手的工具條。圖1顯示了表1創(chuàng)建出的工具條,而圖2顯示出了表2實現(xiàn)的工具條。表 1: CMainFrame::OnCreate as generated by AppWizard |
---|
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if(CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if(!m_wndToolBar.Create(this) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } if(!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators |
圖
1表2: Adding flat buttons and the gripper |
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if(CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if(!m_wndToolBar.CreateEx(this) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } if(!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create } // TODO: Remove this if you don't want tool tips or a resizeable toolbar m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_GRIPPER | CBRS_BORDER_3D | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); // 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; } |
圖2
為了作出扁平按鈕我必須使用CreateEx()來代替Create()。這個新的函數(shù)在afxext.h中聲明:
因為擴(kuò)展風(fēng)格缺省指的就是TBSTYLE_FLAT,因此我要得到扁平按鈕就只需要簡單地將AppWizard形成的代碼中的Create()改為CreateEx()即可。我將在后面實現(xiàn)其它的擴(kuò)展風(fēng)格。 為了獲得把手,我必須在調(diào)用SetBarStyle()函數(shù)時包含CBRS_GRIPPER標(biāo)志,參看表2。這是CControlBar類的一個新風(fēng)格,而CToolBar類是從它繼承而來的。 請注意到我也加入了CBRS_BORDER_3D標(biāo)志,這是為了修正一個未知的繪制問題,該問題將會在工具條的邊緣繪制一些多余的點。這也許意味著預(yù)覽版確實有這個問題,因為一旦我將3D標(biāo)志加入就立即解決了并且也似乎沒有影響到別的什么。 上面所作的兩個簡單的改變是使得一個已存程序獲得酷界面的最省力的方法。在一個程序具有了扁平鈕和把手的同時,它也不會發(fā)生不應(yīng)有的其它改變。 文本標(biāo)簽 Internet Explorer使得普通的工具條具有了大按鈕和取代了文本提示的文本標(biāo)簽。MFC程序員可以通過SetButtonText()函數(shù)為每個按鈕設(shè)置一個文本串來獲得這種效果。雖然在Visual C++ 5.0中已包含了這個函數(shù),但如果不使用扁平鈕風(fēng)格則不會取得令人滿意的效果。 表3顯示了如何使用現(xiàn)有的文本提示作為按鈕的標(biāo)簽,而且圖3和圖4顯示了將工具條分別定位在頂端和右邊的效果。我仍然使得文本提示有效,但你可以通過在調(diào)用SetBarStyle()時去掉CBRS_TOOLTIPS風(fēng)格而使之無效。
為了產(chǎn)生按鈕標(biāo)簽,一個簡單的for循環(huán)掃過所有的按鈕并且從與之相連的幫助串中提取出提示文本。在設(shè)置完每個按鈕的標(biāo)簽后,就調(diào)用工具條的SetSizes()函數(shù)去重新計算工具條的外觀以便使得標(biāo)簽可見。也許會有更好的方法去實現(xiàn)最后一步,但我還是從微軟的MFCIE范例程序中借用了這個過程,不為別的,只為它確實有效。 從很多方面來說,MFCIE都是值得仔細(xì)學(xué)習(xí)的。從本質(zhì)上來說,它實際上是Internet Explorer的一個微型版本,并且它還闡述了如何使用版本6的一些新特色。你將會驚訝于在你的MFC應(yīng)用程序中添加HTML瀏覽功能是如此之簡單。 在絕大多數(shù)情況下你會希望文本標(biāo)簽顯示在按鈕下面(這在最初的公用控件庫中是唯一的選擇)。Internet Explorer 3.0版加入了TBSTYLE_LIST風(fēng)格,該風(fēng)格導(dǎo)致文本標(biāo)簽顯示在按鈕右邊。對于在標(biāo)簽旁邊顯示一個下拉列表或者按鈕被一個子窗口覆蓋時,該風(fēng)格是很有用的。 下拉列表 在“工具條的變形”一文中,我演示了通過將一個組合框作為一個子窗口來在工具條上添加下拉列表的情形。該方法在版本6中仍然有效,并且當(dāng)你想在工具條上顯示當(dāng)前的可選擇項時它仍然是有用的。然而,有時你希望工具條包含一個可以在鼠標(biāo)點擊時顯示選擇列表或菜單的按鈕。該功能現(xiàn)在可以通過擴(kuò)展風(fēng)格TBSTYLE_DROPDOWN和TBSTYLE_EX_DRAWDDARROWS實現(xiàn)了。 例如,假設(shè)我希望對應(yīng)于“文件”菜單下“新建”的按鈕可以顯示一個我的應(yīng)用程序知道如何去創(chuàng)建的所有文件類型的列表。表4 顯示在前面的例子中如何加入該功能,而圖5顯示該工具條。我抓取了鼠標(biāo)停留在該按鈕上時的屏幕,它顯示出了按鈕和下拉箭頭之間的分隔線。 為了加入一個下拉箭頭,首先我必須在基本的工具條控件上調(diào)用SetExtendedStyle()函數(shù),并且指定TBSTYLE_EX_DRAWDDARROWS風(fēng)格。然后我必須在每一個我想要顯示下拉箭頭的按鈕上指定TBSTYLE_DROPDOWN風(fēng)格。
當(dāng)用戶在New按鈕上點擊時,就象圖5所示一樣,基本的按鈕操作就發(fā)生了。在這個例子中命令消息導(dǎo)致調(diào)用CWinApp::OnFileNew()。然而,當(dāng)用戶點擊下拉箭頭時,工具條就發(fā)出TBN_DROPDOWN通知消息給工具條的父窗口。我可以通過重載OnNotify()函數(shù)或者通過在消息映射中加入一個ON_NOTIFY而獲取這個消息。 表5顯示了后者的實現(xiàn)技術(shù)。通常我顯示一個彈出菜單或者一個列表框去響應(yīng)這個通知消息。在絕大多數(shù)情況下沒有必要提供一個結(jié)果值,因為缺省值(TBDDRET_DEFAULT)顯示了我已獲取了對這個事件的控制。其它可能的結(jié)果值是TBDDRET_NODEFAULT和TBDDRET_TREATPRESSED。前者表示該事件沒有受到控制,當(dāng)出現(xiàn)后者時,工具條就表現(xiàn)得好像該按鈕被點擊一樣。
熱點圖像 運行Internet Explorer 4.0并且將鼠標(biāo)在工具條上劃過。就能注意到在平時每個按鈕是平淡的顏色。而當(dāng)鼠標(biāo)觸及到該按鈕時,他會凸出來并且顯現(xiàn)出鮮艷的顏色。這種視覺效果采用了工具條控件的被稱作“熱點圖像”的功能。 一般的AppWizard代碼使用工具條資源來指定其上按鍵的外觀和與每個按鍵相連接的一個命令I(lǐng)D。工具條資源實際上包含一個復(fù)合的位圖,該位圖在調(diào)用LoadToolBar()函數(shù)時將被轉(zhuǎn)變成一個圖像列表(參見表4)。要激活熱點圖像功能,我必須通過SetHotImageList()函數(shù)提供第二個圖像列表,就象表6所示一樣。
圖6 顯示了熱點圖像被激活的情形。鼠標(biāo)正停留在New按鈕上,它就被顯示成一個空文檔的圖形。其它的按鈕是扁平的和淡顏色的。為了生成這個改進(jìn)的工具條,我將res子目錄下的toolbar.bmp拷貝為toolbar1.bmp,然后將其作為一個位圖資源插入資源中,并取其ID為IDR_MAINFRAME。 接下來我編輯IDR_MAINFRAME 工具條,用很淡的顏色(例如淡灰色)來取代它原來的顏色。最后,我加入了如表6所示的對函數(shù)SetHotImageList()的調(diào)用。 這個例子演示了在一個已存的工具條中加入熱點圖像的捷徑,但他不會改進(jìn)工具條的外觀。如果你想在這一點上取得更好的效果,MFCIE的例子包含了非常好的蝕刻位圖,它演示了當(dāng)你使用非常有藝術(shù)性的圖像時它能達(dá)到何等地步的視覺效果。 其它特色 前面的講解演示了你怎樣簡單地改變現(xiàn)存的MFC程序,以獲得扁平鈕、把手、下拉列表和熱點圖像的功能。Visual C++ 6.0還提供了幾種其它令人感興趣的工具條特色,包括自定義繪制、OLE拖入目標(biāo)和使用rebar(抱歉,不知道該單詞指的是什么)容器等。這些特色將會是將來的欄目的主題。 |