Frage

Ich versuche, die folgende Seite mit dem Standard -C# .NET -Code zu erfassen. Ich habe nach den verschiedenen Methoden der Menschen gesucht, von denen die meisten ein Browserobjekt instanziieren und eine Zeichnung zur Bitmap -Methode verwenden. Keiner davon nimmt jedoch den Inhalt des Diagramms auf dieser Seite auf:

http://www.highcharts.com/demo/combo-dual-axes

Vielleicht hat das JavaScript keine Zeit zum Ausführen, aber das Hinzufügen von Thread.Sleep (x) hat nicht unterstützt.

Dies Kommerzielle Komponente Erfasst es richtig, aber ich würde es lieber vermeiden, eine zusätzliche Abhängigkeit in meinem Projekt zu erfordern und 150 US -Dollar zu zahlen, wenn die anderen Lösungen sooo in der Nähe sind!

Findet jemand, das seine Lösung so richtig macht?

War es hilfreich?

Lösung

Sie haben möglicherweise versucht IECAPT. Ich denke, es ist der richtige Weg. Ich habe eine modifizierte Version davon erstellt und habe a verwendet timer Anstatt von Thread.Sleep Es erfasst Ihre Website wie erwartet.

------BEARBEITEN------

Hier ist die hässliche Quelle. Fügen Sie einfach einen Verweis auf Microsoft HTML Object Library.

Und das ist die Verwendung:

HtmlCapture capture = new HtmlCapture(@"c:\temp\myimg.png");
capture.HtmlImageCapture += new HtmlCapture.HtmlCaptureEvent(capture_HtmlImageCapture);
capture.Create("http://www.highcharts.com/demo/combo-dual-axes");

void capture_HtmlImageCapture(object sender, Uri url)
{
    this.Close();
}

Datei1

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;


namespace MyIECapt
{
    public class HtmlCapture
    {
        private WebBrowser web;
        private Timer tready;
        private Rectangle screen;
        private Size? imgsize = null;

        //an event that triggers when the html document is captured
        public delegate void HtmlCaptureEvent(object sender, Uri url);

        public event HtmlCaptureEvent HtmlImageCapture;

        string fileName = "";

        //class constructor
        public HtmlCapture(string fileName)
        {
            this.fileName = fileName;

            //initialise the webbrowser and the timer
            web = new WebBrowser();
            tready = new Timer();
            tready.Interval = 2000;
            screen = Screen.PrimaryScreen.Bounds;
            //set the webbrowser width and hight
            web.Width = 1024; //screen.Width;
            web.Height = 768; // screen.Height;
            //suppress script errors and hide scroll bars
            web.ScriptErrorsSuppressed = true;
            web.ScrollBarsEnabled = false;
            //attached events
            web.Navigating +=
              new WebBrowserNavigatingEventHandler(web_Navigating);
            web.DocumentCompleted += new
              WebBrowserDocumentCompletedEventHandler(web_DocumentCompleted);
            tready.Tick += new EventHandler(tready_Tick);
        }


        public void Create(string url)
        {
            imgsize = null;
            web.Navigate(url);
        }

        public void Create(string url, Size imgsz)
        {
            this.imgsize = imgsz;
            web.Navigate(url);
        }



        void web_DocumentCompleted(object sender,
                 WebBrowserDocumentCompletedEventArgs e)
        {
            //start the timer
            tready.Start();
        }

        void web_Navigating(object sender, WebBrowserNavigatingEventArgs e)
        {
            //stop the timer   
            tready.Stop();
        }



