Задачка такая: запускаем из кода IE в нем открывается page c некоторым контентом.
Надо програмно снять скриншот содержимого страницы, ну и получить на выходе,
например bmp.
Как это можно сделать и какие api для для такой задачи можно заюзать?
Здравствуйте, vladt, Вы писали:
V>Доброе время суток.
V>Задачка такая: запускаем из кода IE в нем открывается page c некоторым контентом. V>Надо програмно снять скриншот содержимого страницы, ну и получить на выходе, V>например bmp. V>Как это можно сделать и какие api для для такой задачи можно заюзать?
V>best regards, V>Vladimir
Есть такая прога, но не помню как она называется.
Насколько я заметил, она программно скролирует страницу, делает (видимо) частичные скриншоты, а потом обединяет их в один.
V>Задачка такая: запускаем из кода IE в нем открывается page c некоторым контентом. V>Надо програмно снять скриншот содержимого страницы, ну и получить на выходе, V>например bmp. V>Как это можно сделать и какие api для для такой задачи можно заюзать?
MSDN, интерфейс IViewObject
То ли WebBrowser2, то ли HtmlDocument поддерживают этот интерфейс. Предназначен для print preview и т.п.
Насколько это будет стабильно, еще не понятно
Вот, что пишут в Msdn по этому поводу:
QueryInterface for IViewObject, and finally call IViewObject::Draw to render the content to a device-independent bitmap (DIB) section.
this technique falls into unsupported territory. The problem is that the product is really not designed or tested to support custom drawing via IViewObject::Draw. IViewObject::Draw is a generic ActiveX control interface that is only intended to allow a container that is directly hosting the control to ask that control to draw itself. Here we are using this interface to ask the control to draw itself into some other location. Therefore, it is possible that this technique will not work properly in future versions of Internet Explorer due to drawing optimizations or other modifications made to the product at a later date. In fact, since the WebBrowser control is a windowed control, it normally handles its own painting when hosted in a container without using IViewObject::Draw at all.
> То ли WebBrowser2, то ли HtmlDocument поддерживают этот интерфейс. Предназначен для print preview и т.п.
V>Насколько это будет стабильно, еще не понятно V>Вот, что пишут в Msdn по этому поводу:
V>QueryInterface for IViewObject, and finally call IViewObject::Draw to render the content to a device-independent bitmap (DIB) section.
MS похоже забила на Internet Explorer, новые версии содержат только минорные апдейты и фиксы, в основном секьюрити. Почит во всём, что касатеся MSHTML, царит полный бардак (нереализованные или неполностью реализованные интерфейсы, неработают некоторые документированные фичи и т.д.), там вообще ни на что рассчитывать нельзя Работает — используй...
Re: IE window Bitmap screenshot
От:
Аноним
Дата:
20.04.05 06:49
Оценка:
Здравствуйте, vladt, Вы писали:
V>Доброе время суток. V>Задачка такая: запускаем из кода IE в нем открывается page c некоторым контентом. V>Надо програмно снять скриншот содержимого страницы, ну и получить на выходе, V>например bmp. V>Как это можно сделать и какие api для для такой задачи можно заюзать?
Примерно так (по-моему нашел на рсдне, и переписал на паскаль )
// vim: foldmethod=marker : foldmarker=<<<,>>>
{
File: html2gif.pas
Product: <product>
Creating date: 08/11/2004 21:33
Remark:
}program html2gif;
uses
classes, sysUtils, Forms, mshtml, ActiveX, OleCtrls, SHDocVw, windows,
messages, Graphics, Controls;
{$APPTYPE CONSOLE}
{$R html2gif.dfm}const
WM_START=WM_USER+101;
WM_CONVERT=WM_USER+102;
WM_STOP=WM_USER+103;
type
TMainWindow = class(TForm)
FBrowser: TWebBrowser;
private
FUrl:string;
FImagePath:string;
FImageWidth:integer;
procedure DocumentComplete(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant);
procedure WMStart(var Message: TMessage); message WM_START;
procedure WMConvert(var Message: TMessage); message WM_CONVERT;
procedure WMStop(var Message: TMessage); message WM_STOP;
protected
procedure CreateParams(var Params: TCreateParams); override;
public
property Url:string read FUrl write FUrl;
property ImagePath:string read FImagePath write FImagePath;
property ImageWidth:integer read FImageWidth write FImageWidth;
procedure Commence;
end;
procedure TMainWindow.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
// Params.Style:=Params.Style or WS_POPUP;
Params.ExStyle:=Params.ExStyle or WS_EX_TOOLWINDOW;
end;
procedure TMainWindow.DocumentComplete(Sender: TObject; const pDisp: IDispatch; var URL: OleVariant);
var
wb:IWebBrowser2;
begin
wb:=FBrowser.ControlInterface;
{ writeln(URL); writeln(wb.ReadyState,' ',wb.Busy);}if wb.ReadyState=4 then begin
writeln(' done.');
FBrowser.OnDocumentComplete:=nil;
PostMessage(Handle,WM_CONVERT,0,0);
end;
end;
procedure TMainWindow.Commence;
begin
PostMessage(Handle,WM_START,0,0);
end;
procedure TMainWindow.WMStart(var Message: TMessage);
begin
writeln('Loading ...');
FBrowser.OnDocumentComplete:=DocumentComplete;
FBrowser.Navigate(FUrl);
end;
procedure TMainWindow.WMConvert(var Message: TMessage);
var
wb:IWebBrowser2;
htmlDocument:IHTMLDocument2;
htmlBody:IHTMLElement;
htmlBody2:IHTMLElement2;
htmlStyle:IHTMLStyle;
viewObject:IViewObject;
sourceDrawRect:TRect;
bm:TBitmap;
begin
writeln('Converting ...');
wb:=FBrowser.ControlInterface;
htmlDocument:=wb.Document As IHTMLDocument2;
htmlBody:=htmlDocument.Body As IHTMLElement;
htmlStyle:=htmlBody.style;
htmlStyle.overflow:='hidden'; htmlStyle.borderStyle:='none';
htmlBody2:=htmlDocument.Body As IHTMLElement2;
wb.Width:=FImageWidth; wb.Height:=htmlBody2.scrollHeight;
bm:=TBitmap.Create;
bm.Width:=wb.Width; bm.Height:=wb.Height;
sourceDrawRect:=Rect(0,0,bm.Width,bm.height);
viewObject := wb as IViewObject;
viewObject.Draw(DVASPECT_DOCPRINT,1,nil,nil
,0,bm.Canvas.Handle, @sourceDrawRect
,nil,nil,0);
bm.SaveToFile(FImagePath);
writeln(' done.');
PostMessage(Handle,WM_STOP,0,0);
end;
procedure TMainWindow.WMStop(var Message: TMessage);
begin
Close();
end;
procedure main;
var
mw: TMainWindow;
begin
if (paramCount<>3) then begin
writeln('Usage: html2bmp.exe url_or_fullpath_to_file bmp_name bmp_width');
ExitProcess(0);
end;
{
mw.Url='E:\html2gif\test.html';
mw.Url:='http://www.voip-info.org/wiki-Asterisk';
mw.ImagePath:='Snapshot.bmp';
mw.ImageWidth:=700;
}
Application.Initialize;
Application.CreateForm(TMainWindow,mw);
mw.Url:=paramStr(1);
mw.ImagePath:=paramStr(2);
try
mw.ImageWidth:=strToInt(paramStr(3));
except
writeln('bmp_width is not a integer');
ExitProcess(0);
end;
mw.Commence;
Application.Run;
end;
begin main; end.
Вообщем заработало, все правильно оказывается нужно было не CreateCompatibleBitmap,
а CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void**)&dibvalues,0,0);
SelectObject и BitBit тогда получаем bmp нормально.
По ходу возникла другая трабла — bmp снимается не с окна броузера!
Хотя эта строчка hresult = pBrowser->get_HWND(&hwnd)
возвращает валидный hwnd именно окна IE !!!!! И дальше работаю только с этим хендлом
В чем грабли ?
V>Вообщем заработало, все правильно оказывается нужно было не CreateCompatibleBitmap, V>а CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void**)&dibvalues,0,0); V>SelectObject и BitBit тогда получаем bmp нормально.
V>По ходу возникла другая трабла — bmp снимается не с окна броузера! V>Хотя эта строчка hresult = pBrowser->get_HWND(&hwnd) V>возвращает валидный hwnd именно окна IE !!!!! И дальше работаю только с этим хендлом V>В чем грабли ?
На самом деле скриншот во всех известных версиях винды снимался всегда с экрана Т.е. над окном что-то есть, кусок этого что-то окажется на снятом изображении. Можно либо временно вытащить окно поверх остальных, либо попробовать-таки распечатать его через IViewObject
Методом вытаскивания — не очень получается, берет все равно не ту область.
Пробую сделать по науке получить IHtmlElement и у него взять IHtmlElementRender, который уже может отрисовать нужный нам контент окна методом DrawToDC.
Однако и здесь засада, получить IHtmlElementRender путем
pElement->QueryInterface(IID_IHTMLElementRender, (void**) &pDisp); не получается ибо E_NOINTERFACE error !!!! Спрашивается и гиде он подевался?
Вот такие вот будни Win программерства
>либо попробовать-таки распечатать его через IViewObject