Jak renderować WebBrowser w kontekście urządzenia?

chcę renderować stronę internetową (tj.TWebBrowser) do kontekstu urządzenia. Chcę użyć silnika układu Internet Explorer do renderowania treści do kontekstu urządzenia (np. metaplik, metaplik pdf).

Począwszy od Internet Explorer 9 theIHTMLElementRender interfejs już nie istniejeutrzymany:

Interfejs IHTMLElementRender

Użyj tego interfejsu, aby narysować zawartość elementu do określonego kontekstu urządzenia, zwykle drukarki.

Członkowie
TheIHTMLElementRender interfejs dziedziczy zNie wiem interfejs, ale nie ma dodatkowych członków.

Do tego stopnia, że ​​nie wspominają już, żeMetoda DrawToDC nawet istnieje:

Metoda IHTMLElementRender :: DrawToDC

Przestarzałe. Rysuje zawartość elementu do określonego kontekstu urządzenia.

Składnia

HRESULT DrawToDC(
     HDC hDC
);

Parametry

hDC
[w] AnHDC określenie urządzenia, na które ma być pobierane, zazwyczaj drukarki.

Wartość zwrotna

Zwraca S_OK, jeśli się powiedzie, lub wartość błędu w przeciwnym razie.

Uwagi

Od Windows Internet Explorer 9 ta metoda jest przestarzała i nie należy jej używać.

Z niektórymi drukarkami działaIHTMLElementRender :: DrawToDC może powodować problemy. Możesz to zapewnićIHTMLElementRender :: DrawToDC działa poprawnie na wszystkich drukarkach, uruchamiając sięIHTMLElementRender :: SetDocumentPrinter najpierw metoda, a następnie przekazanie zmodyfikowanego kontekstu urządzenia doIHTMLElementRender :: DrawToDC.

Uwaga: Cytuję całą dokumentację, aby można ją było znaleźć, gdy Microsoft ostatecznie usunie ją z MSDN. Wraz z deklaracją interfejsu:

IHTMLElementRender = interface(IUnknown)
   ['{3050F669-98B5-11CF-BB82-00AA00BDCE0B}']
   function DrawToDC(hdc: HDC): HResult; stdcall;
   function SetDocumentPrinter(const bstrPrinterName: WideString; hdc: HDC): HResult; stdcall;
end;
UżyjIViewObject berło

Próbowałem przekonwertować, aby użyćIViewObject (na przykład.Jak renderować element HTML bez użycia przeglądarki internetowej?):

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;

Problem z tym kodem polega na tym, że renderuje tylkowidoczny obszar przeglądarki (tj. bez zawartości przewijanej):

muszę renderowaćCały strona internetowa (np. do drukowania).

Próbowałem zmienićrysować aspekt zDVASPECT_CONTENT (tak jakten przykład robi), doDVASPECT_DOCPRINT:

DVASPECT_DOCPRINT
Zapewnia reprezentację obiektu na ekranie, tak jakby był drukowany na drukarce za pomocą polecenia Drukuj z menu Plik. Opisane dane mogą reprezentować sekwencję stron.

Z tym samym wynikiem; zamiast renderowania strony renderowana jest tylko widoczna część:

Jak mogę poprosić silnik renderujący IE9 o renderowanie?

Próbowałem też użyć innegoindeksy wraz zDVASPECT_DOCPRINT. Mimo żeIViewObject nie jest udokumentowane, może tak właśnie drukujesz inaczej„strony”:

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

Ale WebBrowser nie dba o to, jaki jest indeks; renderowanie tylko prąduView (co, jak przypuszczam, ma sens podczas używaniaIViewObject).

Jak renderować przeglądarkę w kontekście urządzenia?

Uwaga: Pytanie jest oznaczone tagiemdelphi, ale w tym pytaniu nie ma nicdelphi konkretny.

Aktualizacja: spróbowałem także innych kombinacjiaspekt iindeks:

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

questionAnswers(1)

yourAnswerToTheQuestion