0

(我使用 Ogre3D 进行渲染,但问题应该是通用的。)

问题:大多数 3D 应用程序使用一个循环来迭代渲染帧并检查消息并处理它们。但是,如果打开一个对话框(MessageBox 或类似的),它会阻止线程的执行并运行它自己的消息循环,但它显然不会调用其中的 3D 渲染函数。

即使打开对话框,保持渲染 3D 场景的首选或“最佳”方式是什么?普通应用程序不会遇到这个问题,因为它们的重新渲染由 WM_PAINT 消息和类似消息处理,并且由于模式对话框确实具有内部消息循环,因此在需要时调用窗口 proc get 并且一切看起来都很好。然而,在我的 3D 项目中,“当需要时”一直是,因为窗口必须更新,即使没有 WM_PAINT 消息。

想到的简单解决方案是在对话框打开时注册一个计时器,并从 WindowProc 渲染 3D 场景,但这真的是最好的吗?好像很脏...

4

2 回答 2

3

我不知道这是最好的方法,但我认为它会起作用。

为WM_ENTERIDLE添加一个处理程序,该处理程序使用PeekMessage执行以下操作:

case WM_ENTERIDLE:
    while (!PeekMessage())
    {
        DoYourRendering();
    }
    return 0;
于 2012-08-08T21:09:23.260 回答
1

我建议在进入模态操作时让代码向自身发布一条自定义消息。然后,您可以在模态循环分派消息时渲染当前帧,然后发布另一条消息以保持渲染循环运行。模态操作完成后,您可以停止向自己发布消息并返回正常的渲染逻辑。对于菜单,您可以捕获WM_ENTERMENULOOPWM_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;
于 2012-08-08T21:36:32.483 回答