青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-250  評論-20  文章-55  trackbacks-0
一、 簡介
Windows的區(Bands)對象有三種:既瀏覽欄(Explorer Bar)區對象,工具欄(Tools Bands)區對象,和桌面區對象(Desk Bands)。

瀏覽欄區對象
瀏覽欄區對象簡稱瀏覽欄,它是從IE4.0引入的,它是鄰近瀏覽器窗格的一個顯示區域。實際上它是IE窗口中的一個子窗口,可以用它來顯示信息及與用戶交互。瀏覽欄即可以是以垂直方式定位在瀏覽器窗格的左邊。也可以水平方式定位在瀏覽器窗格下面。(如圖一)

圖一
在瀏覽欄中可以創建很多子菜單或選項,用戶能以不同方式選擇這些子菜單或選項提供的功能,打開IE或者資源管理器,從“查看”菜單中選擇“瀏覽欄”,可以看到Windows提供了幾種標準的瀏覽欄菜單,如“搜索(Search)”,“收藏夾(Favorites)”, 和“歷史記錄(History)”,以及“文件夾(All Folders)”。(如圖二)

圖二
為了創建定制的瀏覽欄,必須編程實現,然后注冊它們。Windows在外殼(Shell)4.71中引入了區對象。它提供與普通窗口一樣的功能。但因為它是以IE或外殼為容器的COM對象,所以實現起來就與普通窗口有所不同。圖一中顯示的就是一個簡單的瀏覽欄例子。圖中有一個垂直的瀏覽欄和一個水平的瀏覽欄。

工具欄區對象
工具欄區對象簡稱工具欄,它是在IE5.0中引入用以支持單選工具欄(radio toolbar)特性的。IE工具欄實際上是一個Rebar控件,它包含了幾個工具欄(toolbar)控件。通過創建工具欄,你可以將某個區對象功能添加到Rebar控件中。不論是在IE中還是在資源管理器中,區對象都是一樣的,所以工具欄也是一個通用窗口。(如圖三)

圖三

用戶可以從“查看”菜單中的“工具欄”子菜單中選擇顯示單選工具欄,也可以在工具欄區域單擊鼠標右鍵從它的上下文菜單中選擇顯示單選工具欄。

桌面區對象
區對象也可以用在桌面,也就是創建桌面區對象。雖然它們的基本實現與瀏覽欄類似,但桌面區與IE沒有關系,它不用IE作為容器。它主要用來創建桌面浮動窗口。通過在任務欄上單擊右鍵,然后在彈出的菜單中選擇“工具欄”的子菜單選項。(如圖四)

圖四

