Размеры IHTMLWindow2
От: Aniskin  
Дата: 06.10.07 22:25
Оценка:
Возникла задача сохранить содержимое html-страницы, открытой в MS Explorer, в виде графического файла. Снять с экрана копию не проблема. Но размер html-страницы может превышать размер клиентской части окна. Соответственно, сохранять нужно поэтапно, скроллингуя клиентскую часть окна. Для этого с помощью WM_HTML_GETOBJECT получаю интерфейс IHTMLDocument2, а из него IHTMLWindow2, в котором есть метод scrollBy. Но как мне узнать размеры html-страницы для определения необходимого количества итераций.
Re: Размеры IHTMLWindow2
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 07.10.07 08:23
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>Возникла задача сохранить содержимое html-страницы, открытой в MS Explorer, в виде графического файла. Снять с экрана копию не проблема. Но размер html-страницы может превышать размер клиентской части окна. Соответственно, сохранять нужно поэтапно, скроллингуя клиентскую часть окна. Для этого с помощью WM_HTML_GETOBJECT получаю интерфейс IHTMLDocument2, а из него IHTMLWindow2, в котором есть метод scrollBy. Но как мне узнать размеры html-страницы для определения необходимого количества итераций.


Юзать IViewObject::Draw.
... << RSDN@Home 1.1.4 beta 7 rev. 452>>
Re: Размеры IHTMLWindow2
От: goto Россия  
Дата: 07.10.07 14:19
Оценка:
Попадалось на codeproject.com. Можно найти по строке "capture screen".
Re[2]: Размеры IHTMLWindow2
От: Aniskin  
Дата: 07.10.07 14:59
Оценка:
Здравствуйте, Flamer, Вы писали:


F>Юзать IViewObject::Draw.


Спасибо за совет. Провел эксперименты с WebBroser, получая IViewObject у WebBrowser1.Document – все работает прекрасно. Но в случае, когда я имею только хендл окна, не получается. Пожалуйста, укажите на ошибку.

procedure SaveExplorerCaptureFile(AWin: THandle; const AFileName: string);
var Doc: IHTMLDocument2;
    Body: IHTMLElement;
    Body2: IHTMLElement2;
    BodyElement: IHTMLBodyElement;
    W, H: Integer;
    ViewObject: IViewObject;
    DC: HDC;
    R: TRect;
    SaveBorderStyle: WideString;
    SaveScroll: WideString;
    B: TBitmap;
begin
  OleCheck(GetIDocFromHWND(AWin, Doc));
  Body := Doc.body;
  if not Assigned(Body) then raise Exception.Create('Empty body');
  OleCheck(Body.QueryInterface(IHTMLElement2, Body2));
  W := Body2.scrollWidth;
  H := Body2.scrollHeight;
  if (W = 0) or (H = 0) then raise Exception.Create('Empty content');
  OleCheck(Body.QueryInterface(IHTMLBodyElement, BodyElement));
  // Там ли я беру IViewObject?
  OleCheck(Doc.QueryInterface(IViewObject, ViewObject));
  SaveBorderStyle := Body.style.borderStyle;
  Body.style.borderStyle := 'none';
  SaveScroll := BodyElement.scroll;
  BodyElement.scroll := 'no';
  // Еще не плохо было бы установить
  // WebBrowser.Width := Body2.scrollWidth;
  // WebBrowser.Height := Body2.scrollHeight;
  // но где взять IWebBrowser?
  // Или использовать SetWindowPos(AWin, 0, 0, 0, W, H, SWP_NOZORDER or SWP_NOMOVE or
  //   SWP_NOACTIVATE or SWP_NOCOPYBITS or SWP_NOREDRAW or SWP_NOSENDCHANGING or SWP_NOOWNERZORDER)
  B := TBitmap.Create;
  try
    B.Width := W;
    B.Height := H;
    DC := GetDC(0);
    try
      R := Rect(0, 0, B.Width, B.Height);
      OleCheck(ViewObject.Draw(DVASPECT_CONTENT, 1, nil, nil,
        DC, B.Canvas.Handle, @R, nil, nil, 0));
      B.SaveToFile(AFileName);
    finally
      ReleaseDC(0, DC);
    end;
  finally
    B.Free;
    Body.style.borderStyle := SaveBorderStyle;
    BodyElement.scroll := SaveScroll;
  end;
end
Re[3]: Размеры IHTMLWindow2
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 07.10.07 15:13
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>Здравствуйте, Flamer, Вы писали:



F>>Юзать IViewObject::Draw.


A>Спасибо за совет. Провел эксперименты с WebBroser, получая IViewObject у WebBrowser1.Document – все работает прекрасно. Но в случае, когда я имею только хендл окна, не получается. Пожалуйста, укажите на ошибку.


Ошибка в невнимательном чтении MSDN:

Unlike most other interfaces, IViewObject cannot be marshaled to another process. This is because device contexts are only effective in the context of one process.

