日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

打造个性化的Internet Explorer

發布時間:2023/12/9 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 打造个性化的Internet Explorer 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:孫輝

  在Microsoft的軟件哲學中,框架窗口是一個十分重要的角色,這類窗口簡直無處不在。所謂框架窗口,就是四個窗口邊上具有停靠對象能力的窗口對象,從現象上看,框架窗口有十分特別的“邊”,Microsoft構造的許許多多的東西都可以在其邊上“靠泊”,這就是所謂的“Docking”,Internet Explorer是Microsoft的一個典型的運用框架窗口的代表作品。今天的IE,在不知不覺中,你會發現工具欄中會多出一些東西來,這一切的緣由歸根到底都是“邊”在作祟,本文試圖拋磚引玉,將你帶入豐富多彩的IE擴展世界。

Band,IE擴展的利器

  Band,是Windows Shell對象,當Microsoft將Internet Explorer與Windows Shell徹底集成時,Band對象就成為Windows Shell的一個活躍對象,典型的Band對象有IE的搜索欄、收藏欄、歷史欄以及IE的各種工具欄等等。Microsoft公開的Band對象有四類,一類是桌面Band,如位于任務欄上的“快速啟動”、“Windows Media Player”等工具條。而其他三種Band,則均出現在IE之中,包括工具欄Band(如MSN Search工具欄)、Explorer Band(如歷史、媒體等出現在IE左側的窗口)和通訊Band(如位于用戶區下方的“討論”窗口)。

  Band對象停靠在對應于IE的框架窗口的四周,因此,給IE的界面提供了靈活的擴張機制。由于IE的用戶區基本上用于HTML對象的瀏覽,因此現在流行的B/S結構不能充分地運用IE靈活、強大的擴展機制,一旦可以將具有C/S結構特征的自定義子窗口掛接到IE的四周,將可以將IE打造成同時具備B/S、C/S體系優勢的開發框架。現在,Microsoft已經在Office系列產品中體現類似的思路,例如在Microsoft Word以及Excel中,Microsoft引進了Actions Pane對象,使得位于中心的Office文檔可以與停靠在一邊的Actions Pane對象進行通訊、交互操作等等,如圖1所示。


圖1? Word右側的“任務窗格”對象是個典型的Docking對象,這里體現了Microsoft最新的Smart Document技術

