1

我正在尝试在 .NET Windows 窗体应用程序的 C++/CLI 库中创建渲染循环,但 PeekMessage 从未收到任何消息。所以我的渲染循环是无限的,表格看起来冻结了。

我已经尝试了几种方法,但这是我最后一次尝试。

开始渲染循环:

Application::Idle += gcnew EventHandler(this, &TECore::AppIdleHandler);

处理它的代码:

void TECore::AppIdleHandler(Object^ object, EventArgs^ e)
    {
        while (IsAppIdle())
            RenderLoopCallBack();
    }

    bool TECore::IsAppIdle()
    {
        LPMSG msg = {};
        return !PeekMessage(msg, (HWND)_targetForm->Handle.ToInt32(), 0, 0, 0);
    }

因此,如果我没有做错任何事情,我会不断检查来自我的 Windows 句柄的消息(也尝试过使用 NULL),否则我会渲染东西。但是窗口被冻结了,因为我从来没有收到任何消息,IsAppIdle 总是返回 true。我无法聚焦窗口,调整它的大小或任何东西..

非常感谢您的帮助。

编辑 1: 如果我在每一帧中执行 Application::DoEvent() ,它就会起作用。但是性能缺点是什么?

编辑 2:

我现在很确定我的 PeekMessage 没有收到任何消息,因为 RenderLoop 在类库中,而不是直接在 WindowForm 中。PeekMessage 直接在表单代码中正常工作。这是正常的行为吗?也许 C# 在加载 CLI 程序集时会自动将其加载到另一个线程上?所以我的 PeekMessage 正在寻找错误的线程?

4

1 回答 1

0

我发现了我的问题......只是一个语法错误。Intellisense 要求 LPMSG 作为 PeekMessage 的第一个参数(以前从未使用过),实际上我需要传递一个 MSG 指针。所以 PeekMessage 可能在沉默中失败了......

使用正确的语法,它可以正常工作。

错误的语法

bool TECore::IsAppIdle()
{
    LPMSG msg = {};
    return !PeekMessage(msg, NULL, 0, 0, 0);
}

正确的语法

bool TECore::IsAppIdle()
{
    MSG msg = {};
    return !PeekMessage(&msg, NULL, 0, 0, 0);
}
于 2017-04-01T11:56:12.620 回答