将WebBrowser中的页面截屏保存为图片
来源:互联网 发布:有没有优步抢单软件 编辑:程序博客网 时间:2024/04/29 10:56
先说一点题外话,将WEB页面渲染成图片有比较好的开源工具,如CutyCapt ,它使用WebKit渲染,兼容多种操作系统,适合于在服务器上作为后台服务运行。
不过,这里说到的是对WebBrowser内的页面进行截图并保存. WebBrowser本质上就是IE内核的浏览器。使用mshtml来渲染页面的话,依赖GDI,所以不可能作为后台服务运行。
获取WebBrowser截屏的方法很多, PrintWindow / IHTMLElementRender / IViewObject。不管使用哪种方法,都需考虑长页面的问题。因为这些方法都只能截屏clientArea区域,也就是说没显示的部分无法截图,必须通过多次截图完成整个页面截图的拼合。
本文使用的是PrintWindow方式,这种方式原理上能够兼容其它所有的浏览器。
首先通过设置ControlSite将浏览器的边框和滚动条隐藏,这样客户区只有WEB页面。
HRESULT FAR EXPORT CCustomControlSite::XDocHostUIHandler::GetHostInfo( DOCHOSTUIINFO* pInfo ){METHOD_PROLOGUE(CCustomControlSite, DocHostUIHandler)pInfo->cbSize = sizeof(DOCHOSTUIINFO);pInfo->dwFlags = DOCHOSTUIFLAG_DIALOG | DOCHOSTUIFLAG_DISABLE_HELP_MENU |DOCHOSTUIFLAG_ACTIVATE_CLIENTHIT_ONLY |DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8 |DOCHOSTUIFLAG_NO3DOUTERBORDER |DOCHOSTUIFLAG_NO3DBORDER |DOCHOSTUIFLAG_SCROLL_NO |DOCHOSTUIFLAG_USE_WINDOWLESS_SELECTCONTROL;pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;return S_OK;}
然后挂接document.body.onload事件,保证页面上的图片都加载完成。
void CWebBrowser::OnDocumentComplete( IDispatch *pDisp, VARIANT *URL){CComQIPtr<IWebBrowser2> pWebBrowser2(pDisp);if( pWebBrowser2 ){CComPtr<IDispatch> pDispatch;if( S_OK == pWebBrowser2->get_Document(&pDispatch) ){CComQIPtr<IHTMLDocument2> pDoc2(pDispatch);if( pDoc2 ){BSTR bstrReadyState;if( S_OK == pDoc2->get_readyState(&bstrReadyState) ){if( 0 == _wcsicmp( bstrReadyState, L"complete") ){CComPtr<IHTMLWindow2> pWnd2;if( S_OK == pDoc2->get_parentWindow(&pWnd2) ){CComPtr<IHTMLWindow2> pTopWnd2;if( S_OK == pWnd2->get_top(&pTopWnd2) ){CComQIPtr<IHTMLWindow3> pTopWnd3(pTopWnd2);if( pTopWnd3 ){VARIANT_BOOL vbSuccess = VARIANT_FALSE; if( m_pOnPageLoadEvent ){pTopWnd3->detachEvent( _bstr_t(L"onload"), m_pOnPageLoadEvent);}m_pOnPageLoadEvent = (CDOMEventHandler*)CDOMEventHandler::CreateEventHandler( &CWebBrowser::OnPageLoad, (LONG_PTR)this);pTopWnd3->attachEvent( _bstr_t(L"onload"), m_pOnPageLoadEvent, &vbSuccess);}}}}SysFreeString(bstrReadyState);}}// pDoc2}// get_Document}// pWebBrowser2}
当页面onload后,就可以进行截屏了。下面是关键代码,其实原理很简单:
首先创建一个大小等于 document.body.clientWidth 宽, document.documentElement.scrollHeight 高的 画布。 然后依次滚动页面,每次滚动的距离等于客户区的高度,滚动后截图,依此结束。
void CWebBrowser::CaptureToImage(){CComQIPtr<IHTMLDocument2> pDoc2 = this->get_Document();CComQIPtr<IHTMLDocument3> pDoc3(pDoc2);if( pDoc2 ){CComPtr<IHTMLElement> pBodyElem;CComPtr<IHTMLWindow2> pWnd2, pTopWnd2;if( S_OK == pDoc2->get_body(&pBodyElem) &&S_OK == pDoc2->get_parentWindow(&pWnd2) &&S_OK == pWnd2->get_top(&pTopWnd2)){long nScrollHeight = 0L, nClientWidth = 0L, nClientHeight = 0L;CComPtr<IHTMLElement> pDocElem;pDoc3->get_documentElement(&pDocElem);CComQIPtr<IHTMLElement2> pDocElem2(pDocElem);CComQIPtr<IHTMLElement2> pBodyElem2(pBodyElem);pBodyElem2->get_scrollHeight(&nScrollHeight);RECT rect;GetClientRect(&rect);nClientWidth = rect.right - rect.left;nClientHeight = rect.bottom - rect.top;if( nScrollHeight > 0 && nClientWidth > 0 && nClientHeight > 0 ){Bitmap bitmap(nClientWidth, nScrollHeight);Graphics g(&bitmap);HDC hDC = g.GetHDC();if (hDC != NULL){long nYPos = nScrollHeight - nClientHeight;do {pTopWnd2->scrollTo( 0, nYPos);{long y1 = 0, y2 = 0;pDocElem2->get_scrollTop(&y1);pBodyElem2->get_scrollTop(&y2);nYPos = max(y1, y2);}HDC hMemDC = ::CreateCompatibleDC(hDC);HBITMAP hBitmap = ::CreateCompatibleBitmap( hDC, nClientWidth, nClientHeight);::SelectObject( hMemDC, hBitmap);VERIFY(::PrintWindow( GetSafeHwnd(), hMemDC, PW_CLIENTONLY));::SelectObject( hMemDC, NULL);::BitBlt( hDC, 0, nYPos, nClientWidth, nClientHeight, hMemDC, 0, 0, SRCCOPY);::DeleteDC(hMemDC);::DeleteObject(hBitmap);if( nYPos <= 0)break;nYPos -= nClientHeight;if( nYPos < 0 )nYPos = 0;} while (true);g.ReleaseHDC(hDC);CLSID pngClsid; GetEncoderClsid(L"image/png", &pngClsid); bitmap.Save(L"L:\\WebSitesMonitoring\\1.png", &pngClsid);}}}}}
最终通过GDI+保存成PNG格式。下面是GetEncoderClsid方法
int CWebBrowser::GetEncoderClsid(const WCHAR* format, CLSID* pClsid) { UINT num = 0; // number of image encoders UINT size = 0; // size of the image encoder array in bytes ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize(&num, &size); if(size == 0) return -1; // Failure pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if(pImageCodecInfo == NULL) return -1; // Failure GetImageEncoders(num, size, pImageCodecInfo); for(UINT j = 0; j < num; ++j) { if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) { *pClsid = pImageCodecInfo[j].Clsid; free(pImageCodecInfo); return j; // Success } } free(pImageCodecInfo); return -1; // Failure }
下面是效果,图片已经被CSDN压缩的不成样子了。。
- 将WebBrowser中的页面截屏保存为图片
- 截屏保存为图片
- VB截屏保存图片
- WinCE抓屏保存为图片
- 截屏保存为位图(C++)
- aspnet如何实现截屏保存图片?
- android长按画圆并截屏保存图片
- jquery 网页截屏保存图片
- android截屏保存相机图片
- 将JPanel存为图片
- iOS 任意页面摇一摇并截屏保存到相册
- wince下实现拷屏保存为bmp,装载jpg格式图片转成bmp格式图片
- wince下实现拷屏保存为bmp,装载jpg格式图片转成bmp格式图片
- vickate_iOS截屏保存功能
- 将网络中的图片存为NSData并保存到sqlite的BLOB字段中.
- 将网络中的图片存为NSData并保存到sqlite的BLOB字段中
- 将网络中的图片存为NSData并保存到sqlite的BLOB字段中
- 将网络中的图片存为NSData并保存到sqlite的BLOB字段中
- c#窗体透明问题
- cxGrid 使用指南 3
- 《LINUX程序设计》第4章总结
- cxGrid 行变颜色
- 基于S3c6410触摸屏驱动分析(一)
- 将WebBrowser中的页面截屏保存为图片
- 密码学简介(四)
- C++中的虚函数(virtual function)
- C++ 编程规范
- ExpandableListView实例(二)_两种方式实现QQ中组后面显示子条目数量效果
- 断点续传下载器
- VC++2005自带的atlrx.h正则表达式库使用笔记
- 索尼Walkman NWZ-S764 8G MP3 (带蓝牙耳机、FM)$99
- 网络爬虫内容抓取