編集:元の質問は、多くのワイルドな推測を含む長いものでした. 私はそれを残りの謎に戻しました..
私は今、一日中苦労して困惑しており、自分の問題をコミュニティに提示する必要があると思います.
Screenshot method generate black imagesという投稿に由来します。元の投稿者は、ユーザーがログオフしているときでも、WebBrowser を含む自分のプログラムのスクリーンショットを n 秒ごとに連続して撮りたいと考えています。
ユーザーがログアウトすると、画面がなくなります。したがって、画面を読み取ろうとすると失敗します。ウィンドウ ハンドルを使用すると結果はブラック ボックスになり、CopyFromScreen を使用すると GDI エラー例外が発生します。
しかし、プログラムウィンドウはまだそこにありDrawToBitmap
、ユーザーがログアウトしていても使用は正常に機能します。
条件と残りの問題は次のとおりです。
ユーザーは、いかなる方法でも に触れたりクリックしたりしてはなりません
WebBrowser
。たとえば、スクロール、クリック、ナビゲートして後続のDrawToBitmap
呼び出しを行うと、空のボックスが表示されます。は
WebBrowser
そのままですがRefresh
、次の DrawToBitmap 呼び出しの前に a を実行するだけで十分です。タッチした後、次の操作を行って URL を再度読み込む必要があります。
webBrowser1.Url = new Uri(URLpath);
これを行うには、新しい URL をナビゲートするときに保存する必要があります。Navigated イベントでそれを行います。
Web
DrawToBitmap
ページに<input type="text" ..> field
.DocumentText
これは a で破壊することReplace("<input", "<in_put");
で修復できますが、それ以上のトリックを行わないと CSS シートが失われます。
テストするには、2 つをスローButtons, a Label, a Timer, a Combobox and a WebBrowser on a Form
してコードをコピーします。ファイルパスを、セットアップと監視に適したフォルダーに変更します..:
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();
}
ほとんど自由にナビゲートできるようになり、画面のスクレイピングも機能し続けます。ただし、ユーザーページやタグページなどのテキスト入力フィールドのあるページは除きます。
誰でも再現できるのだろうか..?
それとも説明??
それとも、結局「ゴーストハンティング」をしているだけで、物事は単に信頼できないのでしょうか???
最終編集:
説明を得ることができればよかったのですが、実用的な解決策を得るにはおそらく十分であるはずです.OPは、へのPrintWindow
呼び出しを使用してuser32.dll
すべての問題を解決するコードを見つけました。ログオフ中に機能し、Refreshing
クリックした後でも機能しWebBrowser
、テキスト入力フィールドを含むすべてのページをスクレイピングします. これが私のバージョンです:
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;
}
これにより、境界線の有無にかかわらず、フォームまたはコントロールをキャプチャできます。