【发布时间】:2011-02-14 12:54:21
【问题描述】:
我正在考虑创建一个带有图层的绘图程序,并使用 GDI+ 来显示它们。我想使用 GDI+,因为它支持透明度。
问题是,画线到 DC 非常快,但直接画到位图非常慢。仅当您锁定位并开始设置像素时,它才会很快。我可以在我的 WM_PAINT 事件中绘制到多个 DC,然后只为 MemDC 的每一层执行 DrawBitmap 吗?最好的方法是什么?
谢谢
【问题讨论】:
我正在考虑创建一个带有图层的绘图程序,并使用 GDI+ 来显示它们。我想使用 GDI+,因为它支持透明度。
问题是,画线到 DC 非常快,但直接画到位图非常慢。仅当您锁定位并开始设置像素时,它才会很快。我可以在我的 WM_PAINT 事件中绘制到多个 DC,然后只为 MemDC 的每一层执行 DrawBitmap 吗?最好的方法是什么?
谢谢
【问题讨论】:
GDI+ 对于绘图程序来说确实足够快。我将它(来自 C#)用于高速动画(>30 fps)。
您似乎希望能够操纵单个像素。这在 LockBits 中非常快,虽然在 C# 中使用有点笨拙(需要指针和 unsafe 标签),但在 C++ 中似乎没有那么困难。
您可能不想在绘制事件中从多个图层直接复制到您的控制表面。相反,这个渲染应该在屏幕外缓冲区 (B1) 上完成。在完成所有复制/绘图操作后绘制 B1,将其复制到第二个屏幕外缓冲区 (B2),然后使控制表面无效/刷新。在控件的绘制事件中,您从 B2 复制到可见表面。
您不希望通过多步绘图操作直接在可见表面上绘图,因为会导致某种形式的闪烁(有时屏幕会自行重新绘制,而您的代码只是进行多步操作的中途,所以用户偶尔会看到一个半成品帧)。
您可以渲染到单个屏幕外缓冲区,然后在绘制事件中从它复制到可见表面。这里的主要复杂性是您必须以某种方式处理“杂散”绘制事件,即不是由您故意使控件无效而是由其他原因引起的事件(例如用户在您的窗口上拖动另一个窗口)。如果从屏幕外缓冲区复制到表面并且缓冲区仅绘制到一半,则会出现闪烁。如果你在绘制事件中阻塞直到缓冲区绘制完成,你会在你的控件上看到“form trails”,看起来更糟。
解决方案是上述的双缓冲方法。杂散(或无效时非杂散)绘制事件将从 B2 复制,它始终是完全渲染和最新的 - 因此没有闪烁。双缓冲确实会使用更多内存,但在一个有多个图层的绘图程序中,这没什么大不了的。
【讨论】: