2013-10-07 19 views
0

我有一个使用WS_EX_LAYERED窗口样式创建的窗口。我正在使用GDI +绘制内存位图,并使用UpdateLayeredWindow来更新我的分层窗口的图形内容。我打算使用这个窗口作为我的应用程序的主窗口,这将需要经常重绘。重绘分层窗口的正确方法

作为分层窗口看到没有收到WM_PAINT窗口消息[?],我需要拿出一个合适的方法重新绘制窗口。优化不是必不可少的,但它总是很高兴有你的蛋糕和吃它。因此,我正在寻找使用“正确”的方法。

这里是我的想法至今:

  • 我猜想,这是一个好主意之前BitBlt ING或相似的呈现到离屏位图。

  • 每秒渲染60帧应该足够多(但是与其他应用程序的帧速率相比如何?)。

可能的解决方案:

  • 使用SetTimer发送定期的WM_TIMER消息。

    • 有用的,因为通过指定超时值,我可以实现每秒我的所需帧,而不需要测量的持续时间的“帧”需要被渲染。

    • 由于消息的频率和速度可能会导致输入或其他滞后。

  • 仅当发生特定事件(例如窗口大小调整)时才渲染帧。

    • 需要我找出所有需要重绘的事件。

    • 会大大减少不必要的帧的渲染量。

  • 渲染帧时,有在消息队列中没有消息,通过检查PeekMessage

    • 可能减缓窗口消息处理。

    • 这将导致CPU使用率过高,因为正在处理的帧数多于所需的帧数。

  • 创建一个新的线程来执行渲染循环。

    • 为了保持稳定的帧速率,必须执行定时计算。
+0

被卡住到UpdateLayeredWindow?使用SetLayeredWindowAttributes可以创建一个带WM_PAINT的分层窗口。如果使用这种方式,你摆脱了准备更新机制的问题。 “ – xMRi

+1

”这与其他应用程序的帧速率相比如何?“除非应用程序正在动画或显示视频,否则其帧速率通常为零。无缘无故地反复重画屏幕就是从更高效的使用中窃取CPU时间,压平笔记本电脑电池,磨损粉丝并使自己成为卸载目标。严重的是,如果你的应用程序没有做任何事情,不要做任何事情。 – arx

回答

0

它不应该这么复杂,这是给你的消息循环的伪代码:

while (true) 
{ 
    // GetMessages 
    while (PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE)) 
    { 
     if (!GetMessage(&msg, hWnd, 0, 0)) 
     { 
      // Need to handle WM_QUIT 
      ... 
      break; 
     } 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    // Check if we need to draw 
    if (TimeForANewFrameHasCome() || 
     IfWeNeedToDrawAfterInputOrInvalidate() || 
     AnyOtherCaseThatCausesAnUpdate()) 
    { 
     // Render 
     UpdateMemoryDCOrBitmap(...); 

     // Display it 
     UpdateLayeredWindow(...); 
    } 

    // May sleep a while 
    // Either Sleep(20); or better MsgWaitForMultipleObjects, that makes it possible 
    // to wake up upon an Event too... 
    MsgWaitForMultipleObjects(...); 
} 
+0

你为什么一起使用'PeekMessage(PM_NOREMOVE)'和'GetMessage()'?如果您使用'PeekMessage(PM_REMOVE)',则完全不需要'GetMessage()'。如果没有什么可以查看的话,'PeeMessage()'返回FALSE,所以'while'循环仍然有效。 –

+0

我同意。但通过这种方式,我不必为WM_QUIT使用额外的处理。是的,您可以使用PM_REMOVE并在查看后检查WM_QUIT。这是一个风格问题。 – xMRi

+0

嗯,我们来看看... peek +删除一条消息并直接查看它的ID - vs - 查看一条消息,但将它留在队列中,然后返回队列并查看和删除相同的消息,并获得API看看你的ID并返回一个你必须检查的BOOL。是的,同样的效果......但更多的代码和API的工作。但正如你所说,这只是“风格问题”。就我个人而言,我认为API不应该做更多的工作,但这只是我的风格:) –

1

分层的窗口不会收到WM_PAINT消息,否则将可视窗口之后产生改变了,但它不会阻止他们收到此消息。

您可以继续使用InvalidateRect更改窗口更新区域,在您的窗口程序中等待WM_PAINT,在位图中绘制内容并调用UpdateLayeredWindow更改窗口内容。例如,当按下按钮或窗口已调整大小(或激活/禁用)时,可以使用此方法请求重绘。