【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方法修改滚动条。截完图后记得把原来的属性设置回去!

posted on 2014-07-22 20:08  JAM_LU  阅读(1048)  评论(0编辑  收藏  举报