        void tready_Tick(object sender, EventArgs e)
        {
            try
            {
                //stop the timer
                tready.Stop();

                mshtml.IHTMLDocument2 docs2 = (mshtml.IHTMLDocument2)web.Document.DomDocument;
                mshtml.IHTMLDocument3 docs3 = (mshtml.IHTMLDocument3)web.Document.DomDocument;
                mshtml.IHTMLElement2 body2 = (mshtml.IHTMLElement2)docs2.body;
                mshtml.IHTMLElement2 root2 = (mshtml.IHTMLElement2)docs3.documentElement;

                // Determine dimensions for the image; we could add minWidth here
                // to ensure that we get closer to the minimal width (the width
                // computed might be a few pixels less than what we want).
                int width = Math.Max(body2.scrollWidth, root2.scrollWidth);
                int height = Math.Max(root2.scrollHeight, body2.scrollHeight);

                //get the size of the document's body
                Rectangle docRectangle = new Rectangle(0, 0, width, height);

                web.Width = docRectangle.Width;
                web.Height = docRectangle.Height;

                //if the imgsize is null, the size of the image will 
                //be the same as the size of webbrowser object
                //otherwise  set the image size to imgsize
                Rectangle imgRectangle;
                if (imgsize == null) imgRectangle = docRectangle;
                else imgRectangle = new Rectangle() { Location = new Point(0, 0), Size = imgsize.Value };

                //create a bitmap object 
                Bitmap bitmap = new Bitmap(imgRectangle.Width, imgRectangle.Height);
                //get the viewobject of the WebBrowser
                IViewObject ivo = web.Document.DomDocument as IViewObject;

                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    //get the handle to the device context and draw
                    IntPtr hdc = g.GetHdc();
                    ivo.Draw(1, -1, IntPtr.Zero, IntPtr.Zero,
                             IntPtr.Zero, hdc, ref imgRectangle,
                             ref docRectangle, IntPtr.Zero, 0);
                    g.ReleaseHdc(hdc);
                }
                //invoke the HtmlImageCapture event
                bitmap.Save(fileName);
                bitmap.Dispose();
            }
            catch 
            {
                //System.Diagnostics.Process.GetCurrentProcess().Kill();
            }
            if(HtmlImageCapture!=null) HtmlImageCapture(this, web.Url);
        }
    }
}

und Datei2

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Runtime.InteropServices;

namespace MyIECapt
{
    [ComVisible(true), ComImport()]
    [GuidAttribute("0000010d-0000-0000-C000-000000000046")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IViewObject
    {
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int Draw(
            [MarshalAs(UnmanagedType.U4)] UInt32 dwDrawAspect,
            int lindex,
            IntPtr pvAspect,
            [In] IntPtr ptd,
            IntPtr hdcTargetDev,
            IntPtr hdcDraw,
            [MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcBounds,
            [MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcWBounds,
            IntPtr pfnContinue,
            [MarshalAs(UnmanagedType.U4)] UInt32 dwContinue);
        [PreserveSig]
        int GetColorSet([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect,
           int lindex, IntPtr pvAspect, [In] IntPtr ptd,
            IntPtr hicTargetDev, [Out] IntPtr ppColorSet);
        [PreserveSig]
        int Freeze([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect,
                        int lindex, IntPtr pvAspect, [Out] IntPtr pdwFreeze);
        [PreserveSig]
        int Unfreeze([In, MarshalAs(UnmanagedType.U4)] int dwFreeze);
    }
}

Andere Tipps

Thread.Sleep Wird der Thread einfach suspendieren, auf dem Ihr Webbrowser ausgeführt wird - wie erwarten Sie, dass er etwas rendert, wenn er suspendiert wird? :)

Stattdessen müssen Sie dem Thread zulassen, die Arbeit zu verarbeiten. Sie können dies mit einer Kombination von erreichen Thread.Sleep(0) und Application.DoEvents(), mit so etwas wie folgt:

DateTime finish = DateTime.Now.AddSeconds(3);
while (DateTime.Now < finish) {
    Application.DoEvents();
    Thread.Sleep(0);
}

@Lb, danke für die Hilfe!

Nur ein FYI für alle, die es in einer Klassenbibliothek ausführen möchten, muss Webbrowser eine einzelne Thread -Wohnung. Machen Sie also so etwas:

  var t = new Thread(InitAndDo); //InitAndDo would have your code creating the webbrowser object etc...
  t.SetApartmentState(ApartmentState.STA);
  t.Start();

Dann fügen Sie nach Abschluss des Navigationsaufrufs die Gotcha diese Codezeile hinzu, damit Sie das ausgefüllte Navigationsereignis erhalten:

    web.Navigate(Url);
    Application.Run();

Ich habe zu diesem Zweck ein Nuget -Paket erstellthttps://github.com/dcumin39/renderhighcharts/wiki

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top