C#Graphics.CopyFromScreen“参数无效”

时间:2013-05-29 12:29:25

标签: c# graphics bitmap

我在C#中创建了一个应用程序,它将连续执行屏幕捕获,并使用计时器在PictureBox中显示它。运行几秒钟后,出现了ArgumentException。

下面是代码和具有ArgumentException

的行
private void timer1_Tick(object sender, EventArgs e)
    {
        Rectangle bounds = Screen.GetBounds(Point.Empty);
        Graphics graphics;
        Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);
        using (graphics = Graphics.FromImage(bitmap))
        {

            graphics.CopyFromScreen(0, 0, 0, 0, new Size(bounds.Width , bounds.Height )); // ArgumentException
            pictureBox1.Image = bitmap;
            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;

        }
    }

除此之外,我注意到在运行应用程序几秒钟后,Windows会发出低内存警报。

有关解决此问题的任何提示吗?

3 个答案:

答案 0 :(得分:3)

您不断为图片框设置新的位图,并且永远不会丢弃先前的位图。一段时间后,系统缺少GDI句柄和/或内存(运行代码,我在15秒内消耗了一个内存)。

您可以简单地重复使用现有的位图:

Rectangle bounds = Screen.GetBounds(Point.Empty);

Image bitmap = pictureBox1.Image ?? new Bitmap(bounds.Width, bounds.Height);

using (Graphics graphics = Graphics.FromImage(bitmap))
{
    graphics.CopyFromScreen(0, 0, 0, 0, new Size(bounds.Width, bounds.Height));

    if (pictureBox1.Image == null)
    {
        pictureBox1.Image = bitmap;
    }
    else
    {
        pictureBox1.Refresh();
    }

}

您也不必在每次迭代时重置pictureBox1.SizeMode


或者,您可以手动配置以前的位图:

Rectangle bounds = Screen.GetBounds(Point.Empty);
Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
    graphics.CopyFromScreen(0, 0, 0, 0, new Size(bounds.Width, bounds.Height));

    using (Image prev_bitmap = pictureBox1.Image)
    {
        pictureBox1.Image = bitmap;
    }
}

答案 1 :(得分:1)

   pictureBox1.Image = bitmap;

是的,当您经常更新图片框时,您的程序将持续很长时间。 Bitmap类是单一的.NET类,其中IDisposable不容易被忽略。它就像一座冰山,位图可以使用大量的非托管内存但很少有内存。当您不再使用位图时,必须处理位图,以防止它们为其像素数据消耗所有可用的非托管内存。垃圾收集器往往会隐藏这个问题,但是当它没有经常运行时就不能这样做。而Bitmap的托管部分太小,无法经常触发收集。修正:

   if (pictureBox1.Image != null) pictureBox1.Image.Dispose();
   pictureBox1.Image = bitmap;

答案 2 :(得分:-1)

以下KB有助于理解此问题: Bitmap and Image constructor dependencies

  

GDI +,因此System.Drawing命名空间可能会推迟   解码原始图像比特直到图像需要比特。   另外,即使在图像被解码之后,GDI +也可以   确定丢弃大内存的效率更高   位图并稍后重新解码。因此,GDI +必须能够访问   位图或图像生命周期中图像的源位   宾语。

     

为了保持对源位的访问,GDI +锁定任何源文件,和   强制应用程序维护任何源流的生命周期   Bitmap或Image对象的生命周期。

必须弄清楚物体何时可以处置。