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

旅途

如果想飛得高,就該把地平線忘掉

Internet Explorer編程簡述(四)

 1、概述

  調用“添加到收藏夾”對話框(如下)與調用“整理收藏夾”對話框有不同之處,前者所做的工作比后者要來得復雜。將鏈接添加到收藏夾除了將鏈接保存之外,還可能會有脫機訪問的設置,從IE 4.0到IE 5.0,處理的方式也發生了一些變化。




  2、IShellUIHelper接口

  微軟專門提供了一個接口IShellUIHelper來實現對Windows Shell API一些功能的訪問,將鏈接添加到收藏夾也是其中之一,就是下面的AddFavorite函數。


  HRESULT IShellUIHelper::AddFavorite(BSTR URL, VARIANT *Title);

  實例代碼如下:


  void CMyHtmlView::OnAddToFavorites()
  {
  IShellUIHelper* pShellUIHelper;
  HRESULT hr = CoCreateInstance(CLSID_ShellUIHelper, NULL,
  CLSCTX_INPROC_SERVER, IID_IShellUIHelper,(LPVOID*)&pShellUIHelper);

  if (SUCCEEDED(hr))
  {
  _variant_t vtTitle(GetTitle().AllocSysString());
  CString strURL = m_webBrowser.GetLocationURL();

  pShellUIHelper->AddFavorite(strURL.AllocSysString(), &vtTitle);
  pShellUIHelper->Release();
  }
  }

  我們注意到這里的“AddFavorite”函數并沒有像“DoOrganizeFavDlg”那樣需要一個父窗口句柄。這也導致與在IE中打 開不同,通過IShellUIHelper接口顯示出來的“添加到收藏夾”對話框是“非模態”的,有一個獨立于我們應用程序的任務欄按鈕,這使我們的瀏覽 器顯得非常不專業(我是個追求完美的人,這也是我的瀏覽器遲遲不能發布的原因之一)。

  于是我們很自然地想到“shdocvw.dll”中除了“DoOrganizeFavDlg”外,應該還有一個類似的函數,可以傳入一個父窗口句柄用以顯示模態窗口,也許就像這樣:


  typedef UINT (CALLBACK* LPFNADDFAV)(HWND, LPTSTR, LPTSTR);

  事實上,這樣的函數確實存在于“shdocvw.dll”中,那就是“DoAddToFavDlg”。


  3、DoAddToFavDlg函數

  “DoAddToFavDlg”函數也是“shdocvw.dll”暴露出來的函數之一,其原型如下:


  typedef BOOL (CALLBACK* LPFNADDFAV)(HWND, TCHAR*, UINT, TCHAR*, UINT,LPITEMIDLIST);

  第一個參數正是我們想要的父窗口句柄,第二和第四個參數分別是初始目錄(一般來說就是收藏夾目錄)和要添加的鏈接的名字(比如網頁的 Title),第三和第五個參數分別是第二和第四兩個緩沖區的長度,而最后一個參數則是指向與第二個參數目錄相關的item identifier list的指針(PIDL)。但最奇怪的是這里并沒有像“AddFavorite”函數一樣的鏈接URL,那鏈接是怎樣添加的呢?答案是“手動創建”。

