最近在写程序的时候,突然觉得google chrome的网页缩略照片挺好玩 , 可是 chrome 是自己的内核, 自家的东西当然方便.WebBrowser 又怎么办?
首先想到的是最普通的屏幕复制, 也就是大家熟知的bitblt, 从WebBrowser的dc复制到bitmap的dc. 这种方法有很大的局限性: 1.要正确复制,必须保证WebBrowser在屏幕复制的时候必须处于窗口最前端( 就是没有遮蔽物 ), 否则复制出来的图像是有遮盖物. 2.即使没有遮盖物,复制出来的图像往往包含3D Border , Scroll , 这在标准的WebBrowser是必要的.但是对于网页缩略照片,这可就是恶心的东西了.
于是有人想到了ActiveX里面的一个接口 IViewObject2 , WebBrowser也实现了这个接口, 你只需要从WebBrowser对象中QueryInterface(...)就可以枚举出这个接口. IWebBrowser2* pWB2 = ...//获取WebBrowser接口, pWB2->QueryInterface( IID_IViewObject2 , (void**)&pViewObj2 ); 然后使用 IViewObject2 中的 Draw 这个方法,就可以绘画WebBrowser中网页的内容,
很好,即使窗口是隐藏的也可以画出, 可是,等等, 只要您尝试这个方法, 您就会发现,这个仍然不尽如人意. 因为你只能获取WebBrowser这个窗口大小的网页缩略图 , 而无法获取整个网页的缩略图. 同时, 3D Border, Scroll 仍然折磨着我们. 有人提出了如下代码 , 可以一定程度缓解, 让我们看看:
-
IHTMLBodyElement*pBody=0;
-
IHTMLElement*pBodyElem;
-
HRTEST_E(GetHTMLDocument2()->get_body(&pBodyElem));
-
HRTEST_E(pBodyElem->QueryInterface(IID_IHTMLBodyElement,(void**)&pBody));
-
-
IHTMLStyle*pStyle;
-
HRTEST_E(pBodyElem->get_style(&pStyle));
-
HRTEST_E(pStyle->put_borderStyle(bsBorderStyle=::SysAllocString(L"none")));
-
-
-
HRTEST_E(pBody->put_scroll(bsScrollStyle=::SysAllocString(L"no")));
-
-
IHTMLElement2*pBodyElement2;
-
HRTEST_E(pBody->QueryInterface(IID_IHTMLElement2,(void**)&pBodyElement2));
-
longiScrollWidth=0;
-
HRTEST_E(pBodyElement2->get_scrollWidth(&iScrollWidth));
-
longiScrollHeight=0;
-
HRTEST_E(pBodyElement2->get_scrollHeight(&iScrollHeight));
-
RECTrc={0,0,iScrollWidth,iScrollHeight};
-
::SetWindowPos(GetHWND(),NULL,0,0,iScrollWidth,iScrollHeight,SWP_NOREDRAW);
-
SetWebRect(&rc);
忽略其中奇怪的宏,我们可以发现,这个思想就是使用 Body, 来关闭border, 关闭scroll, 在有些场合下是有用的,可是大部分情况,如果页面过大(比如超过屏幕大小), scroll还是会出现. border也不会消失,因为这和body元素没有关系.
真的没有办法解决吗? 当然有,否则我也不会写那么多东西了, 有一个很著名的好东西, 接口:IDocHostUIHandler , 他有一个方法:GetHostInfo(DOCHOSTUIINFO *pInfo); 可以改变WebBrowser的显示方式.完全不需要使用body来关闭border和scroll这种吃力不讨好的办法. 所以为了去除border, scroll我们只要这么写:
-
HRESULT
-
CShadowWebWindow::GetHostInfo(DOCHOSTUIINFO*pInfo)
-
{
-
pInfo->cbSize=sizeof(DOCHOSTUIINFO);
-
pInfo->dwFlags=DOCHOSTUIFLAG_DIALOG|
-
DOCHOSTUIFLAG_THEME|
-
DOCHOSTUIFLAG_NO3DBORDER|
-
DOCHOSTUIFLAG_SCROLL_NO;
-
returnS_OK;
-
}
其中DOCHOSTUIFLAG_NO3DBORDER和DOCHOSTUIFLAG_SCROLL_NO正是我们需要的效果. 接下来我们要画出整个网页,只需要设置WebBrowser的容器大小为html的大小, 就可以完满的画出网页缩略图.
当然, 在下强烈推荐应当使用一个看不见的WebBrowser来实现化网页缩略图, 毕竟, 一个窗口忽大忽小,不是一个好的用户体验.
最后整理一下代码:
我使用一个叫CShadowWebWindow类实现WebBrowser, 这是一个不可见的窗口.
以下是关键代码, (请忽略奇怪的宏 )
-
void
-
CShadowWebWindow::DocumentComplete(IDispatch*pDisp,VARIANT*URL)
-
{
-
-
WebBrowserWindow::DocumentComplete(pDisp,URL);
-
-
-
PWSTRnpwNewBmpFilePath=NULL;
-
IWebBrowser2*pWB2=GetWebBrowser2();
-
IViewObject2*pViewObject2=NULL;
-
HRTEST_E(pWB2->QueryInterface(IID_IViewObject2,(void**)&pViewObject2));
-
IHTMLElement*pBodyElem;
-
HRTEST_E(GetHTMLDocument2()->get_body(&pBodyElem));
-
-
-
IHTMLElement2*pBodyElement2;
-
HRTEST_E(pBodyElem->QueryInterface(IID_IHTMLElement2,(void**)&pBodyElement2));
-
longiScrollWidth=0;
-
HRTEST_E(pBodyElement2->get_scrollWidth(&iScrollWidth));
-
longiScrollHeight=0;
-
HRTEST_E(pBodyElement2->get_scrollHeight(&iScrollHeight));
-
-
RECTrc={0,0,iScrollWidth,iScrollHeight};
-
::SetWindowPos(GetHWND(),NULL,0,0,iScrollWidth,iScrollHeight,SWP_NOREDRAW);
-
SetWebRect(&rc);
-
-
HBITMAPhBitmap=::CreateCompatibleBitmap(GetDC(GetHWND()),RECTWIDTH(rc),RECTHEIGHT(rc));
-
HDChBitmapDC=::CreateCompatibleDC(GetDC(GetHWND()));
-
::SelectObject(hBitmapDC,hBitmap);
-
-
-
RECTLrctl={rc.left,rc.top,rc.right,rc.bottom};
-
-
-
HRTEST_E(pViewObject2->Draw(DVASPECT_CONTENT,1,NULL,NULL,::GetDC(GetHWND()),hBitmapDC,&rctl,NULL,NULL,0));
-
-
BITMAPstBitmap;
-
PBYTEnpData;
-
DWORDdwDataSize;
-
DWORDdwBmpDataSize;
-
HANDLEhBmpFile;
-
DWORDdwWritten;
-
NULLTEST_E(::GetObjectW(hBitmap,sizeof(stBitmap),(PVOID)&stBitmap));
-
NULLTEST_E(npData=
-
newBYTE[dwDataSize=(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(dwBmpDataSize=((stBitmap.bmWidth*8+31)/32)*4*stBitmap.bmHeight*3))]);
-
-
BITMAPFILEHEADER*pBmpFileHeader=(BITMAPFILEHEADER*)(npData);
-
pBmpFileHeader->bfType=0x4D42;
-
pBmpFileHeader->bfSize=dwDataSize;
-
pBmpFileHeader->bfReserved1=0;
-
pBmpFileHeader->bfReserved2=0;
-
pBmpFileHeader->bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+0;
-
BITMAPINFOHEADER*pBmpInfoHeader=(BITMAPINFOHEADER*)(npData+sizeof(BITMAPFILEHEADER));
-
pBmpInfoHeader->biSize=sizeof(BITMAPINFOHEADER);
-
pBmpInfoHeader->biWidth=stBitmap.bmWidth;
-
pBmpInfoHeader->biHeight=stBitmap.bmHeight;
-
pBmpInfoHeader->biPlanes=1;
-
pBmpInfoHeader->biBitCount=24;
-
pBmpInfoHeader->biCompression=BI_RGB;
-
pBmpInfoHeader->biSizeImage=0;
-
pBmpInfoHeader->biXPelsPerMeter=0;
-
pBmpInfoHeader->biYPelsPerMeter=0;
-
pBmpInfoHeader->biClrUsed=0;
-
pBmpInfoHeader->biClrImportant=0;
-
NULLTEST_E(::GetDIBits(hBitmapDC,hBitmap,0,stBitmap.bmHeight,npData+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER),(BITMAPINFO*)(npData+sizeof(BITMAPFILEHEADER)),DIB_RGB_COLORS));
-
-
-
VALUETEST_E(hBmpFile=::CreateFileW(L"e://test.bmp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL),INVALID_HANDLE_VALUE);
-
FALSETEST_E(::WriteFile(hBmpFile,npData,dwDataSize,&dwWritten,NULL));
-
::CloseHandle(hBmpFile);
-
-
RETURN:
-
DeleteArray(npwNewBmpFilePath);
-
return;
-
}
-
HRESULT
-
CShadowWebWindow::GetHostInfo(DOCHOSTUIINFO*pInfo)
-
{
-
pInfo->cbSize=sizeof(DOCHOSTUIINFO);
-
pInfo->dwFlags=DOCHOSTUIFLAG_DIALOG|
-
DOCHOSTUIFLAG_THEME|
-
DOCHOSTUIFLAG_NO3DBORDER|
-
DOCHOSTUIFLAG_SCROLL_NO;
-
returnS_OK;
-
}
至此,我们已经实现了网页的快照(或者缩略图). 完全可以媲美Chrome的实现. 希望给大家有帮助,我在网上看到的都有这样那样的瑕疵, 在下的实现应该稍微完美一点, 希望对大家有帮助.
如果我的文章对您有帮助,请您留言说说您的感想,这是对我莫大的鼓励,谢谢!
分享到:
相关推荐
用于获取网页信息!利用WebBrowser获取网页信息
C# WebBrowser获取网页截图 调用WebBrowser.DrawImage
使用webbrowser控件分析网页指定id的信息,简单的网络爬虫
Webbrowser1获取网页源码,实例
WebBrowser实现编辑网页
c# WebBrowser_网页操作
使用webBrowser采集网页数据,对一些需要登录,或有验证的,可以在webBrowser控件中手动登录或验证后,在开始批量采集
这是一个通过webbrowser打开百度并控制搜索内容的MFC小项目。其它网页控制大同小异,可以做为参考。VS2015项目。
用VC获得webbrowser中的网页代码(包括dhtml及ajax变动后的)
webBrowser 网页放大缩小 开发浏览器
vb利用IHTMLElementCollection与WebBrowser获得网页表格内容 代码完整
本人写了个用C# 导出网页上的图片小项目 只要输入网址就可以导出网页上的图片了 有兴趣的可以看看。
有时需要对网页进行操作,但webbrowser控件却为完成装载,即可用此函数检测
采用WebBrowser伪装成浏览器访问,绕过了反爬虫程序,获取一个目标网页的数据
1,在项目中引用程序集拓展中的Microsoft.mshtml后,可以在公共控件中找到WebBrowser控件。 2,在窗体中加入三个按钮,然后添加WebBrowser控件,右键控件选属性,设置相应的属性。 3,设置WebBrowser控件的属性 ...
C#_WebBrowser_网页操作 1.获取frame的源文件 2.获取frame的HTMLDocument接口 3.获取frame的IHTMLDocument2接口 4.取得frame中被点击的连接 C# 通过webBrowser 框架网页 C#:webBrowser1控件通过TagName,Name查找...
[网络]WebBrowser网页操作(提取元素,自动填表)
获取页面文本的程序,不是页面的源代码哦!!!!!!!!!!!!!!!!!!!
解决了webbrowser下载文件的三个问题: 1、屏蔽了另存为的弹出 2、获得webbrowser所有的cookie值 3、让webclient支持cookie