对IE进行编程一直觉得是相当可怕的事情,里面的接口、函数、事件之多,解释之乱,需要了解的方方面面知识之博,让我仿佛看到了微软就是造物主,因为它已成功制造了这样的混沌,弄就了宇宙的初始状态……
近来做个项目,要截取网页,试了获取mht,开始倒是成功了,但不知装了什么软件后,就再也无法保存成mht了,查了一堆资料,修复了一轮,又可以部份保存成功,如此不稳定肯定不能应用,放弃!不得不赞的是,网文快捕的保存网页的插件的确是精品,成功率很高,不知在后面作者做了多少工作,可惜作者没有作为接口提供。于是决定还是截网页为图片,同时获取其中文字保存用于查询的方式,经过几日无数查找资料尝试,在终于崩溃之前,玉帝可怜我,终于让我成功,一直以来从网上众人文章中获益良多,赶快贴出来给不知多少像我这样可怜的人。
首先,声名使用到的文件:
uses ComObj,shDocvw,MSHtml,OleCtrls,jpeg,ActiveX;
TObjectFromLResult = function (LRESULT: lResult; const IID: TIID;WPARAM: wParam; out pObject): HRESULT; stdcall;
function PrintWindow(SourceWindow: hwnd; Destination: hdc; nFlags: cardinal): bool; stdcall; external ' user32.dll ' name ' PrintWindow ' ;
// 获取IE实例,wHandle为IE的句柄,这段代码网上抄来,向作者致谢!
// wHandle可通过WindowFromPoint(GetCursorPos(pt))获得,获取的办
// 法网上一搜一大堆了。
function GetIEFromHWND(wHandle: HWND; var IE: IWebbrowser2): HRESULT;
var
hInst: HWND;
lRes: Cardinal;
MSG: Integer;
pDoc: IHTMLDocument2;
ObjectFromLresult: TObjectFromLresult;
begin
hInst : = LoadLibrary( ' Oleacc.dll ' );
@ObjectFromLresult : = GetProcAddress(hInst, ' ObjectFromLresult ' );
if @ObjectFromLresult <> nil then
begin
try
MSG : = RegisterWindowMessage( ' WM_HTML_GETOBJECT ' );
SendMessageTimeOut(WHandle, MSG, 0 , 0 , SMTO_ABORTIFHUNG, 1000 , lRes);
Result : = ObjectFromLresult(lRes, IHTMLDocument2, 0 , pDoc);
if Result = S_OK then
(pDoc.parentWindow as IServiceprovider).QueryService(IWebbrowserApp,
IWebbrowser2, IE);
finally
FreeLibrary(hInst);
pDoc : = nil ;
end ;
end ;
end ;
{ 指定IE窗口句柄,滚动获取整个网页图片
此函数执行完后能把IE原来滚动条位置复原,听起来这事很简单,爷找资料却是找到傻了云!如果网页有D3D这种东东的话,网上说的getAttribute('scrollTop', 0)什么的就用不了,混乱!混乱啊!
看了在下这文而受益的同学,不要忘了来感谢下啊,我也弄得很辛苦的。
}
procedure SaveWebPic(hIEHandle: Integer; webJpg: TJPEGImage);
var
rect: TRect;
webBmp: TBitMap;
i, j, webTop, webLeft, tLeft, tTop: integer;
ht, vt: array of Integer;
ie: IWebbrowser2;
iDoc: IHTMLDocument2;
vElement: IHTMLElement2;
procedure CaptureWeb(destBmp: TBitmap; destLeft, destTop, width, height: Integer);
var
temBmp: TBitmap;
begin
temBmp : = TBitMap.Create();
temBmp.Height : = height + 2 ;
temBmp.Width : = width + 2 ;
PrintWindow(hIEHandle, temBmp.Canvas.Handle, 0 );
BitBlt(destBmp.Canvas.Handle, destLeft, destTop, destLeft + width, destTop + height, temBmp.Canvas.Handle, 2 , 2 , SRCCOPY);
temBmp.Free;
end ;
begin
if not Assigned(webJpg) then
Exit;
if GetIEFromHWND(hIEHandle, ie) <> S_OK then
Exit;
iDoc : = ie.Document as IHTMLDocument2;
webBmp : = TBitMap.Create();
webBmp.PixelFormat : = pf24bit;
try
// temCanvas.Handle : = GetDC(hIEHandle);
iDoc.body.setAttribute( ' scroll ' , ' yes ' , 0 );
// 保存原来滚动条位置
vElement : = (iDoc as IHTMLDocument3).documentElement as IHTMLElement2;
if not Assigned(vElement) then
vElement : = iDoc.Body as IHTMLElement2;
tTop : = vElement.scrollTop;
tLeft : = vElement.scrollLeft;
// 获得网页的大小
webBmp.Height : = vElement.scrollHeight; // iDoc.Body.getAttribute( ' scrollHeight ' , 0 );
webBmp.Width : = vElement.scrollWidth; // iDoc.Body.getAttribute( ' scrollwidth ' , 0 );
// 获得显示网页的窗口大小
// windows.GetClientRect(hIEHandle, rect);
// rect.Bottom : = rect.Bottom - GetSystemMetrics(SM_CXHSCROLL) - GetSystemMetrics(SM_CXDLGFRAME);
// rect.Right : = rect.Right - GetSystemMetrics(SM_CXVSCROLL) - GetSystemMetrics(SM_CXDLGFRAME);
rect.Right : = vElement.clientWidth;
rect.Bottom : = vElement.clientHeight;
// 计算纵向和横向每次截取时,截取的高度、宽度
// 网页的截取办法是去零传凑整,如窗口的高度是H,而网页的高度是WH,可先
// 截取WH - H部份,剩下通过循环按H截取
SetLength(vt, webBmp.Height div rect.Bottom + 1 );
SetLength(ht, webBmp.Width div rect.Right + 1 );
vt[ 0 ] : = webBmp.Height - (webBmp.Height div rect.Bottom) * rect.Bottom;
ht[ 0 ] : = webBmp.Width - (webBmp.Width div rect.Right) * rect.Right;
for i: = 1 to Length(vt) - 1 do
vt[i] : = rect.Bottom;
for i: = 1 to Length(ht) - 1 do
ht[i] : = rect.Right;
webLeft : = 0 ;
for i: = 0 to Length(ht) - 1 do begin
webTop : = 0 ;
iDoc.Get_ParentWindow.Scroll(webLeft, webTop);
for j: = 0 to Length(vt) - 1 do begin
CaptureWeb(webBmp, webLeft, webTop, ht[i], vt[j]);
webTop : = webTop + vt[j];
iDoc.Get_ParentWindow.Scroll(webLeft, webTop);
end ;
webLeft : = webLeft + ht[i];
end ;
webJpg.Assign(webBmp);
webJpg.SaveToFile( ' z:\demo.jpg ' );
finally
webBmp.Free;
SetLength(vt, 0 );
SetLength(ht, 0 );
iDoc.Get_ParentWindow.Scroll(tLeft, tTop);
end ;
end ;