第二個參數在函數調用返回后會包含用戶在“添加到收藏夾”對話框中選擇或創建的完整鏈接路徑名(如“X:\XXX\mylink.url”),我們就根 據這個路徑和網頁的URL來創建鏈接,代碼如下(為簡化,此處省去檢查"shdocvw.dll"是否已在內存中的代碼,參見《Internet Explorer 編程簡述(三)“整理收藏夾”對話框》):


  void CMyHtmlView::OnFavAddtofav()
  {
  typedef BOOL (CALLBACK* LPFNADDFAV)(HWND, TCHAR*, UINT, TCHAR*, UINT,LPITEMIDLIST);

  HMODULE hMod = (HMODULE)LoadLibrary("shdocvw.dll");
  if (hMod)
  {
  LPFNADDFAV lpfnDoAddToFavDlg = (LPFNADDFAV)GetProcAddress( hMod, "DoAddToFavDlg");
  if (lpfnDoAddToFavDlg)
  {
  TCHAR szPath[MAX_PATH];
  LPITEMIDLIST pidlFavorites;

  if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE) &&
  (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidlFavorites))))
  {
  TCHAR szTitle[MAX_PATH];
  strcpy(szTitle, GetLocationName());

  TCHAR szURL[MAX_PATH];
  strcpy(szURL, GetLocationURL());

  BOOL bOK = lpfnDoAddToFavDlg(m_hWnd, szPath,
  sizeof(szPath)/sizeof(szPath[0]), szTitle,
  sizeof(szTitle)/sizeof(szTitle[0]), pidlFavorites);
  CoTaskMemFree(pidlFavorites);

  if (bOK)
  CreateInternetShortcut( szURL, szPath, "");  //創建Internet快捷方式
  }
  }
  FreeLibrary(hMod);
  }
  return;
  }

  實現CreateInternetShortcut函數創建Internet快捷方式,可以用讀寫INI文件的方法,但更好的則是利用IUniformResourceLocator接口。


  HRESULT CMyHtmlView::CreateInternetShortcut(LPCSTR pszURL, LPCSTR pszURLfilename,
  LPCSTR szDescription,LPCTSTR szIconFile,int nIndex)
  {
  HRESULT hres;

  CoInitialize(NULL);

  IUniformResourceLocator *pHook;

  hres = CoCreateInstance (CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
  IID_IUniformResourceLocator, (void **)&pHook);

  if (SUCCEEDED (hres))
  {
  IPersistFile *ppf;
  IShellLink *psl;

  // Query IShellLink for the IPersistFile interface for
  hres = pHook->QueryInterface (IID_IPersistFile, (void **)&ppf);
  hres = pHook->QueryInterface (IID_IShellLink, (void **)&psl);

  if (SUCCEEDED (hres))
  {
  WORD wsz [MAX_PATH]; // buffer for Unicode string

  // Set the path to the shortcut target.
  pHook->SetURL(pszURL,0);

  hres = psl->SetIconLocation(szIconFile,nIndex);

  if (SUCCEEDED (hres))
  {
  // Set the description of the shortcut.
  hres = psl->SetDescription (szDescription);

  if (SUCCEEDED (hres))
  {
  // Ensure that the string consists of ANSI characters.
  MultiByteToWideChar (CP_ACP, 0, pszURLfilename, -1, wsz, MAX_PATH);

  // Save the shortcut via the IPersistFile::Save member function.
  hres = ppf->Save (wsz, TRUE);
  }
  }

  // Release the pointer to IPersistFile.
  ppf->Release ();
  psl->Release ();
  }

  // Release the pointer to IShellLink.
  pHook->Release ();

  }
  return hres;
  }

  好,上面的方法雖然麻煩一點,但總算解決了“模態窗口”的問題,使得我們的程序不至于讓用戶鄙視。但是問題又來了,我們發現“允許脫機使用”是Disabled的,那“自定義”也就無從談起了,盡管90%的人都沒有使用過IE提供的脫機瀏覽。

  難道我們的希望要破滅嗎?我們一方面想像調用“AddFavorite”函數一樣的不必手動創建鏈接,一方面又要模態顯示窗口,就像IE那樣,還能自定義脫機瀏覽。

  3、腳本方式

  許多網頁上都會有一個按鈕或鏈接“添加本頁到收藏夾”,實際上通過下面的腳本顯示模態的“添加到收藏夾”對話框將網頁加入到收藏夾。


  window.external.AddFavorite(location.href, document.title);

  這里的external對象是WebBrowser內置的COM自動化對象,以實現對文檔對象模型(DOM)的擴展(我們也可以通過 IDocHostUIHandler實現自己的擴展).查閱MSDN可以得知external對象的的方法與IShellUIHelper接口提供的方法 是一樣的。我們有理由相信,IShellUIHelper提供了對WebBrowser內置的external對象的訪問,如果在適當的地方創建 IShellUIHelper接口的實例,也許調用“AddFavorite”函數顯示出來的就是模態對話框了。問題是我們還沒有找到這樣的地方。

  從上面的腳本,我們很自然地又想到另一個方法。如果能夠讓網頁來執行上面的腳本,豈不是問題就解決了?說做就做,如下:


  void CMyHtmlView::OnFavAddtofav()
  {
  CString strUrl = GetLocationURL();
  CString strTitle = GetLocationName();
  CString strjs = "javascript:window.external.AddFavorite('" + strUrl + "'," + "'" + strTitle + "');";
  ExecScript(strjs);
  }

  void CMIEView::ExecScript(CString strjs)
  {
  CComQIPtr<IHTMLDocument2>   pHTMLDoc = (IHTMLDocument2*)GetHtmlDocument();
  if ( pHTMLDoc != NULL  )
  {
  CComQIPtr<IHTMLWindow2>   pHTMLWnd;
  pHTMLDoc->get_parentWindow( &pHTMLWnd );

  if ( pHTMLWnd != NULL  )
  {
  CComBSTR bstrjs = strjs.AllocSysString();
  CComBSTR bstrlan = SysAllocString(L"javascript");
  VARIANT varRet;
  pHTMLWnd->execScript(bstrjs, bstrlan, &varRet);
  }
  }
  }

  先從CHtmlView獲得文檔的父窗口window對象的指針,再調用其方法execScript來執行腳本(事實上可以執行任意的腳本)。 試驗發現,這個方法非常有效,不僅窗口是模態的,而且不需要手動創建鏈接,更重要的是“允許脫機使用”和“自定義”按鈕也可以用了。

  4、問題仍舊沒有解決

  執行腳本的方式看起來有效,可一旦我們的程序實現了IDocHostUIHandler接口對WebBrowser進行高級控制,就會發現一旦 執行的腳本包含有對“external”對象的調用,就會出現“找不到對象”的腳本錯誤。原因是當MSHTML解析引擎(并非WebBrowser)檢查 到宿主實現了IDocHostUIHandler接口,就會調用其GetExternal方法以獲得一個用以擴展DOM的自動化接口的引用。


  HRESULT IDocHostUIHandler::GetExternal(IDispatch **ppDispatch)

  但有時候我們并沒有想要擴展DOM,同時我們還希望WebBrowser使用它自己的DOM擴展。糟糕的是GetExternal方法的文檔中 說這種情況下必須把ppDispatch設置為NULL,換句話說,WebBrowser連它內置的external對象也不用了,那我們的 window.external.AddFavorite就變得無處為家了。

  我曾多方嘗試將WebBrowser內置的external對象找出來,雖然都沒有成功,但是解決問題的方法卻被我找到了。

  5、完美的方案

  WebBrowser內置的external對象我們雖然找不到,但它肯定存在,我們只要想辦法讓WebBrowser自己完成對其調用即可。 實現非常簡單,找到WebBrowser中包含的“Internet Explorer_Server”窗口的句柄,發一個消息就完成了。下面的代碼中假設m_hWndIE就是“Internet Explorer_Server”窗口的句柄。


  #define ID_IE_ID_ADDFAV 2261
  ::SendMessage( m_hWndIE, WM_COMMAND, MAKEWPARAM(LOWORD(ID_IE_ID_ADDFAV), 0x0), 0 );

  試一試成果,是不是和在Internet Explorer中選擇“添加到收藏夾”的效果一模一樣。

  至于為什么這樣做,后續文章再說。


