如何克服winform的Control.DrawToBitmap()方法大尺寸限制 [英] How to overcome the winform's Control.DrawToBitmap() method large size limitation
问题描述
我正在使用 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() 或其他方法?.但是,它只捕获控件的可见部分.
这个问题让我对很多事情感到困惑..
这是一个从相当大的Panel
写入图像文件的解决方案..
限制因素之一是生成的位图的大小.我已经测试了最大 12.5k * 25k
的大小并发现它可以正常工作;不过,尺寸可能取决于您的机器.我认为您需要相当多的连续内存来创建如此大的Bitmap
.
另一个问题是,正如您的标题所暗示的,确实与 DrawToBitmap
方法本身有关.它看起来好像不能可靠地写入大型位图,这就是为什么我必须将其结果缓冲在临时位图中.如果控件的任何维度超过某个大小,可能是 4k,但也可能不会.
该解决方案首先创建Panel
大小的Bitmap
.然后它创建一个临时的 Panel
来容纳大的 Panel
.这个容器足够小,DrawToBitmap
可以工作.
然后它在宽度和高度上循环,向上和向左移动大Panel
,粘贴DrawToBitmap
带回来的部分,一步一步进入大位图
.
最后将其写回 PNG
以获得最佳可读性和大小..
private void button2_Click(object sender, EventArgs e){Bitmap bmp = new Bitmap(largePanel.ClientSize.Width, largePanel.ClientSize.Height);DrawToBitmap(largePanel, bmp);//拼凑方法bmp.Save(yourFileName, System.Drawing.Imaging.ImageFormat.Png);bmp.Dispose();//摆脱大的!GC.Collect();//不知道为什么,但它有帮助}void DrawToBitmap(Control ctl, Bitmap bmp){光标 = Cursors.WaitCursor;//是的,需要一段时间面板 p = 新面板();//包含面板点 oldLocation = ctl.Location;//p.Location = Point.Empty;//this.Controls.Add(p);//int maxWidth = 2000;//您可能想尝试其他尺寸int maxHeight = 2000;//Bitmap bmp2 = new Bitmap(maxWidth, maxHeight);//缓冲区p.Height = maxHeight;//设置..p.Width = maxWidth;//..容器ctl.Location = new Point(0, 0);//初始点ctl.Parent = p;//容器内部p.Show();//p.BringToFront();////我们将使用 G 在大位图上绘制使用 (Graphics G = Graphics.FromImage(bmp))for (int y = 0; y
我在 Panel
上绘制了一些东西,并投入了几百个 Buttons
,结果看起来是无缝的.无法发布,原因很明显..
*** 注意:如果您的面板不在表单上,您应该将 this
更改为真正的 Parent
!>
I am developing an desktop application using C#, Winforms, and MS Visual Studio 2010. In the application, I have to take the screenshot of a panel of a form and save the image in disc. The panel size can be large. I have used Panel.DrawToBitmap() method to save the image of the panel. But, when the panel size is too large, it throws exception. I have found in msdn ( http://msdn.microsoft.com/en-us/library/system.windows.forms.control.drawtobitmap%28v=vs.110%29.aspx) that for large size control, the method Control.DrawToBitmap will not work. Is there any alternative way, I can achieve the similar behavior overcoming the size limitation. It is to be noted the panel size can vary.
Update: I have found alternative of Control.DrawToBitmap : WebBrowser.DrawToBitmap() or other methods?. But, it only captures the visible part of the control.
This question had me confused about quite a few things..
Here is a solution that writes an image file from a Panel
of rather large sizes..
One of the limiting factors is the size of the resulting Bitmap. I have tested for sizes of up to 12.5k * 25k
and found it to work fine; the sizes may depend on your machine, though. I think you need quite some contiguous memory to create such a large Bitmap
.
The other problem is, as your title suggests, indeed with the DrawToBitmap
method itself. It looks as if it can't reliably write onto large Bitmaps, which is why I had to buffer its results in a temporary Bitmap. Nor can it work if any dimension of the control is over some size, maybe 4k, but maybe not..
The solution first creates a Bitmap
of the Panel
's size. Then it creates a temporary Panel
to house the large Panel
. This container it small enough for DrawToBitmap
to work.
Then it loops over the width and height, moving the large Panel
up and left, pasting the portions DrawToBitmap
brings back, step by step into the large Bitmap
.
Finally it writes it back as PNG
for best readability and size..
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
}
I have drawn a few things onto the Panel
and thrown in a few hundred Buttons
and the result looks seamless. Can't post it, for obvious reasons..
*** Note: If your Panel doesn't sit on the form you should change this
to the real Parent
!
这篇关于如何克服winform的Control.DrawToBitmap()方法大尺寸限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!