C++ 在异常处理程序中,MessageBox()成功返回IDOK,但从未显示
我正在使用一个名为windows_error的自写异常类,该类继承自std::runtime_error,用于正确处理windows API函数中的意外错误 在调用堆栈的底部,在WinMain函数的末尾,我捕获了所有尚未处理的windows_错误异常。我打算在程序终止之前显示一条错误消息来处理它们,如下所示:C++ 在异常处理程序中,MessageBox()成功返回IDOK,但从未显示,c++,windows,winapi,exception-handling,C++,Windows,Winapi,Exception Handling,我正在使用一个名为windows_error的自写异常类,该类继承自std::runtime_error,用于正确处理windows API函数中的意外错误 在调用堆栈的底部,在WinMain函数的末尾,我捕获了所有尚未处理的windows_错误异常。我打算在程序终止之前显示一条错误消息来处理它们,如下所示: int WINAPI wWinMain(HINSTANCE inst, HINSTANCE prev, wchar_t *cmdline, int winshow) { // In
int WINAPI wWinMain(HINSTANCE inst, HINSTANCE prev, wchar_t *cmdline, int winshow)
{
// Initialize result to EXIT_FAILURE in case the program terminates due to
// an exception.
int result = EXIT_FAILURE;
try {
result = sIRC()();
}
catch (windows_error &e) {
e.basicHandler();
}
return result;
}
basicHandler成员函数如下所示:
void windows_error::basicHandler() const
{
std::wostringstream ss;
ss << L"An unexpected error has occurred in a Windows function.\n\n" \
L"Function " << m_api << L" was called by " << m_caller << L" in " << m_srcFile << L" at line " << m_srcLine << L". " \
L"It returned error " << m_error << L":\n\n" << m_errorMessage;
#ifdef _CONSOLE
std::wcout << L"\n" << ss.str();
#else
auto result = MessageBox(HWND_DESKTOP, ss.str().c_str(), L"Windows error!", MB_ICONERROR);
result = result; // I added this line so I can put a breakpoint in the debugger
#endif // _CONSOLE
}
void windows\u错误::basicHandler()常量
{
标准:WOSS;
在对我的问题的评论中,Raymond提供了我需要的提示。在堆栈展开过程中,我的user\u interface类的析构函数调用窗口句柄上的DestroyWindow,因为它在该点上仍然有效。我不知道的是MessageBox会解释生成的WM\u QUIT消息以关闭自己。我认为MessageBox有它自己的own内部消息队列
我可以通过修改我的用户界面类的析构函数来修复我的问题
它是:
if (_wnd)
DestroyWindow(_wnd);
我把它改成:
if (_wnd) {
DestroyWindow(_wnd);
MSG msg = MSG();
while (msg.message != WM_QUIT) {
GetMessage(&msg, 0, 0, 0);
}
}
这是可行的,但看起来有点难看。有什么改进的建议吗?队列中还会有一条离群的退出消息吗?哇,Raymond Chen回答了我的问题!我非常震惊。:-)嗯,在堆栈展开过程中,我的用户界面类的析构函数会调用主窗口句柄上的DestroyWindow,这是由窗口进程处理的我想MessageBox会创建它自己的消息队列吗?函数没有消息队列。线程有消息队列。你正处于这种情况,@RaymondChen谢谢,我现在很清楚了。你愿意评论一下我在回答中提出的修复方法吗?它看起来有点笨拙,但它是bes我对Windows API的理解是有限的。消息框有自己的消息循环,但每个线程只有一个队列。我想你可以启动一个单独的线程来显示消息框。@Harry,这似乎有点过分。:)谢谢你的评论。嗯,如果你在析构函数中这样做,那么你就可以即使在正常(无例外)的情况下,您也会丢弃消息,如果其他人想要其中一条消息,这不是一个好主意。(例如,用户执行了typeahead,在您的消息被销毁后将转到其他窗口。)此外,发布退出消息并立即删除它似乎毫无意义。wnd变量表示我的程序UI中的主窗口。没有其他窗口可供任何提前键入的文本访问。在正常、非异常情况下,运行析构函数时,\ wnd甚至不再是有效的窗口句柄。它将设置为NULL,即s它已在用户请求时被销毁。WM_QUIT将已被正常处理。我明白您所说的在异常情况下发布WM_QUIT是毫无意义的,但窗口过程被设置为调用PostQuitMessage()在处理WM_DESTROY时,我希望保持这种方式。没有任何有价值的东西会丢失。@RaymondChen:根据MSDN,DESTROY窗口会刷新线程的消息队列,所以可能只剩下退出消息了?或者我缺少了一个微妙的地方?