编辑:最初的问题是一个很长的问题,有很多疯狂的猜测。我已经把它切回了剩下的谜团。
我现在整天都在挣扎和困惑,我想我应该向社区提出我的问题。
它起源于帖子中称为Screenshot 的方法生成黑色图像。原始发帖人希望每隔 n 秒连续截取他的程序的屏幕截图,其中包括一个 WebBrowser,即使用户已注销。
当用户注销时,他不再有屏幕。因此,任何读取屏幕的尝试都将失败。如果使用窗口句柄,结果是一个黑框,使用 CopyFromScreen 时会出现 GDI 错误异常。
但是程序窗口仍然存在,DrawToBitmap
即使用户注销也可以正常使用。
以下是条件和剩余问题:
用户不得
WebBrowser
以任何方式触摸/单击。如果他这样做,比如说,滚动、单击、导航子DrawToBitmap
调用会导致一个空框。虽然
WebBrowser
保持不变,但Refresh
在下一次 DrawToBitmap 调用之前执行一次就足够了。触摸它后,需要通过执行重新加载 URL
webBrowser1.Url = new Uri(URLpath);
导航时必须存储新的 URL 才能执行此操作。我在导航事件中这样做。
无论如何,
DrawToBitmap
如果网页包含<input type="text" ..> field
.DocumentText
通过用 a破坏Replace("<input", "<in_put");
可以治愈,但如果没有进一步的技巧,这将丢失 CSS 表..
测试它抛出两个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();
}
我现在几乎可以自由地导航,并且屏幕抓取继续工作——除了带有文本输入字段的页面,例如用户或标签页面。
我想知道是否anybdoy可以复制..?
或者解释一下??
还是我毕竟只是在“猎鬼”而事情根本不可靠???
最终编辑:
虽然得到解释会很好,但获得一个可行的解决方案可能必须足够好。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;
}
这可以捕获带或不带边框的表单或控件。