桌面區的初始浮動位置在任務欄:(如圖五

圖五

用戶可以將桌面區拖到桌面上,這時它就成了一個普通窗口:(如圖六)

圖六
二、實現區對象
盡管可以像使用普通窗口一樣使用區對象,但它們畢竟是COM對象,存在于某個容器之中。如瀏覽欄和工具欄位于IE之中,桌面區位于外殼之中。雖然它們的功能不同,但其基本實現非常相似。一個主要的差別是它們的注冊方式不同,而注冊方式的不同又決定了對象的類型及其容器。這一部分我們先討論所有區對象實現的共性。其它的實現細節可參考垂直瀏覽欄例子程序
區對象除了要實現 IUnknown 和 IClassFactory 兩個接口之外,所有的區對象還必須實現以下這幾個接口:
  • ?IDeskBand?
  • ?IObjectWithSite?
  • ?IPersistStream
另外,在注冊時除了注冊它們的CLSID之外,瀏覽欄和桌面區對象還必須進行組件類別(category)的注冊。它決定了對象的類型及其容器。工具欄不需要進行種類注冊。歸納起來,需要進行CATID注冊的三種區對象是:
區對象類型組件類型
垂直瀏覽欄CATID_InfoBand
水平瀏覽欄CATID_CommBand
桌面區CATID_DeskBand

對于如何注冊區對象的進一步討論請參見注冊部分
如果某個區對象接受用戶輸入,它還必須實現IInputObject接口。如果要往上下文菜單中添加菜單項目,還必須實現IContextMenu接口。注意:工具欄區對象不支持上下文菜單。
??? 因為區對象實現的是子窗口,所以它們還必須有窗口過程來處理Windows的消息。
??? 區對象可以通過其IOleCommandTarget接口發送命令到它的容器。為了得到這個接口的指針,必須調用容器的IInputObjectSite::QueryInterface方法請求IID_IoleCommandTarget。然后用IOleCommandTarget::Exec把命令發送到容器。命令組是CGID_DeskBand。當某個區對象的IDeskBand::GetBandInfo方法被調用時,容器用dwBandID參數將一個標示符賦給這個對象。這個標示符被用于IOleCommandTarget::Exec方法調用時所用命令組中的三個命令。目前命令組共支持四個IOleCommandTarget::Exec命令IDs。這四個命令的解釋如下:
DBID_BANDINFOCHANGED——Band的信息已改變。參數pvaIn的值應該是最近一次調用所用的band標示符。容器將調用這個標示符所指的band對象的IDeskBand::GetBandInfo方法請求更新的信息。
DBID_MAXIMIZEBAND——容器將最大化band。參數pvaIn的值應該是最近一次調用所用的band標示符。
DBID_SHOWONLY——關閉或打開容器中其它band。參數pvaIn的值為VT_UNKNOWN類型,可以取下列值之一:
描述
pUnk這個對象IUnknown接口的指針。所有其它的桌面band將被隱藏。
0隱藏所有桌面band。
1顯示所有桌面band。
DBID_PUSHCHEVRON——目前沒有實現。

注冊
區對象必須作為進程內服務器(in-process)注冊。其線程模型必須為“Apartment”。也就是說區對象必須以DLL的形式來實現。用來描述服務器注冊條目的缺省值是一個菜單文本串。就拿瀏覽欄來說。這個菜單出現在資源管理器或IE “查看(View)”菜單的“瀏覽欄(Explorer Bar)”子菜單中。而工具欄的菜單則出現在資源管理器或IE “查看(View)”菜單的“工具欄(Toolbars)”子菜單中。桌面區出現在任務欄上下文菜單的“工具欄(Toolbars)”子菜單中。作為菜單資源,提供鍵盤快捷的方法與一般菜單快捷鍵相同。也就是將“&”字符放在某個單詞字母前表示這個字母顯示下劃線來指示快捷鍵。
通常區對象的注冊條目如下:
HKEY_CLASSES_ROOT
...
    CLSID
	...
        {Band 對象的 CLSID GUID} = "菜單文本串"
            InProcServer32 = "DLL 路徑名"
                ThreadingModel = "Apartment"
工具欄區對象必須還要注冊對象的CLSID。為此必須在HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Toolbar下創建一個REG_SZ值,用工具欄區對象的CLSID GUID串命名。如:
HKEY_LOCAL_MACHINE
    Software
        Microsoft
            Internet Explorer
                Toolbar
                    { Band 對象的 CLSID GUID }

除此之外,還有幾個可選的注冊值可以加到注冊表中,本文的例子中未使用這些值。
  • HKEY_CLASSES_ROOT\CLSID\{Band 對象的 CLSID GUID}\Instance\CLSID, 它應該被設置為 "{4D5C8C2A-D075-11D0-B416-00C04FB90376}".?
  • HKEY_CLASSES_ROOT\CLSID\{Band對象的CLSID GUID}\Instance\InitPropertyBag\Url 它應該被設置為要在瀏覽欄顯示的包含HTML內容的文件位置。
  • \HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Explorer Bars\{Band 對象的 CLSID GUID}\BarSize 它應該被設置為欄目的高和寬,它需要八個字節才能作為串放入注冊表,字節之間用逗號分開。開始的四個字節一像素為單位指定大小,格式要用十六進制,從最左邊字節開始。最后四個字節是保留字節,應該將它置為零。例如,垂直瀏覽欄的缺省寬度為291(0x123)像素,則BarSize 的值應該是"23,01,00,00,00,00,00,00"?
如果要用瀏覽欄顯示HTML,則前兩個注冊項是必須的。最后一個注冊項則根據垂直的或者水平的瀏覽欄定義相應的缺省寬度和高度。
能顯示HTML的瀏覽欄(缺省寬度為291各像素單位)注冊表條目的形式如下:
HKEY_CLASSES_ROOT
...
    CLSID
	...
        {Band 對象的 CLSID GUID} = "菜單文本串"
            InProcServer32 = "DLL 路徑名"
                ThreadingModel = "Apartment"
            Instance
                CLSID = "{4D5C8C2A-D075-11D0-B416-00C04FB90376}"
                InitPropertyBag
                    Url = "HTML文件"
...
HKEY_CURRENT_USER
...
    Software
    ...
        Microsoft
        ...
            Internet Explorer
            ...
                Explorer Bars
                    { Band 對象的 CLSID GUID }
                        BarSize = "23,01,00,00,00,00,00,00"

你可以通過編程的方式來處理區對象類別 CATID 的注冊。創建一個組件類別管理器對象(CLSID_StdComponentCategoriesMgr)并請求一個指向ICatRegister接口的指針。將區對象的CLSID和CATID傳遞到ICatRegister::RegisterClassImplCategories。
三、定制瀏覽欄的一個簡單例子
這個例子展示了前面所介紹過的垂直瀏覽欄的整個實現過程。它借助了平臺SDK(Platform SDK——在msdn中可以找到)中關于band對象示范代碼。其中還包括了水平瀏覽欄和桌面band的實現代碼。詳細實現細節請參見:CommBand.cpp和DeskBand.cpp。
創建定制瀏覽欄的基本過程是這樣的:
  1. 實現DLL需要的函數。
  2. 實現必須的COM接口。
  3. 實現任何想要的可選接口。
  4. 注冊對象的CLSID。
  5. 進行恰當的組件種類注冊。
  6. 創建IE子窗口,調整窗口大小適合瀏覽欄的顯示區域。
  7. 使用子窗口顯示信息并與用戶交互。
實際上,只要通過恰當的組件種類注冊,瀏覽欄例子代碼便既可用于瀏覽欄的實現,也能用于桌面band實現。更加復雜的實現將需要定制每種對象類型的顯示區域和容器。但大多數的定制工作都能通過范例代碼以及Windows子窗口的編程技術來完成。例如,你可以添加用戶交互控制或者進行色彩豐富的圖形顯示處理。

DLL函數
所有三種區對象被打包在一個DLL中,它輸出以下的函數:
  • DllMain
  • DllCanUnloadNow?
  • DllGetClassObject?
  • DllRegisterServer?
這些函數可以在BandObjs.cpp中找到,它們服務于所有三種區對象。前三個函數乃標準的實現,我們不再本文中討論。類工廠也是標準實現,代碼可以在ClsFact.cpp中找到

注冊定制的瀏覽欄

有了COM對象后,必須對瀏覽欄的CLSID進行注冊。另外如果要與IE或資源管理器
協調運行,還必須進行的恰當的組件種類(CATID_InfoBand)注冊。這個工作由DllRegisterServer處理。瀏覽欄例子代碼有關的處理部分如下:
...
//注冊瀏覽欄對象
if(!RegisterServer(CLSID_SampleExplorerBar, TEXT("垂直瀏覽欄例子")))
return SELFREG_E_CLASS;

//注冊瀏覽欄的對象組件種類
if(!RegisterComCat(CLSID_SampleExplorerBar, CATID_InfoBand))
return SELFREG_E_CLASS;
...
區對象的注冊使用通常的COM過程,它由私有函數RegisterServer處理。
除了CLSID之外,這個區對象服務器還必須注冊一個以上的組件種類。這實際上是垂直瀏覽欄和水平瀏覽欄實現之間的主要差別。這個過程的處理是通過創建一個組件種類管理器對象(CLSID_StdComponentCategoriesMgr),并用ICatRegister::RegisterClassImplCategories方法來注冊區對象服務器。在這個例子中,組件種類注冊的處理是通過將瀏覽欄的CLSID和CATID傳遞到私有函數RegisterComCat完成的:
BOOL RegisterComCat(CLSID clsid, CATID CatID)
{
ICatRegister   *pcr;
HRESULT        hr = S_OK ;
    
CoInitialize(NULL);

hr = CoCreateInstance(  CLSID_StdComponentCategoriesMgr, 
                        NULL, 
                        CLSCTX_INPROC_SERVER, 
                        IID_ICatRegister, 
                        (LPVOID*)&pcr);
if(SUCCEEDED(hr))
   {
   hr = pcr->RegisterClassImplCategories(clsid, 1, &CatID);
   pcr->Release();
   }
        
CoUninitialize();

return SUCCEEDED(hr);
}

必須實現的接口
垂直瀏覽欄例子實現了四個必須的接口:IUnknown, IObjectWithSite, IPersistStream, 和IDeskBand,它們都在CExplorerBar類中實現。
IUnknown
構造函數,析構函數和IUnknown實現比較簡單,本文在此不討論。細節請參見源代碼。
IObjectWithSite接口
當用戶選擇某個瀏覽欄時,容器調用相應band對象的IObjectWithSite::SetSite方法。參數將被設置成這個現場(Site)的IUnknown指針。
通常,SetSite實現應該完成下列步驟:
  1. 釋放當前所把持的任何現場指針。
  2. 如果傳遞到SetSite的指針被置為NULL,此則區對象被刪除。SetSite可以返回S_OK。
  3. 如果傳遞到SetSite的指針被置為非NULL,則建立新的現場。SetSite應該做以下的事情:
  1. 調用現場QueryInterface方法請求IOleWindow接口。
  2. 調用IOleWindow::GetWindow獲取父窗口句柄,并存儲它,以便以后使用。如果不再使用的話,就釋放IOleWindow接口。
  3. 創建此band對象的窗口為一個子窗口,其父窗口就是上一步獲得的那個窗口。注意在此不能將它創建成可見窗口。
  4. 如果此band對象實現IInputObject,調用現場QueryInterface方法請求IInputObjectSite接口,存儲這個接口的指針以備后用。
  5. 如果所有步驟都成功,則返回S_OK,否則返回OLE定義的錯誤代碼以指示錯誤類型。
以下是瀏覽欄實現SetSite的方法。m_pSite是私有成員變量,用它來保存IInputObjectSite指針,而m_hwndParent保存父窗口句柄。
STDMETHODIMP CExplorerBar::SetSite(IUnknown* punkSite)
{
//如果某個現場被把持,則釋放它
if(m_pSite)
   {
   m_pSite->Release();
   m_pSite = NULL;
   }

//如果punkSite 不為NULL, 建立一個新的現場
if(punkSite)
   {
   //獲取父窗口
   IOleWindow  *pOleWindow;

   m_hwndParent = NULL;
   
   if(SUCCEEDED(punkSite->QueryInterface(IID_IOleWindow, (LPVOID*)&pOleWindow)))
      {
      pOleWindow->GetWindow(&m_hwndParent);
      pOleWindow->Release();
      }

   if(!m_hwndParent)
      return E_FAIL;

   if(!RegisterAndCreateWindow())
      return E_FAIL;

   //獲取柄保存IInputObjectSite指針
   if(SUCCEEDED(punkSite->QueryInterface(IID_IInputObjectSite, (LPVOID*)&m_pSite)))
      {
      return S_OK;
      }  
   return E_FAIL;
   }
return S_OK;
}
這個例子的GetSite只簡單地用SetSite保存的現場指針實現了對現場QueryInterface方法的調用。
STDMETHODIMP CExplorerBar::GetSite(REFIID riid, LPVOID *ppvReturn)
{
*ppvReturn = NULL;

if(m_pSite)
   return m_pSite->QueryInterface(riid, ppvReturn);

return E_FAIL;
}
窗口創建由私有方法RegisterAndCreateWindow負責。如果這個窗口不存在,此方法將瀏覽欄窗口創建成一個大小適當的子窗口,它的父窗口就是由SetSite獲得的那個窗口。子窗口的句柄存儲在m_hwnd變量中。
BOOL CExplorerBar::RegisterAndCreateWindow(void)
{
//如果這個窗口不存在,則創建它
if(!m_hWnd)
   {
   //子窗口不能沒有父窗口
   if(!m_hwndParent)
      {
      return FALSE;
      }

   //如果窗口類沒有注冊,則必須注冊
   WNDCLASS wc;
   if(!GetClassInfo(g_hInst, EB_CLASS_NAME, &wc))
      {
      ZeroMemory(&wc, sizeof(wc));
      wc.style          = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
      wc.lpfnWndProc    = (WNDPROC)WndProc;
      wc.cbClsExtra     = 0;
      wc.cbWndExtra     = 0;
      wc.hInstance      = g_hInst;
      wc.hIcon          = NULL;
      wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
      wc.hbrBackground  = (HBRUSH)CreateSolidBrush(RGB(0, 0, 192));
      wc.lpszMenuName   = NULL;
      wc.lpszClassName  = EB_CLASS_NAME;
      
      if(!RegisterClass(&wc))
         {
         //如果注冊失敗,下面的CreateWindow函數將失敗
         }
      }

   RECT  rc;

   GetClientRect(m_hwndParent, &rc);

   //創建這個窗口。WndProc 將建立m_hWnd變量
   CreateWindowEx(   0,
                     EB_CLASS_NAME,
                     NULL,
                     WS_CHILD | WS_CLIPSIBLINGS | WS_BORDER,
                     rc.left,
                     rc.top,
                     rc.right - rc.left,
                     rc.bottom - rc.top,
                     m_hwndParent,
                     NULL,
                     g_hInst,
                     (LPVOID)this);
      
   }
return (NULL != m_hWnd);
}
IPersistStream接口
IE將調用瀏覽欄的IPersistStream接口,以便允許這個瀏覽欄加載或存儲持久性數據。如果沒有持久性數據,這個方法仍然必須返回一個成功代碼。IPersistStream接口從IPersist繼承而來,所以要實現五個方法:
GetClassID, IsDirty, Load, Save, GetSizeMax。
本文的這個瀏覽欄例子不使用持久性數據,并且只有IPersistStream的最小實現。GetClassID返回對象的CLSID(CLSID_SampleExplorerBar),其余的方法返回S_OK, 或者S_FALSE, 或者 E_NOTIMPL。有關細節請參見IPersistStream的實現。

IDeskBand接口
IDeskBand接口是區對象專用接口。它只有一個方法。IDeskBand接口從IDockingWindow繼承而來,而IDockingWindow又從IOleWindow繼承而來。
IOleWindow有兩個方法:GetWindow 和 ContextSensitiveHelp。瀏覽欄例子的GetWindow實現返回瀏覽欄的子窗口句柄m_hwnd。因為不實現上下文敏感幫助,所以ContextSensitiveHelp返回E_NOTIMPL。
IDockingWindow接口有三個方法:ShowDW, CloseDW, 和 ResizeBorder。ResizeBorder不在任何區對象中使用,應該返回E_NOTIMPL。ShowDW方法根據其不同的參數值控制瀏覽欄窗口的顯示或隱藏:
STDMETHODIMP CExplorerBar::ShowDW(BOOL fShow)
{
if(m_hWnd)
   {
   if(fShow)
      {
      //顯示窗口
      ShowWindow(m_hWnd, SW_SHOW);
      }
   else
      {
      //隱藏窗口
      ShowWindow(m_hWnd, SW_HIDE);
      }
   }

return S_OK;
}

CloseDW方法摧毀瀏覽欄窗口:
STDMETHODIMP CExplorerBar::CloseDW(DWORD dwReserved)
{
ShowDW(FALSE);

if(IsWindow(m_hWnd))
   DestroyWindow(m_hWnd);

m_hWnd = NULL;
   
return S_OK;
}
其余的方法,如GetBandInfo是IDeskBand專用的。IE使用它來指定瀏覽欄的標示符以及視圖模式。IE還可能填寫DESKBANDINFO結構的dwMask成員從瀏覽欄請求更多的信息,這個結構用第三個參數傳遞。GetBandInfo應該存儲這個標示符和視圖模式并用所請求的數據填寫DESKBANDINFO結構。下面是本文瀏覽欄例子所實現GetBandInfo:
STDMETHODIMP CExplorerBar::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
{
if(pdbi)
   {
   m_dwBandID = dwBandID;
   m_dwViewMode = dwViewMode;

   if(pdbi->dwMask & DBIM_MINSIZE)
      {
      pdbi->ptMinSize.x = MIN_SIZE_X;
      pdbi->ptMinSize.y = MIN_SIZE_Y;
      }
   if(pdbi->dwMask & DBIM_MAXSIZE)
      {
      pdbi->ptMaxSize.x = -1;
      pdbi->ptMaxSize.y = -1;
      }
   if(pdbi->dwMask & DBIM_INTEGRAL)
      {
      pdbi->ptIntegral.x = 1;
      pdbi->ptIntegral.y = 1;
      }
   if(pdbi->dwMask & DBIM_ACTUAL)
      {
      pdbi->ptActual.x = 0;
      pdbi->ptActual.y = 0;
      }
   if(pdbi->dwMask & DBIM_TITLE)
      {
      lstrcpyW(pdbi->wszTitle, L"瀏覽欄例子");
      }
   if(pdbi->dwMask & DBIM_MODEFLAGS)
      {
      pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT;
      }
   if(pdbi->dwMask & DBIM_BKCOLOR)
      {
      //通過移開這個標志來使用默認的背景顏色
      pdbi->dwMask &= ~DBIM_BKCOLOR;
      }
   return S_OK;
   }
return E_INVALIDARG;
}
可選擇的接口實現
由兩個接口的實現是可選擇的,一個是IInputObject,另一個是 IContextMenu。本文的瀏覽欄例子實現了IInputObject。對于IContextMenu的實現細節請參考有關文檔。

IInputObject接口
如果某個band對象要接受用戶輸入。那就必須實現IInputObject接口。IE實現IInputObjectSite并用IInputObject維護用戶的輸入焦點。瀏覽欄需要實現三個方法:UIActivateIO, HasFocusIO, 和 TranslateAcceleratorIO。
IE調用UIActivateIO通知瀏覽欄它以被激活或者被置灰。當被激活時,瀏覽欄例子調用SetFocus來設置窗口輸入焦點。
當要確定哪個窗口有輸入焦點時,IE調用HasFocusIO。如果瀏覽欄的窗口或它的子窗口之一有輸入焦點,HasFocusIO返回S_OK。否則,它返回S_FALSE。
TranslateAcceleratorIO允許對象處理鍵盤加速鍵。本文瀏覽欄例子沒有實現這個方法,所以它返回S_FALSE。
瀏覽欄例子實現IInputObjectSite的細節如下:
STDMETHODIMP CExplorerBar::UIActivateIO(BOOL fActivate, LPMSG pMsg)
{
if(fActivate)
   SetFocus(m_hWnd);

return S_OK;
}

STDMETHODIMP CExplorerBar::HasFocusIO(void)
{
if(m_bFocus)
   return S_OK;

return S_FALSE;
}

STDMETHODIMP CExplorerBar::TranslateAcceleratorIO(LPMSG pMsg)
{
return S_FALSE;
}
窗口過程
因為區對象的顯示用的是子窗口,所以它必須實現窗口過程來處理Windows消息。瀏覽欄例子實現了一個最簡單的版本,它的窗口過程只處理了五個消息:WM_NCCREATE, WM_PAINT, WM_COMMAND, WM_SETFOCUS, 和 WM_KILLFOCUS。如果要實現更多的功能,很容易擴充使它處理其它的消息。
LRESULT CALLBACK CExplorerBar::WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
CExplorerBar  *pThis = (CExplorerBar*)GetWindowLong(hWnd, GWL_USERDATA);

switch (uMessage)
   {
   case WM_NCCREATE:
      {
      LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
      pThis = (CExplorerBar*)(lpcs->lpCreateParams);
      SetWindowLong(hWnd, GWL_USERDATA, (LONG)pThis);

      //設置窗口句柄
      pThis->m_hWnd = hWnd;
      }
      break;  
   case WM_PAINT:
      return pThis->OnPaint();  
   case WM_COMMAND:
      return pThis->OnCommand(wParam, lParam);  
   case WM_SETFOCUS:
      return pThis->OnSetFocus();
   case WM_KILLFOCUS:
      return pThis->OnKillFocus();
   }
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}
這里WM_COMMAND消息處理器簡單地返回零。WM_PAINT消息處理器創建文本并顯示在資源管理器或IE的區對象中。
LRESULT CExplorerBar::OnPaint(void)
{
PAINTSTRUCT ps;
RECT        rc;

BeginPaint(m_hWnd, &ps);
GetClientRect(m_hWnd, &rc);
SetTextColor(ps.hdc, RGB(255, 255, 255));
SetBkMode(ps.hdc, TRANSPARENT);
DrawText(ps.hdc, TEXT("瀏覽欄例子"), -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(m_hWnd, &ps);
return 0;
}
WM_SETFOCUS 和 WM_KILLFOCUS消息處理器通過調用本現場的IInputObjectSite::OnFocusChangeIS方法通知輸入焦點現場改變:
LRESULT CExplorerBar::OnSetFocus(void)
{
FocusChange(TRUE);

return 0;
}

LRESULT CExplorerBar::OnKillFocus(void)
{
FocusChange(FALSE);
return 0;
}

void CExplorerBar::FocusChange(BOOL bFocus)
{
m_bFocus = bFocus;

//通知焦點已改變的輸入對象現場
if(m_pSite)
   {
   m_pSite->OnFocusChangeIS((IDockingWindow*)this, bFocus);
   }
}
四、總結

區對象提供了靈活和強大的擴展方式,通過定制瀏覽欄使得IE的功能大為增強。桌面區的實現擴展了普通窗口的能力。盡管需要一些對COM的編程,但終究以子窗口的形式提供了一種用戶界面。從而使今后的許多這種編程實現都能用類似的Windows編程技術。雖然本文所討論的例子只提供了有限的功能,但它示范了區對象全部的特性,并且可以在此基礎上進行擴充來創建獨特和功能強大的的用戶界面。
posted on 2007-03-12 16:07 jay 閱讀(641) 評論(0)  編輯 收藏 引用 所屬分類: IE編程
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久久中文| 国产网站欧美日韩免费精品在线观看 | 亚洲午夜一区二区| 亚洲午夜激情| 校园激情久久| 久久精品综合| 六月婷婷一区| 日韩视频免费观看| 亚洲靠逼com| 亚洲一区二区三区四区五区午夜| 国产综合欧美在线看| 国产精品女人网站| 樱桃国产成人精品视频| 亚洲天堂免费观看| 久久九九久精品国产免费直播| 久久精品一区二区三区四区 | 国产精品久久久久久久久免费桃花 | 久久一区二区三区超碰国产精品| 久久综合久久综合九色| 亚洲高清视频的网址| 亚洲精品午夜精品| 亚洲免费在线观看视频| 你懂的国产精品| 国产女同一区二区| 99精品国产99久久久久久福利| 国产精品色婷婷久久58| 久久久久久久尹人综合网亚洲| 久久一综合视频| 国产精品丝袜91| 亚洲国产欧美一区二区三区丁香婷| 亚洲成人在线视频播放| 亚洲欧洲一区二区天堂久久| 亚洲视频狠狠| 欧美99在线视频观看| 在线亚洲激情| 欧美视频在线看| 国模大胆一区二区三区| 欧美一区二区精品在线| 日韩一级大片| 久久久不卡网国产精品一区| 国产精品永久免费观看| 亚洲一区二区三区高清不卡| 亚洲国产欧美在线| 欧美综合第一页| 国产综合精品一区| 亚洲一区二区三区涩| 亚洲国产成人在线| 欧美不卡激情三级在线观看| 在线观看av不卡| 久久久久久久久久久久久女国产乱 | 老色批av在线精品| 在线成人av网站| 欧美国产精品专区| 欧美高清在线一区| 亚洲一区二区三区精品视频| 欧美专区在线| 在线观看日韩专区| 亚洲日本视频| 亚洲国产精品专区久久| 欧美肥婆bbw| 日韩一二在线观看| 亚洲三级电影全部在线观看高清| 欧美日韩裸体免费视频| 亚洲精品资源| 亚洲视频在线观看| 国内一区二区三区在线视频| 欧美韩日一区二区| 欧美日韩蜜桃| 男人的天堂亚洲在线| 欧美mv日韩mv国产网站| 亚洲自拍偷拍视频| 久热国产精品| 午夜精品久久久久久久白皮肤| 正在播放亚洲| 亚洲黄色在线视频| 在线中文字幕日韩| 亚洲国产老妈| 亚洲欧美日韩在线高清直播| 黄色成人免费观看| 久久久精品五月天| 欧美一区在线视频| 欧美日韩一区二区在线观看| 久久一二三区| 国产精品你懂得| 亚洲精品久久久久久久久久久| 亚洲精品字幕| 国产精品最新自拍| 宅男66日本亚洲欧美视频| 能在线观看的日韩av| 欧美在线视频a| 国内视频精品| 久久综合狠狠综合久久综合88| 免费高清在线视频一区·| 国产精品久久久久国产a级| 亚洲国产二区| 欧美不卡视频一区发布| 亚洲毛片一区| 欧美一区二区三区在| 国产亚洲人成网站在线观看| 亚洲欧美一区二区三区极速播放| 欧美影院一区| 一区在线影院| 欧美日韩国产一级片| 亚洲欧美激情精品一区二区| 欧美激情a∨在线视频播放| 99精品视频免费观看| 国产精品大片免费观看| 欧美一级视频| 亚洲精品美女| 久久五月婷婷丁香社区| 亚洲免费电影在线| 午夜日韩激情| 亚洲高清不卡一区| 久久动漫亚洲| 亚洲人成在线播放网站岛国| 欧美午夜美女看片| 久久久久青草大香线综合精品| 亚洲美女av在线播放| 久久这里只有精品视频首页| 一本综合久久| 亚洲毛片av| 亚洲国产精品小视频| 国产午夜亚洲精品不卡| 国产精品久久久久av| 欧美日韩一区免费| 欧美午夜无遮挡| 欧美日韩美女在线| 亚洲激情视频网站| 奶水喷射视频一区| 久久久精品国产免大香伊| 国产区欧美区日韩区| 亚洲综合国产激情另类一区| 亚洲精品一区二区网址| 免费久久99精品国产| 亚洲主播在线| 欧美日韩在线精品一区二区三区| 亚洲精品视频一区二区三区| 91久久精品国产91久久性色tv| 久久久久久97三级| 在线观看欧美日本| 亚洲精品免费看| 国产精品大片免费观看| 久久九九热免费视频| 久久综合激情| 国产视频一区三区| 亚洲国产精品久久久| 99精品国产热久久91蜜凸| 国产精品久久久久久影视| 极品日韩av| 久久久久久夜| 欧美在线资源| 国产热re99久久6国产精品| 亚洲天堂av综合网| 亚洲午夜日本在线观看| 国产精品久在线观看| 亚洲午夜羞羞片| 亚洲综合日韩在线| 国产视频久久久久| 欧美成在线视频| 欧美精品免费在线| 亚洲欧美高清| 久久精品国产一区二区三区免费看| 国产一区91| 欧美国产免费| 欧美激情久久久久久| 亚洲特级毛片| 亚洲国产小视频在线观看| 欧美激情亚洲国产| 免费成人你懂的| 国产欧美一区二区白浆黑人| 亚洲人成人一区二区在线观看| 国产欧美一区二区色老头| 亚洲激情影视| 亚洲国产日本| 亚洲一区精品视频| 中文欧美在线视频| 欧美高清在线一区二区| 久久久91精品国产一区二区三区| 欧美高清在线视频| 男人的天堂亚洲| 99亚洲视频| 最新日韩av| 免费成人黄色| 老司机精品福利视频| 国产精品视频九色porn| 在线亚洲电影| 午夜久久久久| 国产一区激情| 久久免费国产| 亚洲国产成人在线| 99re热精品| 国产精品久久久久三级| 亚洲无线视频| 久久久精品国产免大香伊| 韩国v欧美v日本v亚洲v| 免费成人av在线| 亚洲午夜精品在线| 老**午夜毛片一区二区三区| 亚洲精一区二区三区| 国产精品一二|