gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 12:30:49 24 4
gpt4 key购买 nike

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

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

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

我省略了 Dialog 过程,但基本上它会在对话框关闭后调用下面相关的消息处理程序。

请注意,我们不能使用 EndDialog函数销毁对话框并结束消息循环,因为 CreateDialogIndirectParamW我们必须使用 DestroyWindow明确地。

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

我尝试执行 this loop但问题是自 for 以来,这种方法要么消耗过多的 CPU 资源。示例代码中的循环将只是愚蠢地运行,直到有一条消息,或者如果 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_QUITOnDestroy 发送处理程序,因此一旦 Dialog 对象被删除,msg 循环将继续运行,这将使 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并且不能设置为 nullptrOnNcDestroy处理程序。

最佳答案

好的,经过一段时间的试验后,我对代码进行了以下更改,使一切正常运行! (更多信息见评论)

顺便说一句。我将保留这个问题,希望有更有效的方法,目前 IsWindow 为每条消息调用,这可能是一个性能问题。

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

MSG msg{ };
BOOL result = FALSE;

// first we save the handle to the window
HWND hwnd = mhWnd;
if (!IsWindow(hwnd)) // make sure the handle is valid dialog window
std::abort();

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

// if object is deleted the handle is no longer valid!
// because prior to OnNcDestroy handler DestroyWindow has been called
if (!IsWindow(hwnd))
goto invalid;

if (!IsDialogMessageW(mhWnd, &msg))
{
invalid: // non dialog message processing
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}

// NOTE that we removed EnableWindow(mHwndParent) here!

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

这本身就可以工作,但一个额外的步骤是在销毁对话框之前启用所有者窗口(主窗口),因此更新处理程序:

bool Dialog::OnClose() noexcept
{
// otherwise first window in Z order (such as Desktop) will get focus!
EnableWindow(mhWndParent, TRUE);

return DestroyWindow(mhWnd);
}

关于c++ - 结束自定义对话框的嵌套消息循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58692019/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com