(我使用Ogre3D进行渲染,但问题应该是通用的。)
问题:大多数3D应用程序使用循环来迭代渲染帧并检查消息并处理它们。但是,如果打开一个对话框(MessageBox或类似的对象),它会阻止线程的执行并运行它自己的消息周期,但它显然不会调用其中的3D渲染函数。
即使对话框打开,保持渲染3D场景的首选或“最佳”方式是什么?普通的应用程序不会遇到这个问题,因为它们的重新渲染是由WM_PAINT消息等处理的,并且由于模态对话框确实有内部消息循环,所以在需要时调用窗口proc并且一切看起来都很好。然而,在我的3D项目中,“需要时”始终是,因为即使没有WM_PAINT消息,窗口也必须更新。
想到的简单解决方案是在对话框打开时注册计时器,并从WindowProc渲染3D场景,但它真的是最好的吗?看起来很脏......
答案 0 :(得分:2)
我不知道这是最好的方式,但我认为它会起作用。
为WM_ENTERIDLE添加一个处理程序,使用PeekMessage执行以下操作:
case WM_ENTERIDLE:
while (!PeekMessage())
{
DoYourRendering();
}
return 0;
答案 1 :(得分:1)
我建议让代码在进入模态操作时向自己发布自定义消息。然后,您可以在模态循环调度消息时呈现当前帧,然后发布另一条消息以保持渲染循环运行。模态操作完成后,您可以停止向自己发布消息并返回到正常的渲染逻辑。对于菜单,您可以捕获WM_ENTERMENULOOP
和WM_EXITMENULOOP
消息,以检测模式菜单消息循环何时开始和结束。
例如:
const UINT WM_RENDER_FRAME = WM_USER+100:
BOOL m_InModalOp = FALSE;
case WM_ENTERMENULOOP:
m_InModalOp = TRUE;
PostMessage(hwnd, WM_RENDER_FRAME, 0, 0);
break;
case WM_EXITMENULOOP:
m_InModalOp = FALSE;
break;
case WM_RENDER_FRAME:
if (m_InModalOp)
{
// render a frame...
PostMessage(hwnd, WM_RENDER_FRAME, 0, 0);
}
break;
m_InModalOp = TRUE;
PostMessage(hwnd, WM_RENDER_FRAME, 0, 0);
MessageBox(...);
m_InModalOp = FALSE;