編寫可複用性更好的C++代碼——Band對象和COMToys(一)

來源:互聯網
上載者:User

編譯/趙湘寧

原著:Paul Dilascia 

MSJ  November 1999 & December 1999

關鍵字:Bands 對象,Desk Bands,Info/Comm Bands,Explorer Bar,Tool Bands。

本文假設你熟悉C++,COM,IE。

下載本文原始碼: MyBands.zip (128KB) 
                TestEditSrch.zip (75KB)

第一部分 Band 對象介紹

譯者註:
    很難將 "Band" 一詞與某個中文詞語對應起來,所以本文不打算刻意將"Band"這個詞語翻譯成中文。只要理解Band是Windows外殼擴充(Shell)中的一種應用就行了。如果非要譯出來,我比較傾向於把它譯成"區帶對象"。看一下註冊表中的CATID,如果你的機器中安裝了Desk Band或者Explorer Bar之類的Band應用程式,那麼運行一下CatView.exe程式(這是一個例子程式,可以從VCKBASE線上雜誌第十一期的文章《理解COM編程中的“種類”(Category)概念 》中下載)便會看到微軟對其的稱呼,在“category name”欄中把Desk Bands稱為“案頭區”,把Explorer Bars 稱為“瀏覽器區”。還有一個瞭解Band名稱的地方是下面註冊表入口處的表項目值:

HKCR/Component Categories/{00021492-0000-0000-C000-000000000046}——案頭區
HKCR/Component Categories/{00021493-0000-0000-C000-000000000046}——Internet Explorer 瀏覽器區
HKCR/Component Categories/{00021494-0000-0000-C000-000000000046}——Internet Explorer 瀏覽器通訊帶

不管把 Band 叫做什麼,關鍵是要理解 Band 在外殼應用中的角色。

概要介紹:
    Band對象有三類:Desk,Info和Comm以及Tools Bands。其中Desk Bands 用於工作列;Info和Comm--又稱瀏覽欄(Explorer Bar)--用於IE和資源管理員。Tools Bands用於資源管理員或IE的工具列。本文的例子代碼 MyBands.dll 實現了上述前面兩種類型的Band對象應用,並介紹了如何在自己的程式中使用 Bands 對象。由於Tools Bands是IE5以後才有的新特性。有關它的實現細節將在另外一篇文章中介紹,關於 Bands 對象的基本概念請參考另外一篇MSDN譯文“Windows區對象(Bands)的建立與定製”。
    不久以前,有個朋友問我如何在工作列裡添加編輯框控制。他的思路是想擷取工作列的 HWND,然後將編輯框作為子視窗加到工作列。我當時就斷了他的想法:原因是不能再用過去那種齷齪的方法對現在的系統進行編程。如今的作業系統用COM高度整合,正確的方法應該是利用COM所提供的特性或介面與作業系統進行友善的溝通。

      “請把菜單給我好嗎?”
“噢,當然可以,”
“請拿好菜單。”
“請現在執行這個命令好嗎?”
“沒問題,由IContextMenu來做吧。”
......

完成這些工作只需要外殼擴充中各種各樣層出不窮的一個小小介面之一就能搞掂。
    但是在這些介面中,我還真沒發現一個能將視窗添加到工作列的現成介面呢!。我當時就告訴那可憐的朋友,他的想法很難實現。後來我發現了band對象和IDeskBand(當時這兩個東西剛出來不久,在IE4.0和IE5.0中提供)。立刻覺得它就是我夢寐以求的那種介面。我看到 IDeskBand 介面中只有一個方法。於是決定為什麼不自己寫一個案頭 band(desk band)來實現我朋友的想法呢?心想不就是用這唯一的一個函數嘛,有什麼難的呢?
    幾個月之後產生了幾千行代碼(不包括代碼筆記和一些節外生枝的附加內容),結果如何呢?到不覺得 band 對象實現起來有多難(實際上也並不難),而是我的工程代碼不停地膨脹。寫了一個band對象不過癮;接著又建一個架構。有了架構後還覺得不夠;我又建立了一個自己通用的 COM 編程平台。之所以要這麼做,主要是想盡量使自己的代碼具有更佳的的複用性。眾所周知,可複用性乃編程之極致,程式員應該像追求靚女一樣不停地追求自己代碼的可複用性。在最後完工時,我建立了自己的 BandObj 架構和一些可重用的 COM 代碼,它就是將要在後繼部分要介紹的 COMToys。而本文我們先討論 BandObj 的基本內容。

Mybands DLL 的實現邏輯
    理解任何系統的最好方式是理解它想要解決的問題(某些系統並不在乎要解決任何問題,這樣的系統通常不是好系統)。這就是Mybands DLL的由來。
    我最討厭那種demo例子程式,在一個醜陋的背景上顯示一串笨拙的文本,如"Hello +[應用程式名稱字]",然後還整天提起它。我覺得,如果我在編程過程中遇到了麻煩,那麼我可能同時也獲得了一些有用的東西——或至少是問題細節。所以當我開始寫Desk Bands時,要做的第一件事情就是找一個編寫它的理由,老實說,把一個自己的一個小視窗放到工作列裡的想法具有挑戰性,也很刺激。圖一顯示的是在工作列中有一個Web搜尋方塊。

圖一 工作列中的Web搜尋方塊

在這個編輯框中輸入要尋找的內容,然後按斷行符號鍵,系統就會啟動預設的瀏覽器並且用你在編輯框的操作功能表中指定的Web搜尋引擎進行尋找。你還可以將這個Web搜尋方塊拖到案頭,這時它就變成了一個普通視窗,二所示:

圖二 工作列中的Web搜尋方塊變成了一個普通對話方塊

    實現Web搜尋方塊的程式是 Mybands.dll,它是一個DLL。聰明人肯定會問,這個DLL的名字怎麼有複數形式?因為它實現了所有三種類型的Band應用。這三種Band對象就是本文前面提到過的:Desk Bands,info/comm和Tools Bands。注意:IE5之後,微軟將info/comm類型的Bands統稱為Explorer Bars——瀏覽欄——用於IE或資源管理員--它包括垂直型和水平型,IE以及資源管理員"查看"菜單中"瀏覽欄"的"記錄","收藏夾","搜尋"(三)都屬於info類型或者Explorer Bar類型的Bands應用。Tool Bands是IE5新增加的一種Band類型----工具列Bands。

圖三 其它形式的Bands

安裝Mybands.dll的方法如下:下載原始碼,編譯後將dll拷到Windows的系統目錄(system或system32),然後將它註冊到系統中,方法是:

regsvr32.exe Mybands.dll

註冊成功後,在IE或資源管理員的"查看"=〉"工具列"和"瀏覽欄"菜單中會出現Bands的功能表項目,三所示。顯示Desk Band需要一點小技巧:必須重新啟動資源管理員進程(針對Windows 9x。Windows 2000,Windows XP不需要)。方法是:按按鍵組合"Ctrl+Atl+Del",刪除掉資源管理員進程,重啟之後你就可以在工作列的操作功能表的"工具列"中看到Desk Band功能表項目了四:


圖四 

    使用BandObj編寫band對象是很容易的,就以MyBands為例,它由幾個模組組成,但只有一個模組是編寫band對象的重點,那就是主模組:MyBands.cpp。MyBands由一個叫的App類,它派生於CBandObjDll(BandObj.h),而CBandObjDll又派生於MFC的COleControlModule。它們之間的派生關係為:

    CWinApp
COleControlModule
CBandObjDll
CBandObjDll

與普通的MFC應用一樣,CBandObjDll有一個InitInstance函數:

BOOL CMyBandsDll::InitInstance()
{
AddBandClass(CLSID_MYINFOBAND,
RUNTIME_CLASS(CMyInfoBand),
CATID_InfoBand,
IDR_INFOBAND);
AddBandClass(CLSID_MYCOMMBAND, ...);
AddBandClass(CLSID_MYDESKBAND, ...);
return CBandObjDll::InitInstance();
}

    它類似於DOC/VIEW,只是DOC/VIEW調用的是AddDocTemplate,而不是AddBandClass。對於每一個Band類,必須提供這個類的ID(GUID),MFC運行時類,種類(category)和資源IDs。種類ID就是一個GUID,它告訴Windows你的類是哪一種Band--是info,comm(Explorer Bar)還是Desk Band。從代碼中不難看出,MyBands使用單獨的類來處理每一種Band。CMyInfoBand,CMyCommBand,和 CMyDeskBand,它們都派生於CBandObj,並且都使用DECLARE/IMPLEMENT_DYNCREATE,這樣MFC就能用其通常的運行時機制和COleObjectFactory來動態建立執行個體。它們都具有建構函式來負責初始化DESKBANDINFO結構中有關Band的資訊及CBandObj::m_dbiDefault。例如,Desk Band有一個預設的寬度(100)及變高。

CMyDeskBand::CMyDeskBand() : CBandObj(CLSID_MYDESKBAND)
{
m_dbiDefault.ptActual = CPointL(100,0);
m_dbiDefault.dwModeFlags = DBIMF_VARIABLEHEIGHT;
}

Explorer Bar 有固定高度30個像素,且沒有標題。

CMyCommBand::CMyCommBand() : CBandObj(CLSID_MYCOMMBAND)
{
m_strTitle.Empty();
m_dbiDefault.ptMinSize = CPointL(0,30);
m_dbiDefault.ptMaxSize = CPointL(-1,30);
}

    不管你相不相信,MyBands中真正與Band對象有關的東西就這些。剩下的內容無非就是實現Band行為以及一些常規的MFC應用處理。如:CMyDeskBand中OnCreate處理函數的作用是建立編輯框控制,CMyCommBand中WM_PAINT處理函數的作用是繪製有關資訊:

void CMyCommBand::OnPaint()
{
CPaintDC dc(this);
dc.DrawText("歡迎訪問VC知識庫!");
}

    Band對象不像架構有最上層菜單,但如果你願意的話可以為它添加操作功能表。繁瑣的細節都由CBandObj來處理。這時MyBands必須用與Band類相同的資源ID來建立菜單。命令會神奇般地通過所有正常渠道到達MyBands的ON_COMMAND處理函數。如果不是有GUIDs和種類(category)IDs,你很難瞭解MyBands是一個COM對象。CBandObj隱藏了全部的細節,留下一個自由的空間讓你編寫自己的Band。這就是我的最終目的所在。(待續)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.