User interface 当图像未被覆盖时,绘制图像时会显示背景色条带 我有一个显示图像的WxWiWdsC++应用程序。当图像被另一个窗口遮住时,我非常缓慢地拖动另一个窗口来揭开图像,图像经常显示未绘制的背景色带

User interface 当图像未被覆盖时,绘制图像时会显示背景色条带 我有一个显示图像的WxWiWdsC++应用程序。当图像被另一个窗口遮住时,我非常缓慢地拖动另一个窗口来揭开图像,图像经常显示未绘制的背景色带,user-interface,graphics,wxwidgets,User Interface,Graphics,Wxwidgets,图像位于位图中,并在滚动窗格中呈现。OnPaint函数尽可能简单。无论我使用true还是false作为DrawBitmap的最后一个参数(“use_mask”),行为都是相同的 我试着使用wxBufferedPaintDC。问题依然存在。我能做些什么 在下图中,我刚刚将Firefox窗口缓慢向右拖动, 显示我的应用程序的图片 我正在Windows7服务包1上测试这个。AMD A6-3620 APU,带Radeon(tm)高清图形2.2 GHz。VC++2012。wxWidgets 2.9.4.

图像位于位图中,并在滚动窗格中呈现。OnPaint函数尽可能简单。无论我使用true还是false作为DrawBitmap的最后一个参数(“use_mask”),行为都是相同的

我试着使用wxBufferedPaintDC。问题依然存在。我能做些什么

在下图中,我刚刚将Firefox窗口缓慢向右拖动, 显示我的应用程序的图片


我正在Windows7服务包1上测试这个。AMD A6-3620 APU,带Radeon(tm)高清图形2.2 GHz。VC++2012。wxWidgets 2.9.4.

禁用擦除背景事件。当wxWidgets想要更新显示时,它会发出两个事件:擦除背景事件和绘制事件。必须为erase background事件实现一个空方法(换句话说:截获EVT_erase_background事件并不调用event.Skip()

由于位图覆盖整个面板,因此不需要擦除背景

使用wxClientDC对您有效的原因是“在EVT_PAINT()处理程序中使用wxPaintDC会自动将剪裁区域设置为窗口的损坏区域。在该区域之外绘制的尝试不会出现。”

由于剪裁区域存在问题,忽略剪裁区域“解决”了问题

这在wxPaintDC和wxClientDC类参考文档的详细描述部分进行了介绍


下面是一个“更好”答案的草图。这比计时器和重绘所有解决方案要复杂得多,但从节省系统资源的意义上讲,它会更好,因此应用程序的响应性会更高

需要两件事

  • 快速显示位图的方法

  • 仅重新绘制位图的损坏区域

  • (注意:在wxPaintDC上使用DrawBitmap实际上是处理整个位图,然后剪辑输出)

    为了加快位图部分的显示速度,您需要将位图绘制到内存DC中,并将其放在某个方便的地方(此解决方案不节省内存,但这通常不是现代计算机的问题),以便您可以将所需的位图部分blit到wxPaintDC中

    wxMemoryDC memdc;
    memdc.SelectObject(bitmap);
    dc.Blit( ...
    
    以下是Blit参数的描述

    要仅处理受损区域,需要调用GetUpdateRegion并使用区域迭代器通过reutun进行工作。我看到您使用的是滚动面板,因此您必须考虑到这一点,因为更新区域是窗口中的客户端区域,而不是位图中的逻辑区域

     wxRegionIterator upd(GetUpdateRegion());
     while ( upd )
     {  wxRect rect(upd,GetRect());
        // calculate damaged rectangle in terms of your complete bitmap
        ...
        // blit the calculated rectangle from bitmap in memoryDC to damaged recatngle in wxPaintDC
        ...
    
        upd++;
     {
    

    这是版本2.9.4中的一个bug。在以前的稳定版本2.8.12中不存在此功能。它似乎只影响滚动窗口

    目前最好的解决方案可能是使用build 2.8.12。如果这不实际,可以通过使用wxClientDC绘制整个图像来解决此问题。最好只是偶尔做一次。我想出了一个启发式方法来确定何时可能遗漏一条条纹。它基于保存更新区域的最新历史记录。它会出现误报,但不会引起闪烁,至少在我的机器上是这样

    当我知道更多的时候,我会发布更多

    更新Eric Jensen报告说,另一个解决方法是重写OnDraw方法进行绘制,而根本不使用on-paint处理程序

    使用Windows Aero主题时,更新问题不会表现出来


    修正了-

    Oops。这破坏了应用程序。有些背景有时会暴露出来。它必须被清除。我会试着用刷子在背景或油漆上刷它。哦,该死的。我删除了答案中的更新部分,因为我发现使用ClientDC会导致很多闪烁。我们的编辑遇到了问题。谢谢你的信息,谢谢你。我很遗憾地说,这是行不通的。我已经确定缺陷在更新区域本身。它们被正确地涂上了。有时一个太小,或者一个不知怎的迷路了。我把它带到了wxWidgets论坛。阅读所有关于它的信息。你似乎很了解wx的内部工作原理。它是如何产生这些更新区域的?它是直接从Windows本机调用或事件获取它们,还是以某种方式计算它们?(我很困惑为什么wx不只是从Windows使用CPaintDC。)如果您能告诉我在wx源代码中的位置,我将不胜感激。我试着用调试器进行调试,但很快就不知所措了。更新“错误”的原因是您的绘制处理程序花费的时间太长。如果将睡眠添加到绘制处理程序中,您可以在任何应用程序中看到这种情况。解决方案是优化绘制处理程序。
     wxRegionIterator upd(GetUpdateRegion());
     while ( upd )
     {  wxRect rect(upd,GetRect());
        // calculate damaged rectangle in terms of your complete bitmap
        ...
        // blit the calculated rectangle from bitmap in memoryDC to damaged recatngle in wxPaintDC
        ...
    
        upd++;
     {