首页 > 代码库 > 【MFC】截图编辑插件技术总结(4):IE下网页整页截屏

【MFC】截图编辑插件技术总结(4):IE下网页整页截屏

现在大部分浏览器都已经实现了网页截图的功能,我要说的与这种情况稍有不同,浏览器是从内部获取,而因为我是ActiveX插件,需要从外部获取网页的document。但是,实现的思路基本一致,就是将Webbrowser放大到足够大,使滚动条不出现,然后调用IViewObject接口的Draw方法实现整页的截图。下面先给出代码实现,再对代码进行分析。

  1 POINT pnt;  2   3 RECT rc;  4   5 HWND DeskHwnd = ::GetDesktopWindow(); //取得桌面句柄  6   7 HDC DeskDC = ::GetWindowDC(DeskHwnd); //取得桌面设备场景dc  8   9 int oldRop2 = SetROP2(DeskDC, R2_NOTXORPEN); 10  11 ::GetCursorPos(&pnt);//取得鼠标坐标 12  13 HWND UnHwnd = ::WindowFromPoint(pnt) ; //取得鼠标指针处窗口句柄,这里获取到的是Webbrowser控件的窗口句柄 14  15 m_ptWnd=UnHwnd; 16  17 HDC pdc=::GetWindowDC(m_ptWnd);//获取目标窗口DC用于截图 18  19 //----------------以下获取IWebBrowser2接口------------------------- 20  21 CComPtr<IOleClientSite> spClientSite; 22  23 HRESULT hr; 24  25 long iHeight,iWidth; 26  27 hr=GetSite(IID_IUnknown,(void**)&spClientSite); 28  29 CComPtr<IServiceProvider> isp, isp2; 30  31 IViewObject* spIViewObject; 32  33 hr = spClientSite->QueryInterface(IID_IServiceProvider, (void**)(&isp)); 34  35 if (SUCCEEDED(hr)) 36  37 { 38  39 hr = isp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void**)(&isp2)); 40  41 if (SUCCEEDED(hr)) 42  43 { 44  45 CComPtr<IWebBrowser2> spBrowser; 46  47 hr = isp2->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void**)(&spBrowser)); 48  49 if (SUCCEEDED(hr)) 50  51 { 52  53 //------------------------从获取到的IWebBrowser2接口中获取IHTMLDocument2接口------------------ 54  55 IHTMLDocument2* pHtmlDocument2; 56  57 CComPtr<IDispatch> spDisp; 58  59 spBrowser->get_Document(&spDisp); 60  61 spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&pHtmlDocument2);//获取IHTMLDocument2接口文档 62  63 IHTMLElement* pElement; 64  65 pHtmlDocument2->get_body(&pElement);//获取IHTMLElement接口文档 66  67 IHTMLElement2* pElement2; 68  69 pElement->QueryInterface(IID_IHTMLElement2, (void**)&pElement2);//获取IHTMLElement2接口文档 70  71 pElement2->get_scrollHeight(&iHeight); //获取网页实际高度 72  73 pElement2->get_scrollWidth(&iWidth); //获取网页实际宽度 74  75 //------------------以下准备合适大小的图片------------------------ 76  77 //HDC pdc2=::GetWindowDC(m_ptWnd); 78  79 HDC hIEMenDC2=::CreateCompatibleDC(DeskDC); 80  81 HBITMAP hIEBitmap2=::CreateCompatibleBitmap(DeskDC,iWidth,iHeight); 82  83 ::SelectObject(hIEMenDC2,hIEBitmap2); 84  85 //------------------以下调整Webbrowser大小以截取全页--------------- 86  87 long oldHeight,oldWidth; 88  89 CRect oldrect; 90  91 ::GetWindowRect(m_ptWnd,&oldrect);//调整前先记录下原来的大小,以便最后还原 92  93 oldHeight=oldrect.Height(); 94  95 oldWidth=oldrect.Width(); 96  97 HWND m_parentWnd=::GetParent(m_ptWnd);//**************想要改变webbrowser的大小必须获取宿主窗口的句柄,改变宿主窗口的大小,这里被坑了好久,要注意!************* 98  99 BOOL flag=::MoveWindow(m_parentWnd,0,0,iWidth,iHeight,TRUE);//改变宿主窗口的大小到合适的大小100 101 flag=::MoveWindow(m_ptWnd,0,0,iWidth,iHeight,TRUE);//改变webbrowser窗口的大小到合适的大小102 103 //------------------以下对网页进行截图-----------------------------104 105 //------------------方法一:获取IViewObject接口,调用Draw方法截图--106 107 IViewObject* pViewObject;108 109 //------------------------从获取到的IWebBrowser2接口中获取IHTMLDocument2接口------------------110 111 pHtmlDocument2->QueryInterface(IID_IViewObject,(void**)&pViewObject);112 113 pHtmlDocument2->get_body(&pElement);//获取IHTMLElement接口文档114 115 // pElement->QueryInterface(IID_IHTMLElementRender, (void **) &pRender);116 117 IHTMLBodyElement* pBodyElement;118 119 pElement->QueryInterface(IID_IHTMLBodyElement,(void**)&pBodyElement);120 121 BSTR oldscrolltype;122 123 pBodyElement->get_scroll(&oldscrolltype);124 125 pBodyElement->put_scroll(_T("no"));//去掉滚动条126 127 RECTL rectl;128 129 rectl.left=0;rectl.top=0;rectl.right=iWidth;rectl.bottom=iHeight;130 131 pViewObject->Draw(DVASPECT_CONTENT,1,NULL,NULL,NULL,hIEMenDC2,&rectl,NULL,NULL,NULL);132 133 //------------以下还原浏览器位置和滚动条,并保存图片134 135 pBodyElement->put_scroll(oldscrolltype);136 137 flag=::MoveWindow(m_ptWnd,0,0,oldWidth,oldHeight,TRUE);138 139 flag=::MoveWindow(m_parentWnd,0,0,oldWidth,oldHeight,TRUE);140 141 SaveToFile(_T(""),hIEBitmap2);142 143 }144 145 }146 147 }

 

