自定义对话框的结束嵌套消息循环

问题描述 投票:1回答:1

我在内存中有一个由对话框模板制成的对话框类,它运行它自己的嵌套消息循环(除了主应用程序msg循环外。)>

要创建对话框,我使用CreateDialogIndirectParamW将句柄返回到对话框窗口,

由于对话框是完全自定义的,因此所有消息处理和创建都是手动完成的。

我省略了Dialog过程,但是基本上,一旦对话框关闭,它将调用以下相关的消息处理程序。

注意,我们不能使用EndDialog函数破坏对话框和结束消息循环,因为对于CreateDialogIndirectParamW,我们必须显式使用DestroyWindow

我正在寻找结束对话框循环的有效方法。

我尝试实现this loop,但问题是该方法将消耗过多的CPU资源,因为示例代码中的for循环将一直愚蠢地运行直到出现消息为止,或者如果忽略了for,则PeekMessage将立即停止循环,这不是我想要的。

相关类声明:

class Dialog :
    public ContainerWindow,
    public MessageWindow,
    public SuperClassWindow
{
    // ...

public:
    /** Process messages for dialog window */
    [[nodiscard]] int RunMessageLoop() override;

protected:
    /** Handler for WM_NCDESTROY */
    std::uint32_t OnNcDestroy(const UINT& uMsg, const WPARAM& wParam, const LPARAM& lParam) override;

    /** Handler for WM_DESTROY */
    inline void OnDestroy() const noexcept override;

    /** Handler for WM_CLOSE */
    inline virtual bool OnClose() noexcept;

    // ...

protected:
        HWND mhWnd;                 /** Window handle of derived component */
    }

简化的类定义:

std::uint32_t Dialog::OnNcDestroy(
    [[maybe_unused]] const UINT& uMsg,
    [[maybe_unused]] const WPARAM& wParam,
    [[maybe_unused]] const LPARAM& lParam)
{
    // ...
    delete this; // note we can't set this pointer to nullptr!
    // ...
    return count;
}

void Dialog::OnDestroy() const noexcept
{
    PostQuitMessage(0);
}

bool Dialog::OnClose() noexcept
{
    return DestroyWindow(mhWnd);
}

这是对话框的消息循环

:我需要在循环中添加一些检查代码以检查对话框是否有效,也就是说,如果已删除对话框对象,则以某种方式停止循环

一旦调用OnNcDestroy处理程序,IsDialogMessageW以下将失败,请参见注释。

[看起来像GetMessageW将在分派WM_NCDESTROY之后继续运行,循环仍在等待WM_QUIT处理程序发送的OnDestroy,因此一旦删除Dialog对象,则味精循环将继续运行,这将使IsDialogMessageW(mhWnd, &msg)失败。因为mhWnd不再存在。

int Dialog::RunMessageLoop()
{
    EnableWindow(mhWndParent, FALSE);

    MSG msg{ };
    BOOL result = FALSE;

    while ((result = GetMessageW(&msg, nullptr, 0, 0)) != FALSE)
    {
        if (result == -1)
        {
            ShowError(ERR_BOILER); // error checking function.
            break;
        }

        // once OnNcDestroy is called "mhWnd" is invalid memory
        // and this will off course cause access violation!
        if (!IsDialogMessageW(mhWnd, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    }

    EnableWindow(mhWndParent, TRUE);

    return static_cast<int>(msg.wParam);
}

请注意,我们无法if (this),因为this不是nullptr,并且无法在nullptr处理程序中将其设置为OnNcDestroy

我在内存中有一个由对话框模板制成的对话框类,它运行它自己的嵌套消息循环(除了主应用程序msg循环外)。要创建对话框,我使用CreateDialogIndirectParamW,它返回...

c++ winapi
1个回答
0
投票

[确定,经过一段时间的试验,我对代码进行了以下更改,从而使所有功能都能正常工作! (请参阅评论以获取更多信息)

© www.soinside.com 2019 - 2024. All rights reserved.