我正在使用C#,Winforms和MS Visual Studio 2010开发桌面应用程序。在应用程序中,我必须截取表单面板的屏幕截图并将图像保存在光盘中。面板尺寸可能很大。我使用Panel.DrawToBitmap()方法来保存面板的图像。但是,当面板尺寸太大时,它会抛出异常。我在msdn(http://msdn.microsoft.com/en-us/library/system.windows.forms.control.drawtobitmap%28v=vs.110%29.aspx)中发现,对于大尺寸控件,Control.DrawToBitmap方法不起作用。有没有其他方法,我可以实现克服大小限制的类似行为。需要注意的是,面板尺寸可能会有所不同。
更新:我找到了Control.DrawToBitmap的替代品:WebBrowser.DrawToBitmap() or other methods?。 但是,它只捕获控件的可见部分。
答案 0 :(得分:1)
这个问题让我对很多事情感到困惑。
这是一个从Panel
相当大的尺寸写出图像文件的解决方案。
其中一个限制因素是生成的Bitmap的大小。我测试了最大12.5k * 25k
的尺寸,发现它工作正常;但是,尺寸可能取决于您的机器。我认为你需要相当多的连续内存来创建这么大的Bitmap
。
另一个问题是,正如你的标题所示,确实使用DrawToBitmap
方法本身。它看起来好像无法可靠地写入大型位图,这就是为什么我必须在临时位图中缓冲其结果的原因。如果控件的任何尺寸超过某个尺寸,可能是4k,但也许不是......,它也不会起作用。
解决方案首先创建Bitmap
大小的Panel
。然后,它会创建一个临时Panel
来容纳大Panel
。这个容器足够小,DrawToBitmap
可以工作。
然后它在宽度和高度上循环,向上移动大Panel
并向左移动,将DrawToBitmap
部分粘贴回来,一步一步地进入大Bitmap
。
最后,它将其写回PNG
以获得最佳可读性和大小。
private void button2_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(largePanel.ClientSize.Width, largePanel.ClientSize.Height);
DrawToBitmap(largePanel, bmp); // the patchwork method
bmp.Save(yourFileName, System.Drawing.Imaging.ImageFormat.Png);
bmp.Dispose(); // get rid of the big one!
GC.Collect(); // not sure why, but it helped
}
void DrawToBitmap(Control ctl, Bitmap bmp)
{
Cursor = Cursors.WaitCursor; // yes it takes a while
Panel p = new Panel(); // the containing panel
Point oldLocation = ctl.Location; //
p.Location = Point.Empty; //
this.Controls.Add(p); //
int maxWidth = 2000; // you may want to try other sizes
int maxHeight = 2000; //
Bitmap bmp2 = new Bitmap(maxWidth, maxHeight); // the buffer
p.Height = maxHeight; // set up the..
p.Width = maxWidth; // ..container
ctl.Location = new Point(0, 0); // starting point
ctl.Parent = p; // inside the container
p.Show(); //
p.BringToFront(); //
// we'll draw onto the large bitmap with G
using (Graphics G = Graphics.FromImage(bmp))
for (int y = 0; y < ctl.Height; y += maxHeight)
{
ctl.Top = -y; // move up
for (int x = 0; x < ctl.Width; x += maxWidth)
{
ctl.Left = -x; // move left
p.DrawToBitmap(bmp2, new Rectangle(0, 0, maxWidth, maxHeight));
G.DrawImage(bmp2, x, y); // patch together
}
}
ctl.Location = p.Location; // restore..
ctl.Parent = this; // form layout <<<==== ***
p.Dispose(); // clean up
Cursor = Cursors.Default; // done
}
我在Panel
上画了一些东西,然后扔了几百Buttons
,结果看起来很无缝。由于显而易见的原因,无法发布它。
***注意:如果您的小组不在表单上,则应将this
更改为真实的Parent
!