[IE編程] IE網頁截圖技術總結

IE網頁截圖是IE編程中的經典問題。 IE9 beta發佈之後我收到很多關於這方面的問題。 最近我把IE和Windows中這部分相關的代碼重新架構了一下,使它們能夠在IE9開啓硬件加速的情況下完美兼容原來GDI函數。 趁着記憶還fresh, 寫一個總結以供大家參考。

主要有以下3個接口可以實現IE網頁截圖。

1) HRESULT IHTMLElementRender::DrawToDC(HDC hDC)

MSDN參考: http://msdn.microsoft.com/en-us/library/aa752273(VS.85).aspx

簡單代碼示例:

  1. IHTMLDocument3 *pDoc = ...;  //得到IHTMLDocument3指針  
  2. IHTMLElement *pDocElement = NULL;  
  3. pDoc->get_documentElement(&pDocElement );  
  4. IHTMLElementRender *pRender =  NULL;  
  5. pDocElement ->QueryInterface(IID_IHTMLElementRender, (void **) &pRender);  
  6. pDocElement->DrawToDC(hImageDC);  
  7.  

注意事項: Quirks 模式下,documentElement不存在, 請使用BODY元素。

優點: 可以畫某個特定的HTML元素

缺點:

  • 需要判斷是不是Quirks模式下,進而決定拿documentElement元素還是BODY元素的的指針;
  • 只能按目前屏幕顯示大小截取,不支持縮放;
  • 在有些情況就是當網頁由frames 組成或者是個內嵌的doc/pdf文檔,該可能會失敗;

 

2) HRESULT IViewObject::Draw( DWORD dwAspect, LONG lindex,  void * pvAspect, DVTARGETDEVICE * ptd, HDC hicTargetDev, HDC hdcDraw,  const LPRECTL lprcBounds,
const LPRECTL lprcWBounds, BOOL (*) (DWORD) pfnContinue, DWORD dwContinue )

MSDN參考:http://msdn.microsoft.com/en-us/library/ms688655(VS.85).aspx

簡單代碼示例:

  1. IHTMLDocument2* pDoc = ...;  // 得到IHTMLDocument2指針  
  2. IViewObject* pViewObject = NULL;  
  3. pDoc->QueryInterface(IID_IViewObject, (void**)pViewObject);  
  4. pViewObject->(DVASPECT_CONTENT, 1, NULL, NULL, hScreenDC, hImageDC, rcSource, NULL, NULL, 0); 

 優點: 可以縮放,IE會根據傳入的lprcBounds自行縮放圖片。

缺點:

  • 因爲要計算縮放,速度會較慢;
  • 截取整個文檔的可見區域,沒法截取特定的元素
  • 有些第三方的ActiveX沒有實現IViewObject接口,導致那些ActiveX沒有出現在截圖裏面。

 

3) BOOL PrintWindow( hwnd,  HDC hdcBlt,  nFlags)

MSDN參考:http://msdn.microsoft.com/en-us/library/dd162869(VS.85).aspx

簡單代碼示例:

  1. IWebBrowser2* pIWebBrowser2 = ...; // 得到IWebBrowser2指針  
  2. HWND hTridentWnd= NULL;    
  3. IOleWindow* pOleWin = NULL;  
  4. pIWebBrowser2->QueryInterface(IID_PPV_ARGS(&pOleWin));  
  5. pOleWin->GetWindow(&hTridentWnd); // 得到Trident窗口handle (類名"Internet Explorer_Server")  
  6. ::PrintWindow(hTridentWnd, hImageDC, PW_CLIENTONLY); 

優點: 內容完整,就算ActiveX沒有實現IViewObject接口,也會被截圖。

缺點:

  • 只能按目前屏幕顯示大小截取,不支持縮放;
  • 速度不如IHTMLElementRender::DrawToDC 

 

注:以上代碼示例都是簡化版,實際使用請檢查函數返回值以及指針有效性。

總結

綜合考慮, PrintWindow 是首選, 簡單而且內容完整。 如果你希望得到縮放的結果,那選擇IViewObject::Draw。 如果你想要對特定某個元素截圖, 那選擇IHTMLElementRender::DrawToDC。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章