我在内存中有一个由对话框模板制成的对话框类,它运行它自己的嵌套消息循环(除了主应用程序msg循环外)。
要创建对话框,请使用CreateDialogIndirectParamW
,它将句柄返回到对话框窗口
由于对话框是完全自定义的,因此所有消息处理和创建都是手动完成的。
我省略了Dialog过程,但是基本上,一旦对话框关闭,它将调用以下相关的消息处理程序。
请注意,我们不能使用EndDialog
函数破坏对话框并结束消息循环,因为对于CreateDialogIndirectParamW
,我们必须显式使用DestroyWindow
。
我正在寻找结束对话循环的有效方法。
我尝试实现this loop,但是问题在于这种方法会消耗过多的CPU资源,因为示例代码中的for
循环只会愚蠢地运行直到出现消息为止,或者如果{忽略{1}},然后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
失败。因为IsDialogMessageW(mhWnd,&msg)
不再存在。
mhWnd
请注意,我们不能int Dialog::RunmessageLoop()
{
EnableWindow(mhWndParent,FALSE);
MSG msg{ };
BOOL result = FALSE;
while ((result = GetMessageW(&msg,nullptr,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
。