我在内存中有一个由对话框模板制成的对话框类,它运行它自己的嵌套消息循环(除了主应用程序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,它返回...
[确定,经过一段时间的试验,我对代码进行了以下更改,从而使所有功能都能正常工作! (请参阅评论以获取更多信息)