posted on 2007-07-29 15:12 旅途 閱讀(1050) 評論(0)  編輯 收藏 引用 所屬分類: BHO

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美激情视频网站| 亚洲片在线资源| 亚洲高清av| 娇妻被交换粗又大又硬视频欧美| 国产精品一区免费视频| 国产欧美在线观看一区| 国产欧美亚洲日本| 亚洲春色另类小说| aⅴ色国产欧美| 亚洲一区二区三区免费观看 | 亚洲一本大道在线| 欧美在线播放一区二区| 久久久人成影片一区二区三区观看| 毛片av中文字幕一区二区| 欧美激情精品| 亚洲午夜精品一区二区三区他趣| 翔田千里一区二区| 你懂的视频一区二区| 欧美日韩国产精品一区二区亚洲| 国产精品久久77777| 黄色成人片子| 亚洲欧美久久| 亚洲电影在线| 午夜激情综合网| 欧美精品观看| 国产亚洲欧美另类中文| 亚洲片在线资源| 欧美专区亚洲专区| 亚洲精品自在久久| 久久国产免费看| 欧美日韩亚洲一区在线观看| 国产手机视频精品| 99视频日韩| 女生裸体视频一区二区三区| 亚洲天堂成人| 狼狼综合久久久久综合网| 国产欧美日本一区视频| 亚洲精品人人| 欧美成人国产| 久久精品在线观看| 国产精品激情av在线播放| 亚洲精品久久久一区二区三区| 国产精品热久久久久夜色精品三区| 极品少妇一区二区| 欧美亚洲一区二区三区| 亚洲伦理一区| 欧美人与性动交α欧美精品济南到| 韩国成人精品a∨在线观看| 午夜精品久久久久影视| 一区二区三区精密机械公司| 欧美日韩不卡视频| 日韩亚洲欧美在线观看| 欧美黑人在线播放| 久久综合激情| 国内精品久久久久影院 日本资源 国内精品久久久久伊人av | 伊人久久综合97精品| 欧美一区在线看| 中国亚洲黄色| 欧美午夜宅男影院| 亚洲专区免费| 一区二区三区四区五区在线| 欧美日韩1区| 一区二区精品在线观看| 日韩一区二区精品视频| 欧美精品日韩三级| 99re热这里只有精品免费视频| 亚洲电影免费在线| 另类春色校园亚洲| 亚洲人成绝费网站色www| 美国十次成人| 女人天堂亚洲aⅴ在线观看| 亚洲精品系列| 亚洲精品中文字幕女同| 欧美日韩国产成人在线观看| 亚洲一区在线观看视频| 午夜精品短视频| 国产亚洲欧美一区在线观看| 麻豆成人综合网| 欧美国产一区在线| 亚洲天堂av图片| 欧美在线资源| 亚洲国产免费| 一区二区欧美在线观看| 国产精品最新自拍| 另类图片国产| 欧美精品一区在线| 午夜精品在线视频| 久久综合中文字幕| 亚洲伦理久久| 亚洲在线观看视频| 红桃视频国产一区| 一区二区免费看| 国产一区二区在线观看免费播放| 欧美激情一区二区久久久| 国产精品豆花视频| 欧美黄色成人网| 国产精品实拍| 欧美韩日一区二区| 国产精品美女诱惑| 麻豆成人小视频| 国产精品久久久久一区二区三区| 午夜综合激情| 99这里只有精品| 一区二区三区在线视频观看| 亚洲精品美女在线观看播放| 国产欧美一区二区三区另类精品| 欧美福利一区二区| 国产美女精品| 亚洲国产精品一区制服丝袜| 国产亚洲aⅴaaaaaa毛片| 亚洲精品一区二区在线| 伊人久久大香线蕉av超碰演员| 99精品欧美一区二区三区| 在线观看一区二区精品视频| 亚洲小说春色综合另类电影| 亚洲精品免费一区二区三区| 久久精品人人做人人爽电影蜜月| 亚洲午夜日本在线观看| 欧美大片va欧美在线播放| 久久免费午夜影院| 国产精品夜夜夜| 99综合电影在线视频| 亚洲精品专区| 嫩模写真一区二区三区三州| 嫩模写真一区二区三区三州| 国产欧美日韩一区二区三区在线| 久久久久9999亚洲精品| 国产老女人精品毛片久久| 欧美超级免费视 在线| 国产美女诱惑一区二区| 9色精品在线| 久久久天天操| 国产精品都在这里| 亚洲最新中文字幕| 一本高清dvd不卡在线观看| 欧美+亚洲+精品+三区| 欧美成人精品在线| 亚洲福利在线看| 欧美成人乱码一区二区三区| 你懂的一区二区| 亚洲高清二区| 欧美成人首页| 亚洲精品视频在线| 一区二区三区四区五区精品视频| 欧美人妖在线观看| av不卡免费看| 欧美在线观看一区二区| 激情国产一区二区| 免费在线欧美黄色| 亚洲黄色免费网站| 欧美激情精品久久久久久变态| 你懂的视频欧美| 亚洲美女毛片| 欧美视频在线不卡| 亚洲欧美日韩区| 久热精品视频在线免费观看| 在线精品国精品国产尤物884a| 久久综合久色欧美综合狠狠| 亚洲国产精品久久| 亚洲综合色视频| 国际精品欧美精品| 欧美国产国产综合| 亚洲一区二区三区色| 久久亚洲图片| 99www免费人成精品| 国产欧美综合一区二区三区| 久久影视三级福利片| 亚洲最新视频在线| 久久精品亚洲国产奇米99| 伊人天天综合| 欧美日韩一区在线播放| 久久精品国产精品亚洲精品| 最新精品在线| 欧美在线观看一二区| 亚洲精品护士| 国产日韩精品一区二区浪潮av| 久久一区二区精品| 9人人澡人人爽人人精品| 久久午夜精品一区二区| 日韩视频免费观看| 国产日韩一区二区| 欧美久久电影| 久久精品成人欧美大片古装| 99国产精品久久久| 欧美成人网在线| 亚洲一级黄色| 亚洲日本一区二区| 国产在线乱码一区二区三区| 欧美午夜不卡在线观看免费| 噜噜噜91成人网| 欧美一区二区大片| 一区二区欧美在线观看| 亚洲第一级黄色片| 久久视频在线视频| 欧美在线观看天堂一区二区三区| 一片黄亚洲嫩模| 亚洲欧洲日产国码二区| 尤物99国产成人精品视频| 国产伦一区二区三区色一情| 欧美日韩国产小视频在线观看|