Wie rendere ich WebBrowser in den Gerätekontext?

Ich möchte eine Webseite rendern (d. h.TWebBrowser) zu einem Gerätekontext. Ich möchte die Layout-Engine von Internet Explorer zum Rendern von Inhalten in einem Gerätekontext (z. B. Metadatei, PDF-Metadatei) verwenden.

Ab Internet Explorer 9 wird derIHTMLElementRender Schnittstelle ist nicht mehrunterstützt:

IHTMLElementRender-Schnittstelle

Verwenden Sie diese Schnittstelle, um den Inhalt eines Elements in einen bestimmten Gerätekontext, normalerweise einen Drucker, zu zeichnen.

Mitglieder
DasIHTMLElementRender Schnittstelle erbt von derIUnbekannt Interface hat aber keine zusätzlichen Mitglieder.

Bis zu dem Punkt, dass sie nicht mehr erwähnen, dass dieDrawToDC-Methode existiert sogar:

IHTMLElementRender :: DrawToDC-Methode

Veraltet Zeichnet den Inhalt des Elements in den angegebenen Gerätekontext.

Syntax

HRESULT DrawToDC(
     HDC hDC
);

Parameter

hDC
[in einem (nHDC Angabe des Geräts, auf das gezeichnet werden soll, normalerweise ein Drucker.

Rückgabewert

Gibt bei Erfolg S_OK oder ansonsten einen Fehlerwert zurück.

Bemerkungen

Ab Windows Internet Explorer 9 ist diese Methode veraltet und sollte nicht mehr verwendet werden.

Mit einigen Druckern läuftIHTMLElementRender :: DrawToDC kann Probleme verursachen. Sie können das sicherstellenIHTMLElementRender :: DrawToDC Funktioniert ordnungsgemäß auf allen DruckernIHTMLElementRender :: SetDocumentPrinter Methode zuerst, und übergeben Sie dann den geänderten Gerätekontext anIHTMLElementRender :: DrawToDC.

Hinweis: Ich zitiere die gesamte Dokumentation, damit sie immer noch gefunden werden kann, wenn Microsoft sie endgültig aus MSDN entfernt. Zusammen mit der Schnittstellendeklaration:

IHTMLElementRender = interface(IUnknown)
   ['{3050F669-98B5-11CF-BB82-00AA00BDCE0B}']
   function DrawToDC(hdc: HDC): HResult; stdcall;
   function SetDocumentPrinter(const bstrPrinterName: WideString; hdc: HDC): HResult; stdcall;
end;
Verwenden Sie dieIViewObject Schnittstelle

Ich habe versucht zu konvertieren, um die zu verwendenIViewObject (z.B.Wie kann ich ein HTML-Element ohne Verwendung eines Webbrowsers rendern?):

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;

Das Problem mit diesem Code ist, dass er nur das rendertsichtbar Bereich des Browsers (d. h. ohne gescrollten Inhalt):

Ich muss das renderngesamte Webseite (z. B. zum Drucken).

Ich habe versucht, das zu ändernAspekt zeichnen vonDVASPECT_CONTENT (wiedieses Beispiel tut), zuDVASPECT_DOCPRINT:

DVASPECT_DOCPRINT
Bietet eine Darstellung des Objekts auf dem Bildschirm, als würde es mit dem Befehl Drucken aus dem Menü Datei auf einem Drucker gedruckt. Die beschriebenen Daten können eine Folge von Seiten darstellen.

Mit dem gleichen Ergebnis; Anstatt die Seite zu rendern, wird nur der sichtbare Teil gerendert:

Wie kann ich die IE9-Rendering-Engine zum Rendern auffordern?

Ich habe auch versucht mit verschiedenenIndizes zusammen mitDVASPECT_DOCPRINT. ObwohlIViewObject ist nicht dokumentiert, vielleicht drucken Sie so anders"Seiten":

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

Dem WebBrowser ist es jedoch egal, wie der Index lautet. rendert nur den StromView (was ich für sinnvoll halte bei der verwendungIViewObject).

Wie rendere ich einen Browser in einen Gerätekontext?

Hinweis: Die Frage ist markiert mitdelphi, aber es ist nichts in dieser FrageDelphi Spezifisch.

Aktualisieren: ich habe auch andere kombinationen von probiertAspekt undIndex:

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

Antworten auf die Frage(1)

Ihre Antwort auf die Frage