【问题标题】:How to efficiently render double buffered window without any tearing effect?如何有效地渲染双缓冲窗口而没有任何撕裂效果?
【发布时间】:2012-03-27 12:41:55
【问题描述】:

我想创建自己的小型无窗口 GUI 系统,因为我正在使用 GDI+。我不能在这里发布代码,因为它很大(c++),但下面是我要遵循的主要步骤......

  1. 创建一个与应用程序窗口大小相等的位图。
  2. 对于所有鼠标和键盘事件,更新自定义控件状态(例如,如果鼠标当前位于特定控件上等)
  3. 对于 WM_PAINT 事件,将背景绘制到屏幕外位图,然后在其上绘制所有更新的控件,最后通过 Graphics::DrawImage(..) 调用将整个屏幕外图像复制到前端缓冲区。
  4. 对于 WM_SIZE/WM_SIZING,删除之前的离屏位图并创建另一个具有新窗口大小的位图。

还有一些检查可以防止重复绘制控件,即仅在需要重新绘制控件时绘制控件,换句话说,当控件的状态发生更改时才绘制控件等。

系统工作正常,但只有一个例外......当窗口正在调整大小时会出现某种撕裂效果。现在我所说的撕裂效果是什么意思,我将尝试解释......

在尺寸调整边缘/边框上,当我拖动边框时,会有一个闪烁的间隙。就好像我的 DrawImage() 函数立即返回,而当一个交换操作完成一半时,另一个图像绘制开始了。

现在您可能会认为这是在许多其他应用程序中发生的常见伪影,因为调整后缓冲区大小并不总是像调整窗口大小一样快,但在其他应用程序中我注意到在其他应用程序中虽然窗口之间有一条腿随着窗口大小的增加,大小和客户区大小在边缘附近没有任何闪烁(它通常只是白色背景,沿边界显示为均匀的细条)。 此外,随着窗口调整大小而移动的动态控件在调整大小时也会出现抖动。

起初在我看来,使用恒定的全屏尺寸离屏表面可以最大限度地减少伪影,但当我尝试时,结果并不那么令人满意。我还尝试在调整大小期间调用 Sleep(),以便在另一个翻转开始之前完全完成翻转,但奇怪的是,即使这对我也不起作用!

我听说 vista 上的 GDI 没有硬件加速,这可能是问题吗?

我还想知道 Qt 之类的框架如何如此流畅地呈现无窗口 GUI,即使您非常快速地调整复杂的 Qt GUI 窗口的大小,出现的工件几乎可以忽略不计。据我所知,Qt 可以使用 opengl 进行 GUI 渲染,但这是第二种选择。

如果我使用directx,那么实时调整大小就更难了,另一方面,opengl 似乎可以毫无问题地调整大小,但我会失去GDI+的所有二维绘图能力。

如果你们中的任何人以前做过这样的事情,请指导我。此外,如果您有任何我应该考虑进行自定义用户界面设计的指针,请提供链接。

谢谢!

我一直希望设计像 windows media player 11 这样的界面,但有人可以告诉我,对于 c++ 程序员有一个直接的解决方案吗(我想知道如何而不是使用一些现有的框架等)?子类化,所有者绘图,自定义绘图似乎什么都没有给你这种级别的控制,我不知道用普通控件绘制半透明控件的方法,所以我认为这个问题值得特别注意。再次感谢。

【问题讨论】:

  • 这是一个熟悉的问题:stackoverflow.com/questions/9786218/…
  • 我自己也经历过这种痛苦——我需要一个具有完整 alpha 支持和可变点击率的表单。我从来没有设法顺利地调整大小(并且花了很长时间来解决所有其他小问题,比如代理事件)。如果您找到合适的解决方案,我很想知道。
  • 但是其他框架如 qt 做平滑调整大小呢?如果我没记错的话,gtk 还使用无窗口非原生自定义绘制控件。我相信存在一个解决方案,但很惊讶网上关于这个主题的资源如此之少。很少有人会不同意,拥有一个像样的自定义 GUI 是不值得的。
  • 关键是在绘制框架之前先绘制窗口内容,但是Windows不会让你那样做。这就是为什么框架可以自行绘制框架的原因。
  • @Mark 感谢您的提示,我会将其应用到我的代码中。

标签: c++ user-interface custom-controls gdi+


【解决方案1】:

可能是 WM_ERASEBKGND 消息引起的吗?

看到这个问题:GDI+ double buffering in C++

另外,如果您需要 GUI 的快速响应,我建议您不要使用 GDI+。

【讨论】:

  • 是的,我确实做到了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
相关资源
最近更新 更多