WebBrowser Madness

Bearbeiten: Die ursprüngliche Frage war eine lange mit vielen wilden Vermutungen. Ich habe es auf die verbleibenden Geheimnisse zurückgeschnitten ..

Ich habe jetzt den ganzen Tag gekämpft und gerätselt und denke, ich sollte mein Problem der Community vorstellen.

Es entstand aus der genannten StelleDie Screenshot-Methode erzeugt schwarze Bilder. Das Originalplakat möchte alle n Sekunden fortlaufend Screenshots seines Programms machen, das einen WebBrowser enthältauch wenn der Benutzer abgemeldet ist.

Wenn der Benutzer abgemeldet ist, hat er keinen Bildschirm mehr. Daher schlägt jeder Versuch fehl, den Bildschirm zu lesen. Wenn Sie ein Fensterhandle verwenden, ist das Ergebnis eine Blackbox, wenn Sie CopyFromScreen verwenden, eine GDI-Fehlerausnahme.

Aber das Programmfenster ist noch da und benutztDrawToBitmap funktioniert einwandfrei, auch wenn der Benutzer abgemeldet ist.

Hier sind die Bedingungen und die verbleibenden Probleme:

Der Benutzer darf den nicht berühren / anklickenWebBrowser in irgendeiner Weise. Wenn er dies beispielsweise durch Scrollen, Klicken und Navigieren durch den Unterordner tutDrawToBitmap Anrufe führen zu einer leeren Box.

WährendWebBrowser unberührt bleibt, reicht es aus, aRefresh vor dem nächsten DrawToBitmap-Aufruf.

Nach dem Berühren muss die URL mit a erneut geladen werdenwebBrowser1.Url = new Uri(URLpath);

Beim Navigieren muss dazu die neue URL gespeichert werden. Das mache ich im Navigated Event.

Egal was,DrawToBitmap schlägt fehl (mit leerem Kästchen), wenn die Webseite a enthält<input type="text" ..> field.

Durch Zerstörung derDocumentText mit einemReplace("<input", "<in_put"); Dies könnte geheilt werden, aber ohne weitere Tricks werden die CSS-Blätter verloren gehen.

Um es zu testen, werfen Sie zweiButtons, a Label, a Timer, a Combobox and a WebBrowser on a Form und kopieren Sie den Code; Ändern Sie den Dateipfad in einen Ordner, der zu Ihrem Setup und Ihrer Uhr passt.

public Form1()
{
    InitializeComponent();
    this.button1.Click += new System.EventHandler(this.button1_Click);
    this.button2.Click += new System.EventHandler(this.button2_Click);
    this.button1.Text = "Start";
    this.button2.Text = "Stop";
    this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
    this.comboBox1.Items.AddRange(new object[] {
        "https://stackoverflow.com/questions",
        "http://webcam.zirndorf.de/marktplatz/gross.jpg"});
    scapeRect = this.ClientRectangle;
    webBrowser1.Url = new Uri("https://stackoverflow.com/questions");
    this.comboBox1.SelectedIndexChanged += 
                   new System.EventHandler(this.comboBox1_SelectedIndexChanged);

}

Rectangle scapeRect = Rectangle.Empty;
int imgIndex = 0;
int urlIndex = 0;

private void button1_Click(object sender, EventArgs e)
{
    timer1.Interval = 10 * 1000;  // every 10 seconds
    timer1.Start();
}

private void button2_Click(object sender, EventArgs e)
{
    timer1.Stop();
}


private void timer1_Tick(object sender, EventArgs e)
{
    imgIndex ++;
    label1.Text = imgIndex .ToString();
    webBrowser1.Url = new Uri(comboBox1.Text); // this works almost always
    //webBrowser1.Refresh();                   // this works only if the WB is 'untouched'   
    string filename = "d:\\scrape\\AB_sos_Screen" + imgIndex .ToString("000") + ".png";
    Bitmap bmp = new Bitmap(scapeRect.Width, scapeRect.Height);
    this.DrawToBitmap(bmp, scapeRect);
    bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Png);
    bmp.Dispose();
}

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    if (comboBox1.Text != "") webBrowser1.Url = new Uri(comboBox1.Text);
}




private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
    if (!comboBox1.Items.Contains(e.Url.ToString()))
        urlIndex = comboBox1.Items.Add(e.Url.ToString());
    else
        urlIndex = comboBox1.Items.IndexOf(e.Url.ToString());
    if (urlIndex >= 0) comboBox1.SelectedIndex = urlIndex;
    button1.Focus();
}

Ich kann jetzt fast frei navigieren und das Scrapen des Bildschirms funktioniert weiter - mit Ausnahme von Seiten mit Texteingabefeldern wie z. dasBenutzer oder derStichworte Seiten.

Ich frage mich, ob anybdoy reproduzieren kann ..?

Oder erklären?

Oder war ich doch nur 'Geisterjagd' und die Sache ist einfach unzuverlässig ???

Final Edit:

Es wäre zwar nett gewesen, eine Erklärung zu erhalten, aber eine funktionierende Lösung muss wahrscheinlich gut genug sein. Das OP hat Code gefunden, der a verwendetPrintWindow Aufrufuser32.dll und löst alle Probleme. Es funktioniert während der Abmeldung, funktioniert mitRefreshing auch nach dem Klicken in dieWebBrowser und kratzt alle Seiten, einschließlich der mit Texteingabefeldern. Hier ist meine Version davon:

using System.Runtime.InteropServices;
//...
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);

public Bitmap CaptureControl(Control ctl)
{
    //Bitmap bmp = new Bitmap(ctl.Width, ctl.Height);  // includes borders
    Bitmap bmp = new Bitmap(ctl.ClientRectangle.Width, ctl.ClientRectangle.Height);  // content only
    using (Graphics graphics = Graphics.FromImage(bmp))
    {
        IntPtr hDC = graphics.GetHdc();
        try      { PrintWindow(ctl.Handle, hDC, (uint)0);   }
        finally  { graphics.ReleaseHdc(hDC);                }
    }
    return bmp;
}

Dies kann ein Formular oder ein Steuerelement mit oder ohne Rahmen erfassen.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage