【问题标题】:Do I have to keep creating a Graphics object我是否必须继续创建 Graphics 对象
【发布时间】:2015-09-14 22:30:13
【问题描述】:

我是一个老的 delphi 程序员,我习惯于创建对象并一直使用它们来有效地使用内存。但是在 c# 中(可能是我见过的所有教程),你每次都在用new 创建东西(感谢垃圾收集器!!,让我来编码)..

无论如何,我正在尝试创建一个包含大量绘图的设计软件。 我的问题是:我必须创建一个图形对象,还是使用protected override void OnPaint(PaintEventArgs e) e.Graphics 每个绘画事件.. 因为当我创建一个图形对象然后调整我绘制的控件的大小时,我创建的图形对象,有裁剪问题,只绘制旧的矩形区域..

谢谢

【问题讨论】:

  • 始终使用提供的Paint 方法。 CreateGraphics 是通往灾难的必经之路。
  • 好的,感谢您的快速回答。我保留了一个缓冲区位图来绘制它,如果发生调整大小或绘制额外的东西等事情;我正在使用从中创建的图形对象进行重绘,然后使用 graphics.DrawImage(bitmapB, 0, 0); 将其刷新到控制组件的表面。现在我将重新设计我的管道并使用 OnPaint 事件的 e.graphic 对象来刷新......再次感谢。你真的很有帮助

标签: c# winforms gdi+ clipping onpaint


【解决方案1】:

当对象的创建成本高、存储成本低且保持更新相对简单时,缓存对象才有意义。 Graphics 对象的独特之处在于,没有这些条件为真:

  • 创建起来非常便宜,不到一微秒。
  • 存储非常昂贵,底层设备上下文存储在会话的桌面堆中。可以存储的对象数量很少,不超过 65535。在会话中运行的所有程序共享该堆。
  • 很难保持更新,背后发生的事情会使设备上下文无效。就像用户或您的程序更改窗口大小一样,会使 Graphics.ClipBounds 属性无效。您正在浪费使用正确 Graphics 对象的机会,该对象是在 Paint 事件处理程序中传递给您的。尤其是使用双缓冲时的错误工厂。

缓存 Graphics 对象是一个错误。

【讨论】:

    【解决方案2】:

    如果您想在表面上绘图,请始终使用来自Paint 事件的Graphics 对象!

    如果您想绘制到 Bitmap 中,您可以创建一个 Graphics 对象并根据需要使用它。

    要使Paint 事件起作用,您需要将所有绘图收集到List 的图形操作中;所以你会想要创建一个很好的类来存储所有需要的参数。

    在您的情况下,您可能需要考虑一种混合方法:旧的图形动作绘制成位图,例如BackgroundImageImage 由您控制

    当前/正在进行的绘图是在表面上完成的。这相当于将位图用作缓存,因此您不必对每一个小改动等重新绘制大量操作

    这与您的undo/redo 实现密切相关。您可以设置一个限制并将之前的内容绘制到 Btimap 中,将之后的内容绘制到表面上..

    PS:您还应该重新考虑您的GC 态度。拥有它简单、高效,是一种幸福。 (而且,是的,我已经完成了 TP&Delphi 的份额,早在它们负担得起的时候......) - 是的,我们进行编码,但 GC 不是关于编码,而是关于家务。无聊至多..(你总是可以设计来避免它,但不能在 Windows 系统中使用 Graphics 对象。)

    【讨论】:

      【解决方案3】:

      每个实现 IDisposable 的类的一般规则是尽快 Dispose() 它。确保您了解using(...){} 声明。

      对于在 WinForms (GDI+) 中绘图,最佳实践确实是使用 PaintEventArgs 中的 Graphics 对象。因为你没有创建那个,所以 not Dispose() 它。也不要把它藏起来。

      【讨论】:

        【解决方案4】:

        我必须完全不同意这里其他更有经验的成员,他们说一遍又一遍地重新创建 Graphics 对象没什么大不了的,或者实际上更好。

        HDC 是一个指向 HDC__ 结构的指针,它是一个具有一个成员“int未使用”的结构。每次需要绘制时创建另一个实例/对象是绝对的浪费和愚蠢。 HDC 并不大,它是 4 或 8 字节,它指向的结构几乎在所有情况下都是 4 字节。此外,就一个人所做的而言,在切换前的 WndProc() 开头使用“静态”关键字制作图形对象也无济于事,因为为图形对象提供设备的唯一方法要绘制的上下文或句柄是通过调用其构造函数来实现的,因此“静态”不会让您避免一遍又一遍地创建它。

        除此之外,Microsoft 建议您创建一个 HDC 指针并将其分配给 PAINTSTRUCT 已经具有的相同值,它发送的每条 WM_PAINT 消息。

        很抱歉,我认为 WinAPI 非常糟糕。举个例子,我花了一整天的时间研究如何制作一个子 WS_EX_LAYERED 窗口,发现为了启用 Win 8 功能,必须将带有操作系统 ID 号的 XML 代码添加到清单中。简直荒谬。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-16
          • 1970-01-01
          • 2011-09-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-02
          相关资源
          最近更新 更多