DrawToBitmap返回空白图像

时间:2016-02-22 02:16:23

标签: c# user-controls drawtobitmap

我在winform应用程序中创建位图图像时遇到问题。

情况:

我有UserControl名为" CanvasControl"接受OnPaint方法作为我的Draw Pad应用程序的画布。在这个用户控件中,我有一个功能" PrintCanvas()"这将在PNG文件中创建UserControl的屏幕截图。以下是PrintCanvas()函数:

public void PrintCanvas(string filename = "sample.png")
{
    Graphics g = this.CreateGraphics();
    //new bitmap object to save the image        
    Bitmap bmp = new Bitmap(this.Width, this.Height);
    //Drawing control to the bitmap        
    this.DrawToBitmap(bmp, new Rectangle(0, 0, this.Width, this.Height));
    bmp.Save(Application.StartupPath + 
        @"\ExperimentFiles\Experiment1" + filename, ImageFormat.Png);
    bmp.Dispose();
}

此用户控件(CanvasControl)在我的主窗体中被调出,用户将在其中绘制内容并可选择使用保存按钮进行保存。保存按钮会调出" PrintCanvas()" UserControl的功能。

我按预期得到输出图像文件,但问题是它是一张空白图像。

到目前为止我尝试过:

为了测试它不是语法问题,我尝试将PrintCanvas()函数转移到我的主窗体中,令人惊讶的是我得到了整个主窗体的图像,但是UserControl不是在那里可见。

我是否错过任何其他设置以使winform UserControl可打印?

更新:(绘图程序)

  1. 用户控件充当画布 - code here

1 个答案:

答案 0 :(得分:2)

问题中的代码给出了第一个提示,但链接中的代码显示了问题的根源:您使用了错误的'绘图的Graphics对象的实例:

protected override void OnPaint(PaintEventArgs e)
{
  // If there is an image and it has a location,
  // paint it when the Form is repainted.
  Graphics graphics = this.CreateGraphics();
  ..

这是winforms图形最常见的错误之一! 永远不要使用CreateGraphics!你总是应该在Paint或DrawXXX事件中使用Graphics对象绘制到控制界面上。这些事件有一个参数e.Graphics,它是唯一可以绘制持久性图形的参数。

持久性表示在必要时始终会刷新,而不仅仅是在您触发它时。这是一个令人讨厌的错误,因为一切似乎都有效,直到您遇到外部事件需要重绘的情况:

  • 最小化然后最大化表单
  • 将其从屏幕移开然后再移回
  • 致电DrawToBitmap
  • ...

..只有在您使用Graphics参数中的有效且最新的 PaintEventArgs e对象时,才会有效。

所以,解决方案很简单:

 protected override void OnPaint(PaintEventArgs e)
{
// If there is an image and it has a location,
// paint it when the Form is repainted.
Graphics graphics = e.Graphics();  // << === !!
..

但是 CreateGraphics的优点是什么?引诱新手进入那个错误只会有好处吗?

不完全;以下是它的一些用途:

  • 绘制非持久性图形,如橡皮筋矩形或特殊鼠标光标
  • 测量文字大小,而不是使用TextRendererMeasureString方法
  • 进行实际绘制
  • 使用Bitmap
  • 查询屏幕或Graphics.DpiX/Y分辨率

可能还有其他一些我现在无法想到的......

因此,对于正常绘制到控件总是,请使用e.Grapahics对象!您可以将其传递给子例程以使代码更加结构化,但不要尝试缓存它;它需要是最新的!