Как отображать WebBrowser в контексте устройства?

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


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

Интерфейс IHTMLElementRender

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

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

Вплоть до того, что они больше не упоминают, что метод DrawToDCвообще существует:

Метод IHTMLElementRender::DrawToDC

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

Синтаксис

HRESULT DrawToDC(
HDC HDC
);

Параметры

  • hDC
    [in] 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, но в этом вопросе нет ничего, что было бы специфично для delphi.


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

view.Draw(DVASPECT_CONTENT, -1, ...);
view.Draw(DVASPECT_DOCPRINT, -1, ...);
view.Draw(DVASPECT_CONTENT, 0, ...);
view.Draw(DVASPECT_DOCPRINT, 0, ...);

9
задан Community 23 May 2017 в 02:24
поделиться