IE window Bitmap screenshot
От: vladt  
Дата: 19.04.05 08:37
Оценка:
Доброе время суток.

Задачка такая: запускаем из кода IE в нем открывается page c некоторым контентом.
Надо програмно снять скриншот содержимого страницы, ну и получить на выходе,
например bmp.
Как это можно сделать и какие api для для такой задачи можно заюзать?


best regards,
Vladimir
Posted via RSDN NNTP Server 1.9
Re: IE window Bitmap screenshot
От: BlackHeretic Израиль  
Дата: 19.04.05 09:24
Оценка:
Здравствуйте, vladt, Вы писали:

V>Доброе время суток.


V>Задачка такая: запускаем из кода IE в нем открывается page c некоторым контентом.

V>Надо програмно снять скриншот содержимого страницы, ну и получить на выходе,
V>например bmp.
V>Как это можно сделать и какие api для для такой задачи можно заюзать?


V>best regards,

V>Vladimir

Есть такая прога, но не помню как она называется.
Насколько я заметил, она программно скролирует страницу, делает (видимо) частичные скриншоты, а потом обединяет их в один.
ICQ 156156278
Re: IE window Bitmap screenshot
От: Divineshadow  
Дата: 19.04.05 10:00
Оценка:
Возможно GetDC, BitBlt
Re: IE window Bitmap screenshot
От: Кодёнок  
Дата: 19.04.05 10:58
Оценка:
V>Задачка такая: запускаем из кода IE в нем открывается page c некоторым контентом.
V>Надо програмно снять скриншот содержимого страницы, ну и получить на выходе,
V>например bmp.
V>Как это можно сделать и какие api для для такой задачи можно заюзать?

MSDN, интерфейс IViewObject

То ли WebBrowser2, то ли HtmlDocument поддерживают этот интерфейс. Предназначен для print preview и т.п.
Re[2]: IE window Bitmap screenshot
От: vladt  
Дата: 19.04.05 13:47
Оценка:
Насколько это будет стабильно, еще не понятно
Вот, что пишут в 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 и т.п.
Posted via RSDN NNTP Server 1.9
Re[3]: IE window Bitmap screenshot
От: Кодёнок  
Дата: 19.04.05 13:58
Оценка:
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.
Re[2]: IE window Bitmap screenshot
От: vladt  
Дата: 20.04.05 13:02
Оценка:
Вот, что я делаю:

Создал экземпляр IWebBrowser2 и запустил окно.

long width;
long height;
SHANDLE_PTR hwnd;

pBrowser->get_Width(&width);
pBrowser->get_Height(&height);

//Получаем handle окна
hresult = pBrowser->get_HWND(&hwnd);
HDC dcBrowser = GetDC((HWND)hwnd);
HDC dcCompatible = CreateCompatibleDC(dcBrowser);

HBITMAP pBitMap = CreateCompatibleBitmap(dcBrowser, width, height);
if (pBitMap == 0)
{
printf("failed create bitmap");
}

if (!SelectObject(dcCompatible, pBitMap))
{
printf("compatible bitmap selection");
}

//Копируем содержимое
if (!BitBlt(dcCompatible,
0,0,
width, height,
dcBrowser,
0,0,
SRCCOPY))
{
printf("bitbit failed");
}

BITMAP bm;
GetObject(pBitMap, sizeof(bm), &bm);

в результате получаем в битмапе правильные width и height картинки
но bmBits == NULL ??!! Те ничего не скопировалось.

Что сделал не так?
Posted via RSDN NNTP Server 1.9
Re[3]: IE window Bitmap screenshot
От: Кодёнок  
Дата: 21.04.05 06:17
Оценка:
V>HBITMAP pBitMap = CreateCompatibleBitmap(dcBrowser, width, height);
V>Что сделал не так?

У compatible bitmap биты всегда равны нулю. Используй CreateDIBSection.
Re[4]: IE window Bitmap screenshot
От: vladt  
Дата: 21.04.05 08:40
Оценка:
Вообщем заработало, все правильно оказывается нужно было не CreateCompatibleBitmap,
а CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (void**)&dibvalues,0,0);
SelectObject и BitBit тогда получаем bmp нормально.

По ходу возникла другая трабла — bmp снимается не с окна броузера!
Хотя эта строчка hresult = pBrowser->get_HWND(&hwnd)
возвращает валидный hwnd именно окна IE !!!!! И дальше работаю только с этим хендлом
В чем грабли ?
Posted via RSDN NNTP Server 1.9
Re[5]: IE window Bitmap screenshot
От: Кодёнок  
Дата: 21.04.05 09:04
Оценка:
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
Re[6]: IE window Bitmap screenshot
От: vladt  
Дата: 21.04.05 16:30
Оценка:
Методом вытаскивания — не очень получается, берет все равно не ту область.
Пробую сделать по науке получить IHtmlElement и у него взять IHtmlElementRender, который уже может отрисовать нужный нам контент окна методом DrawToDC.
Однако и здесь засада, получить IHtmlElementRender путем
pElement->QueryInterface(IID_IHTMLElementRender, (void**) &pDisp); не получается ибо E_NOINTERFACE error !!!! Спрашивается и гиде он подевался?
Вот такие вот будни Win программерства

>либо попробовать-таки распечатать его через IViewObject
Posted via RSDN NNTP Server 1.9
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.