【问题标题】:How to overcome the winform's Control.DrawToBitmap() method large size limitation如何克服winform的Control.DrawToBitmap()方法大尺寸限制
【发布时间】:2014-12-11 01:00:33
【问题描述】:

我正在使用 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?。 但是,它只捕获控件的可见部分。

【问题讨论】:

  • 我们在谈论什么数字?您能给我们提供您可能需要的尺寸吗?
  • 这种情况是一直发生的,还是在您的程序运行一段时间后首先发生的?在后一种情况下,您可能需要处理一些资源 - 请参阅此处:stackoverflow.com/questions/11996335/…
  • “如何克服 [whatever winforms 限制]” - 使用当前的、非弃用的技术。 winforms 什么都不支持。
  • @HighCore:WinForms 已弃用?哪里说的?
  • @Highcore:请不要在此处带回与主题无关的不必要讨论

标签: c# winforms


【解决方案1】:

这个问题让我对很多事情感到困惑..

这是一个从相当大的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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多