Winapi-WM_CLOSE的替代方案
Winapi - Alternatives to WM_CLOSE
我知道在Windows通知消息中,WM_CLOSE指的是通过窗口右上角的"X"按钮关闭窗口。
有人知道用文件->退出关闭的通知消息吗?
我之所以这么问,是因为我试图实现JNI本机代码,以便在用户启动系统关闭时优雅地关闭窗口。关于背景,请参阅我之前的文章(ShutdownBlockReasonCreate/Dedestroy中的Winapi-SetWindowLongPtr)。
当点击"X"关闭时,会出现确认对话框,防止关闭原因消息消失(当我希望它在一段时间后消失时)。我知道文件->从菜单栏退出不会要求确认,但我如何使用windows通知消息实现这一点?
经过一番挖掘,我发现的唯一建议是使用DestroyWindow。因此,我尝试使用DestroyWindow()函数关闭窗口,但它只是"销毁"窗口,而不是结束整个应用程序。这是我在WndProc回调函数中的switch语句:
switch (message) {
case WM_QUERYENDSESSION:
PostMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
case WM_ENDSESSION:
PostMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, AppWndProc, uIdSubclass);
break;
}
任何帮助都将不胜感激!
干杯
我知道在Windows通知消息中,WM_CLOSE指的是通过窗口右上角的"X"按钮关闭窗口。
实际上,当单击窗口的标准"X"按钮(或者如果启用,则选择窗口左上角菜单上的标准"关闭"项目,或者窗口接收到ALT+F4击键)时,会向窗口发出WM_SYSCOMMAND
消息,其中wParam
包含SC_CLOSE
标志。如果该消息被传递给DefWindowProc()
(默认行为),则它会向窗口发出WM_CLOSE
消息。
请参见关闭窗口。
其他条件也可能导致发布WM_CLOSE
消息。
有人知道用File->Exit关闭的通知消息吗?
选择该菜单项时发生的情况由应用程序而非操作系统定义。应用程序可以做任何它想做的事情,包括如果它想立即销毁窗口
然而,也就是说,如果菜单是标准Win32菜单,那么窗口将接收至少包含所选菜单项的ID的WM_COMMAND
消息。
我之所以这么问,是因为我试图实现JNI本机代码,以便在用户启动系统关闭时优雅地关闭窗口。
默认情况下,您不需要为此做任何事情。在系统关闭期间,操作系统会自动关闭所有打开的窗口。如果需要清理任何资源,您应该对窗口被关闭做出反应,而不是手动关闭窗口。
单击"X"关闭时,会出现确认对话框,以防止关闭原因消息消失(当我预计它会在一段时间后消失)。
则应用程序未正确处理系统关闭。
大多数应用程序响应于接收到WM_CLOSE
消息而呈现这样的确认框。如果确认中止,应用程序将丢弃消息并继续操作。但是,在系统关闭期间,应用程序不应提示用户进行确认。但并不是所有的应用程序都遵循这一规则。
我知道文件->从菜单栏退出不会要求确认
同样,这是由应用程序决定的,而不是由操作系统决定的。
如何使用windows通知消息实现此功能?经过一番挖掘,我发现的唯一建议是使用DestroyWindow。
正确。或者,您也可以将WM_QUIT
消息发布到消息队列中。请参阅PostQuitMessage()
函数。
所以我尝试使用DestroyWindow()函数关闭窗口,但它只是"销毁"窗口,而不是结束整个应用程序。
应用程序有责任终止自己,通常是在主窗口被破坏时退出消息循环。
这是我的WndProc回调函数中的switch语句:
无需发布WM_CLOSE
以响应WM_QUERYENDSESSION
或WM_ENDSESSION
。让操作系统为您处理。
如果你不想在系统关闭时出现确认,请将代码更改为类似以下内容:
bool shuttingDown = false;
LRESULT CALLBACK AppWndProc(
_In_ HWND hWnd,
_In_ UINT message,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ UINT_PTR uIdSubclass,
_In_ DWORD_PTR dwRefData
) {
switch (message) {
case WM_QUERYENDSESSION:
shuttingDown = true;
break;
case WM_ENDSESSION:
if (wParam == FALSE)
shuttingDown = false;
break;
case WM_CLOSE:
if (shuttingDown) {
DestroyWindow(hWnd);
// or:
// PostQuitMessage(0);
return 0;
}
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, AppWndProc, uIdSubclass);
break;
}
return DefSubclassProc(hWnd, message, wParam, lParam);
}
没有特定的消息来处理File>Exit。您必须将其作为任何其他菜单项处理:
- 为菜单项定义一个标识符。选择你想要的任何东西,它对windows没有特别的意义
- 构造菜单时,请在AppendMenu/InsertMenu/etc中指定此标识符。或在资源文件中
- 在窗口过程中,截取WM_COMMAND消息。如果
LOWORD(wParam)
与标识符相对应,则表示菜单项已被激活
处理退出命令的典型方法是发送WM_CLOSE消息,正如您在示例代码中已经做的那样。因此,您将避免代码重复,并确保无论用户选择如何退出应用程序,行为都是相同的(通过菜单,单击"x"或Alt+F4)
在处理WM_CLOSE时,您可以选择显示消息框、销毁窗口、发布退出消息或其他任何您想要的方式。默认情况下,DefWindowProc调用DestroyWindow,后者依次发送WM_DESTROY消息。请注意,当选择系统菜单的"关闭"项目时,WM_CLOSE也会被触发(Alt+Space或单击窗口标题旁边左侧的窗口图标)
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- 计算每个节点的树高,帮助我解释这个代码解决方案
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- visual c++,如何获取解决方案目录中的代码
- 有没有办法在远程设备上打开和编辑visual Studio 2017解决方案
- C++Matching Brackets 2解决方案不起作用
- 在 ubuntu3 上C++ goto 定义有什么解决方案吗16.04?
- C++11 中不同类型的对象的 std::array 的替代方案
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- 我的固定时间步长与增量时间和插值的解决方案是错误的吗?
- 无法在问题解决方案中执行输出逻辑
- 最大的回文产品 - 程序未运行,编写解决方案但无法理解问题
- 从预序遍历构造 bst 的 c++ 和 python 解决方案之间的区别
- 在一个解决方案中针对第三方静态库 (Creo) 的不同版本(版本)进行构建
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- N-queen问题:无法弄清楚为什么我的解决方案不起作用
- 从排序数组中删除重复项,具有不同代码方式的相同解决方案具有不同的输出