首先,要想操作Webbrowser就要获取IWebBrowser2接口,如果是浏览器实现该功能可以直接获取,而在ActiveX中就要用别的方法从外部获取,获取的方法很多,这里只介绍我使用的方法:

1、使用GetSite函数获取IOleClientSite接口。

2、通过IOleClientSite接口获取IServiceProvider接口。

3、使用QueryService获取顶层WebBrowser,hr = isp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (void**)(&isp2));

4、使用QueryService获取IWebBrowser2接口。

这里不探讨为什么要这么获取,我也不是很清楚,只知道通过这种方法可以从外部获取顶层WebBrowser的IWebBrowser2接口。

然后,在获取了IWebBrowser2接口后,我们就可以开始通过它操作WebBrowser了。要想截全图,当然需要知道网页的实际大小,可以通过下面的顺序来获取IHTMLElement2接口:

IWebBrowser2-->IHTMLDocument2-->IHTMLElement-->IHTMLElement2

获取了IHTMLElement2接口后就可以通过get_scrollHeight和get_scrollWidth获取网页的高和宽了。得到网页实际大小后就可以用MoveWindow改变WebBrowser的大小了,但这里需要注意的是,如果只是改变WebBrowser的大小并不一定能够将网页放大,还需要将它的宿主窗口也一起放大才可以~本人之前一直无法把WebBrowser放大,最后发现是这个原因,切记,切记!

最后,前面的准备工作做完之后,就可以通过IHTMLDocument2接口获取IViewObject接口了,然后调用Draw方法就可以把整个网页的内容保存到内存DC中了。这样截取到的图片中还是会有不能滚动的滚动条图案在,如果觉得碍眼想要把它去掉的话也是有办法的,那就是修改body元素了,通过前面获取的IHTMLDocument2接口,可以通过get_body方法获取body的IHTMLElement然后获取IHTMLBodyElement然后通过put_scroll方法修改滚动条。截完图后记得把原来的属性设置回去!