Вопрос по rendering, winapi – Как сделать WebBrowser для контекста устройства?

9

я хочу сделать веб-страницу (т.е.TWebBrowser) к контексту устройства. я хочу использовать механизм компоновки Internet Explorer для рендеринга контента в контекст устройства (т. е. метафайл, метафайл pdf).

Начиная с Internet Explorer 9 theIHTMLElementRender интерфейс больше не Поддерживается:

IHTMLElementRender interface

Используйте этот интерфейс для рисования содержимого элемента в указанном контексте устройства, обычно в принтере.

Пользователи
The IHTMLElementRender интерфейс наследуется от IUnknown интерфейс, но не имеет дополнительных членов.

До такой степени, что они больше не упоминают, чтоDrawToDC метод даже существует:

IHTMLElementRender :: Метод DrawToDC

Deprecated. Рисует содержимое элемента в указанном контексте устройства.

Синтакси

HRESULT DrawToDC(
     HDC hDC
);

Параметры

HDC
[in] An HDC с указанием устройства, к которому нужно обращаться, обычно это принтер.

Возврат стоимости

Возвращает S_OK в случае успеха или значение ошибки в противном случае.

Примечания

В Windows Internet Explorer 9 этот метод устарел и не должен использоваться.

С некоторыми принтерами, работающимиIHTMLElementRender :: DrawToDC может вызвать проблемы. Вы можете убедиться, чтоIHTMLElementRender :: DrawToDC правильно работает на всех принтерах, запустивIHTMLElementRender :: SetDocumentPrinterначала метод @, а затем передача измененного контекста устройства вIHTMLElementRender :: DrawToDC.

Заметк: Я цитирую всю документацию, чтобы ее можно было найти, когда Microsoft окончательно удалит ее из MSDN. Вместе с объявлением интерфейса:

IHTMLElementRender = interface(IUnknown)
   ['{3050F669-98B5-11CF-BB82-00AA00BDCE0B}']
   function DrawToDC(hdc: HDC): HResult; stdcall;
   function SetDocumentPrinter(const bstrPrinterName: WideString; hdc: HDC): HResult; stdcall;
end;
ИспользоватьIViewObject интерфейс

Я пытался конвертировать, чтобы использоватьIViewObject (например, Как отобразить HTML-элемент без использования веб-браузера?):

procedure RenderWebBrowserToMetafile(Browser: TWebBrowser; Metafilename: string);
var
    view: IViewObject;
    m: TMetafile;
    mc: TMetafileCanvas;
    w, h: Integer;
    r: TRect;
    dpix: Integer;
    dpiy: Integer;
    dc: HDC;
begin
    w := WebBrowserScrollWidth(Browser);
    h := WebBrowserScrollHeightStrict(Browser);

    //96dpi screen to 300dpi metafile (destined for printer)
    dc := GetDC(0);
    try
        dpix := GetDeviceCaps(GetDC(0), LOGPIXELSX);
        dpiy := GetDeviceCaps(GetDC(0), LOGPIXELSY);
    finally
        ReleaseDC(0, dc);
    end;
    w := MulDiv(w, 300, dpix);
    h := MulDiv(h, 300, dpiy);

    view := Browser.Document as IViewObject;

    m := TMetafile.Create;
    try
        m.Width := w;
        m.Height := h;
        r := Rect(0, 0, w, h);

        mc := TMetafileCanvas.Create(m, 0);
        try
            view.Draw(
                    DVASPECT_CONTENT, //draw aspect
                    1, //index
                    nil, //pAspectInfo
                    nil, //pDVTargetDevice
                    0, //Target Device Context
                    mc.handle, //hdcDraw
                    @r, //target Bounds
                    @w, //window bounds (for metafiles)
                    nil, //continue function
                    0); //continue value
        finally
            mc.Free;
        end;
        m.SaveToFile(Metafilename);
    finally
        m.Free;
    end;
end;

Проблема с этим кодом в том, что он отображает только Видимым область браузера (т.е. без прокручиваемого содержимого):

мне нужно сделать Весь веб-страница (например, для печати).

я пытался изменить рисовать аспект отDVASPECT_CONTENT (как этот пример делает), чтобыDVASPECT_DOCPRINT:

DVASPECT_DOCPRINT
Предоставляет представление объекта на экране, как если бы оно было напечатано на принтере с помощью команды «Печать» из меню «Файл». Описанные данные могут представлять собой последовательность страниц.

С таким же результатом; вместо отображения страницы отображается только видимая часть:

Как я могу попросить рендеринг движка IE9?

я также пытался использовать разные Индексы вместе сDVASPECT_DOCPRINT. ХотяIViewObject не документировано, может быть, так вы печатаете разные "Страница":

view.Draw(DVASPECT_DOCPRINT, 1, ...);
view.Draw(DVASPECT_DOCPRINT, 2, ...);
view.Draw(DVASPECT_DOCPRINT, 3, ...);
...
view.Draw(DVASPECT_DOCPRINT, n, ...);

Но веб-браузеру все равно, что это за индекс; только рендеринг текущегоView (что, я думаю, имеет смысл при использованииIViewObject).

Как отобразить браузер в контексте устройства?

Заметк: Вопрос помечен какdelphi, но в этом вопросе нет ничего, что было бы Дельфи конкретный

Обновит: я также пробовал другие комбинации Аспект а такжепоказател:

view.Draw(DVASPECT_CONTENT, -1, ...);
view.Draw(DVASPECT_DOCPRINT, -1, ...);
view.Draw(DVASPECT_CONTENT, 0, ...);
view.Draw(DVASPECT_DOCPRINT, 0, ...);
@ Ян, похоже, вы не можете получить полный контент без изменения размера браузера, как упомянул TOndrej. Кстати, вы можете захотеть включить поля слева, справа, сверху и снизу в ваши расчеты ширины и высоты. Hendra
TOndrej В этом случае браузер (элемент управления) выровнен / прикреплен к клиентской форме, которая ограничена размером монитора пользователя. Как и сам Internet Explorer. Поэтому мне интересно, как Internet Explorer справляется сPrint. Ian Boyd
@ TOndrej Изменение размера элемента управления браузером может работать в некоторых случаях, в других это может привести к неожиданным результатам, поскольку содержимое HTML может изменить свою компоновку, если вы измените размер самого элемента управления браузером. iamjoosy
Возможно, вы сможете создать временный невидимый элемент управления браузера и скопировать в него содержимое, или повторно использовать существующий элемент управления и попробовать такие хитрости, как WM_SETREDRAW, LockWindowUpdate, чтобы избежать видимых эффектов. Ondrej Kelle
Согласно сэт, вы на правильном пути и вам нужно изменить размер элемента управления браузера (временно). Не проверено Ondrej Kelle

Ваш Ответ

1   ответ
1

вы можете создать скриншот текущего видового экрана. Я использую трюк для создания скриншота веб-страницы (без каких-либо рамок) или документа рамок.

Рассчитайте полный размер документа с помощью scrollWidth / scrollHeight / scrollLeft / scrollTop (проверьте интерфейсы IHtmlDocument2 и IHtmlDocument3) Обновление окна блокировки и корректировка документа до рассчитанного полного размера Используйте IViewObject для создания снимка (ваш код выглядит нормально) Восстановите документ до его исходного размера и разблокируйте обновление окна

Обратите внимание, чт вы должны быть осторожны, когда документ очень большой.

Второй параметр 'index' в IViewObject.Draw (..) выглядит нормально. Я боюсь, что вы не можете создать полноразмерный снимок документа, используя любой API напрямую. stanleyxu2005

Похожие вопросы