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.