開發你的Band對象,讓IE因你而變

  從IE4開始,Band對象就已經存在了,但其復雜的接口使大多數開發人員望而卻步。一個典型的Band對象是一個COM對象,需要實現如下幾個接口:

  • IDeskBand
  • IObjectWithSite
  • IPersistStream
  • IInputObject
  •   每個接口各自包含一些列方法。接口IDeskBand決定了Band對象的基本行為,接口IObjectWithSite提供了Band對象與IE的通訊渠道,接口IInputObject提供了Band對象的輸入消息處理,特別該接口是處理對話框消息的關鍵所在,當需要實現桌面Band對象時,接口IPersistStream提供實現相關的信息存儲(如Band對象的位置)。關于Band對象的一般介紹,可以參考Microsoft Internet SDK技術文檔,由于Microsoft僅提供了很少的文檔與范例,因此Band對象基本上被廣大開發者忽略了。事實上,IE內部的擴展性十分強大(當然,強大也意味著危險),就其擴展編程接口而言,IE的擴展性并不輸給FireFox。

      理論上,只要支持COM技術的開發工具,都可以用來構造Band對象,然而對于更深層的COM技術細節而言,ATL/MFC類庫還是最佳的選擇。毋庸置疑,MFC具備強大的界面構造能力,然而,由于缺乏一個有效的銜接,MFC類庫與深層COM技術開發一直被一層很薄的“紙”隔開了,這一點不能不說是個遺憾。

    CTangramBandImpl,一個Band對象的起點

      首先,我們需要一個構造Band對象的起點,為此我們構造一個基類,以實現上面提到的四個接口,CTangramBandImpl對象的詳細實現細節請參考我們提供的源代碼,以下是其基本構造:

    class CTangramBandImpl :
    ??? public IDeskBand,
    ??? public IObjectWithSite,
    ??? public IPersistStream,
    ??? public IInputObject
    {
    public:
    ??? CTangramBandImpl(void);
    ??? virtual ~CTangramBandImpl(void);

    // IDeskBand
    public:
    ??? STDMETHOD(GetBandInfo)(DWORD dwBandID, DWORD dwViewMode,
    ??? DESKBANDINFO* pdbi);

    // IObjectWithSite
    public:
    ??? STDMETHOD(SetSite)(IUnknown* pUnkSite);
    ??? STDMETHOD(GetSite)(REFIID riid, void **ppvSite);

    // IOleWindow
    public:
    ??? STDMETHOD(GetWindow)(HWND* phwnd);
    ??? STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);

    // IDockingWindow
    public:
    ??? STDMETHOD(CloseDW)(unsigned long dwReserved);
    ??? STDMETHOD(ResizeBorderDW)(const RECT* prcBorder,
    ??? IUnknown* punkToolbarSite, BOOL fReserved);
    ??? STDMETHOD(ShowDW)(BOOL fShow);

    // IPersist
    public:
    ??? STDMETHOD(GetClassID)(CLSID *pClassID);

    // IPersistStream
    public:
    ??? STDMETHOD(IsDirty)(void);
    ??? STDMETHOD(Load)(IStream *pStm);
    ??? STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty);
    ??? STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize);

    // IInputObject
    public:
    ??? STDMETHOD(HasFocusIO)(void);
    ??? STDMETHOD(TranslateAcceleratorIO)(LPMSG lpMsg);
    ??? STDMETHOD(UIActivateIO)(BOOL fActivate, LPMSG lpMsg);

    public:
    ??? BOOL m_bFocus;
    ??? BOOL m_bCommBand;
    ??? void FocusChange(BOOL);

    protected:
    ??? virtual BOOL RegisterAndCreateWindow(){return false;};
    ??? virtual void SetBandTitle(DESKBANDINFO* pdbi){};
    ??? CFrameWnd* m_pFrameWnd;
    ??? DWORD m_dwBandID;
    ??? DWORD m_dwViewMode;
    ??? BOOL m_bShow;
    ??? BOOL m_bEnterHelpMode;
    ??? HWND m_hWndParent;
    ??? IInputObjectSite* m_pSite;
    };

      對于IE,除了工具欄外,我們將停靠于IE框架左側的Band稱為Explorer Band,而將停靠于框架底邊的Band稱為通訊Band(Communication Band),從COM的角度看,這兩類對象分別屬于不同的對象范疇(Category),所有這兩類對象均被羅列在IE的View菜單的“Explorer Bar”子菜單中。我們實現的Explorer Band對象的類結構如下:

    class ATL_NO_VTABLE CBand : public CTangramBandImpl,
    ??? public CComObjectRootEx<CComSingleThreadModel>,
    ??? public CComCoClass<CBand, &CLSID_Band>,
    ??? public IDispatchImpl<IBand, &IID_IBand, &LIBID_TANGRAMBANDLib>
    {
    public:
    ??? CBand();

    ??? DECLARE_REGISTRY_RESOURCEID(IDR_BAND)

    ??? DECLARE_PROTECT_FINAL_CONSTRUCT()

    ??? BEGIN_CATEGORY_MAP(CBand)
    ??????? IMPLEMENTED_CATEGORY(CATID_InfoBand)
    ??????? IMPLEMENTED_CATEGORY(CATID_DeskBand)
    ??? END_CATEGORY_MAP()

    ??? BEGIN_COM_MAP(CBand)
    ??????? COM_INTERFACE_ENTRY(IBand)
    ??????? COM_INTERFACE_ENTRY(IOleWindow)
    ??????? COM_INTERFACE_ENTRY(IObjectWithSite)
    ??????? COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
    ??????? COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
    ??????? COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
    ??????? COM_INTERFACE_ENTRY(IPersist)
    ??????? COM_INTERFACE_ENTRY(IPersistStream)
    ??????? COM_INTERFACE_ENTRY(IDispatch)
    ??? END_COM_MAP()

    protected:
    ??? virtual BOOL RegisterAndCreateWindow();
    ??? virtual void SetBandTitle(DESKBANDINFO* pdbi);
    };

    代碼片斷:

    BEGIN_CATEGORY_MAP(CBand)
    ??? IMPLEMENTED_CATEGORY(CATID_InfoBand)
    ??? IMPLEMENTED_CATEGORY(CATID_DeskBand)
    END_CATEGORY_MAP()

    表明CBand對象隸屬兩個對象范疇,分別是桌面Band以及Explorer Band,因此,此類對象可以停靠于Windows Shell的桌面,同時也可以停靠于IE框架窗口的左側,當你在桌面的工具欄中點擊鼠標右鍵,選擇Toolbars時,你會看到創建桌面TangramBand的菜單項:

      Communication Band對象CHBand的類結構與CBand的基本一致,最大的區別是:

    BEGIN_CATEGORY_MAP(CHBand)
    ??? IMPLEMENTED_CATEGORY(CATID_CommBand)
    END_CATEGORY_MAP()

      由于Band對象實現了接口IObjectWithSite,因此,Band對象可以通過該接口得到Band對象所從屬的IE實例。為此,我們注意到CTangramBandImpl中已經實現了IObjectWithSite的方法SetSite,我們可以在其中添加如下代碼:

    IOleCommandTarget* pCmdTarget = NULL;
    IWebBrowser2* m_pBrowser;
    HRESULT hr = pUnkSite->QueryInterface(IID_IOleCommandTarget,
    ??? (LPVOID*)&pCmdTarget);
    if(SUCCEEDED(hr))
    {
    ??? IServiceProvider* pSP;
    ??? hr = pCmdTarget->QueryInterface(IID_IServiceProvider,
    ??????? (LPVOID*)&pSP);

    ??? pCmdTarget->Release();
    ??? if (SUCCEEDED(hr))
    ??? {
    ??????? hr = pSP->QueryService(SID_SWebBrowserApp,
    ??????????? IID_IWebBrowser2, (LPVOID*)&m_pBrowser);
    ??????? if(hr==S_OK)
    ??????????? TRACE(_T("Get m_pBrowser: %x\n"),m_pBrowser);
    ??????? pSP->Release();
    ??? }
    }

      這樣就可以以得到這個Band對象對應的IE實例(即上述代碼中的m_pBrowser)。通過m_pBrowser,Band對象可以訪問當前瀏覽器瀏覽的頁面、調用網頁中的腳本代碼以及實現其他的Band對象與網頁之間的交互功能。

    實現基于MFC的Band對象

      為了將MFC類庫的強大功能自然納入Band對象,我們需要一個基于MFC的Frame窗口。我們注意到,CTangramBandImpl已經包含了一個成員變量:

    CFrameWnd* m_pFrameWnd;

      這個變量建立了一座銜接Band對象與MFC類庫的橋梁,在每個Band對象的RegisterAndCreateWindow函數中,均包含如下代碼:

    BOOL CHBand::RegisterAndCreateWindow()
    {
    ??? RECT rect;
    ??? ::GetClientRect(m_hWndParent, &rect);
    ??? AFX_MANAGE_STATE(AfxGetStaticModuleState());
    ??? theApp.m_pBand = this;
    ??? m_pFrameWnd = new CTangramBandFrame();
    ??? CCreateContext m_Context;
    ??? m_Context.m_pNewViewClass = RUNTIME_CLASS(TestFormView);
    ??? CWnd* pWnd = CWnd::FromHandle(m_hWndParent);
    ??? m_pFrameWnd->Create(NULL,_T("TangramBand"),
    ??????? WS_CHILD, CRect(rect.left, rect.top,
    ??????? rect.right - rect.left, rect.bottom - rect.top),
    ??????? pWnd, NULL, NULL, &m_Context);
    ??? theApp.m_pBand = NULL;
    ??? return true;
    }

      我們注意到,這段代碼創建了一個MFC CFrameWnd對象m_pFrameWnd。由此,一切關于MFC的代碼技巧自然而然地盤活了,我們看到一個典型的MFC框架被融入IE之中:

    BOOL CTangramBandFrame::OnCreateClient(LPCREATESTRUCT lpcs,
    ??? CCreateContext* pContext)
    {
    ??? if(!m_pBand->m_bCommBand)
    ??? {
    ??????? m_SplitterWnd.CreateStatic(this, 2, 1);
    ??????? m_SplitterWnd.CreateView(0, 0, RUNTIME_CLASS(TestFormView),
    ??????????? CSize(0, 100), NULL);
    ??????? m_SplitterWnd.CreateView(1, 0, RUNTIME_CLASS(TestFormView2),
    ??????????? CSize(0, 100), NULL);
    ??? }
    ??? else
    ??? {
    ??????? m_SplitterWnd.CreateStatic(this, 1, 2);
    ??????? m_SplitterWnd.CreateView(0, 0, RUNTIME_CLASS(TestFormView),
    ??????????? CSize(150, 100), NULL);
    ??????? m_SplitterWnd.CreateView(0, 1, RUNTIME_CLASS(TestFormView2),
    ??????????? CSize(0, 0), NULL);
    ??? }
    ??? return true;
    }

      由于Band對象存在于一個動態鏈接庫中,故創建MFC對象時要注意在合適的位置調用代碼:

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    以使得MFC能夠正確處理消息。

    輸入消息處理

      接口IInputObject用于管理Band對象的輸入以及對話框、加速鍵消息,關于MFC消息,由于Band對象本質上是一種IE插件,故消息隊列由IE控制,因此MFC窗口的消息處理是個關鍵問題。當Band對象捕獲輸入焦點時,我們必須保證MFC窗口消息被正確處理,下述代碼:

    STDMETHODIMP CTangramBandImpl::TranslateAcceleratorIO(LPMSG lpMsg)
    {
    ??? AFX_MANAGE_STATE(AfxGetStaticModuleState());
    ??? if(m_bFocus&&theApp.m_pWnd)
    ??? {
    ??????? theApp.m_pWnd->PreTranslateMessage(lpMsg);
    ??????? TRACE(_T("TranslateAcceleratorIO\n"));
    ??????? return S_OK;
    ??? }
    ??? return S_FALSE;
    }

    用來處理當前具有輸入焦點的MFC窗口theApp.m_pWnd的相關消息,因此具有輸入焦點的MFC窗口必須重載函數PreTranslateMessage,特別是CFormView的派生對象,在范例代碼中我們給出了重載該函數的例子。

    調試與中文處理

      Band對象的調試例程是IE,因此需要修改工程配置,使得調試過程定向到IE。為使得Band對象能夠正確接受中文輸入,代碼工程必須是基于UNICODE的。

      您可以到雜志的站點(http://mag.csdn.net/msdn)上下載本刊附帶的源代碼,其中的MsdnJxControl解決方案中有本文所提到的項目的完整實現。該解決方案已經為您做好了所有的配置工作,但還是希望您能夠通過屬性面板仔細觀察該解決方案的具體設置。

    小結

      正如Microsoft系列的其他產品一樣,Internet Explorer中存在著豐富的擴展空間。對于Microsoft而言,框架窗口的四周存在著可停靠對象的口岸,因此你可以在這些岸邊開拓你的軟件空間以展示你的軟件魅力,如果你讀到了本文,那么你就開始吧,充滿誘惑的海岸,等待你去開拓。



    本文引用通告地址: http://blog.csdn.net/dotnet_editor/services/trackbacks/455812.aspx

    總結

    以上是生活随笔為你收集整理的打造个性化的Internet Explorer的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。