<< Если ты не являешься частью решения, то ты являешься частью проблемы. >>
Re[4]: Размеры IHTMLWindow2
От: Aniskin  
Дата: 07.10.07 16:46
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Ошибка в невнимательном чтении MSDN:


F>

F>Unlike most other interfaces, IViewObject cannot be marshaled to another process. This is because device contexts are only effective in the context of one process.


То есть мне нужно внедрятся в чужой процесс? Как это лучше сделать? Глобальным хуком?
Re[5]: Размеры IHTMLWindow2
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 07.10.07 18:43
Оценка:
Здравствуйте, Aniskin, Вы писали:

F>>

F>>Unlike most other interfaces, IViewObject cannot be marshaled to another process. This is because device contexts are only effective in the context of one process.


A>То есть мне нужно внедрятся в чужой процесс? Как это лучше сделать? Глобальным хуком?


Можно глобальным хуком, можно CreateRemoteTread, есть еще несколько способов. На сайте есть статьи по этой теме, плюс можно Рихтера почитать.

Еще мысль пришла: раз уж все равно IE юзается — написать BHO, потом куданить в шарную область или через named pipe слать команду: мол, нуна снять скрин для этого HWND. BHO смотрит, а не является ли переданный HWND дескриптором окна браузера, в котором ему вызвали SetSite, и если да, то делает черную работу и рапортует о результатах. Имхо самый простой в реализации метод, хотя и не без недостатков.
<< Самое главное — это деньги, а здоровье приходит и уходит. >>
Re[6]: Размеры IHTMLWindow2
От: Aniskin  
Дата: 08.10.07 18:47
Оценка:
Остается вопрос, как заполучить IWebBroser имея IHTMLDocument2 и IHTMLWindow2. Это вообще возможно?
Re[7]: Размеры IHTMLWindow2
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 08.10.07 19:09
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>Остается вопрос, как заполучить IWebBroser имея IHTMLDocument2 и IHTMLWindow2. Это вообще возможно?


В SetSite:

    CComQIPtr<IServiceProvider,&IID_IServiceProvider> pServProv(pUnkSite);
     if(pServProv)
        hr =  pServProv->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2,
         (void**)&m_pWebBrowser2);


pUnkSite — интерфейс, переданный в SetSite. Потом вызываем get_HWND у полученного интерфейса браузера.
<< Люди, не умеющие лгать, являются социально неадаптированными. >>
Re[8]: Размеры IHTMLWindow2
От: Aniskin  
Дата: 08.10.07 19:42
Оценка:
Здравствуйте, Flamer, Вы писали:

F>В SetSite:


F>
F>    CComQIPtr<IServiceProvider,&IID_IServiceProvider> pServProv(pUnkSite);
F>     if(pServProv)
F>        hr =  pServProv->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2,
F>         (void**)&m_pWebBrowser2);

F>


F>pUnkSite — интерфейс, переданный в SetSite. Потом вызываем get_HWND у полученного интерфейса браузера.


Честно говоря, я не понимаю вышенаписнного. Я никогда ранее не работал с интерфейсами Explorer`а, и для меня это темный лес.
Все что у меня есть — это хендл окна и полученные IHTMLDocument2 и IHTMLWindow2. Мне нужно из этого как-нибуть получить IWebBroser. Прямого пути нет?
Re[9]: Размеры IHTMLWindow2
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 08.10.07 20:33
Оценка:
Здравствуйте, Aniskin, Вы писали:

[]

A>Честно говоря, я не понимаю вышенаписнного. Я никогда ранее не работал с интерфейсами Explorer`а, и для меня это темный лес.

A>Все что у меня есть — это хендл окна и полученные IHTMLDocument2 и IHTMLWindow2. Мне нужно из этого как-нибуть получить IWebBroser. Прямого пути нет?

1. Запрашиваете у IHTMLWindow2 интерфейс IServiceProvider c помощью QueryInterface
2. У полученного IServiceProvider запрашиваете интерфейс IWebBrowser2 с помощью QueryService.

Примерно так:

IServiceProvider* pService;
HRESULT hr = pWindow->QueryInterface(IID_IServiceProvider,(void**)&pService);
if(SUCCEEDED(hr))
{
    IWebBrowser2* pBrowser;
    hr = pService->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2,(void**)&pBrowser);
    
    if(SUCCEEDED(hr))
    {
        // получили IWebBrowser2 в pBrowser
    } // if

} // if
<< Деньги не приносят счастья, но вот то, что на них можно купить…. >>
Re[10]: Размеры IHTMLWindow2
От: Aniskin  
Дата: 09.10.07 12:53
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Примерно так:


Благодарю за помощь, все прекрасно работает.
Re[11]: Размеры IHTMLWindow2
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 09.10.07 14:21
Оценка:
Здравствуйте, Aniskin, Вы писали:

[]

A>Благодарю за помощь, все прекрасно работает.


Да не за что
<< Чистая совесть — вернейший симптом склероза. >>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.