1

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

情况:

我有一个UserControl名为 " CanvasControl" 的方法,它接受OnPaint充当我的 Draw Pad 应用程序的画布的方法。在此用户控件中,我有一个函数“ PrintCanvas()”,它将创建UserControlPNG 文件的屏幕截图图像。下面是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那里不可见。

是否有任何其他设置我错过了使 winformUserControl可打印?

更新:(绘图程序)

  1. 充当画布的用户控件 -此处的代码
4

1 回答 1

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好处呢?这只对引诱新手犯这个错误有好处??

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

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

可能还有一些我现在想不起来的东西..

因此,对于控件上的正常绘图,请始终使用e.Grapahics对象!您可以将其传递给子程序以使代码更有条理,但不要尝试缓存它;它必须是最新的!

于 2016-02-23T07:35:25.703 回答