如何克服 winform 的 Control.DrawToBitmap() 方法大尺寸限制

本文关键字:方法 DrawToBitmap 何克服 克服 winform Control | 更新日期: 2023-09-27 18:33:28

我正在使用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((或其他方法。但是,它仅捕获控件的可见部分。

如何克服 winform 的 Control.DrawToBitmap() 方法大尺寸限制

这个问题

让我对很多事情感到困惑。

这是一个从相当大的Panel写入图像文件的解决方案。

限制因素之一是生成的位图的大小。我已经测试了高达 12.5k * 25k 的尺寸,发现它工作正常;但是,大小可能取决于您的计算机。我认为您需要相当多的连续内存才能创建如此大的Bitmap.

另一个问题是,正如您的标题所暗示的那样,确实与DrawToBitmap方法本身有关。看起来它不能可靠地写入大型位图,这就是为什么我不得不将其结果缓冲在临时位图中的原因。如果控件的任何维度超过某种大小,也许是 4k,但也许不是,它也不能工作。

该解决方案首先创建Panel大小的Bitmap。然后它创建一个临时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