在应用程序崩溃的情况下,有很多方法可以确保Shell_NotifyIcon(NIM_DELETE, &m_tnd);
在 C++ 中调用;在您使用的RAII包装器上NOTIFYICONDATA
使用将完成工作,例如:
struct NID
{
NID() : icon_data() { icon_data.cbSize = sizeof(icon_data); }
~NID() { Shell_NotifyIcon(NIM_DELETE, &icon_data); }
void Show(HWND w) { icon_data.hWnd = w; Shell_NotifyIcon(NIM_ADD, &icon_data); }
NOTIFYICONDATA icon_data;
};
这是包装器的简化版本,但它将说明主要思想:如果您NID
在静态存储中创建一个实例,它将在WinMain
ormain
调用之前初始化,并且在程序清理时将调用其析构函数,即使此清理到期异常终止。
所以,我们可以用这种方式NOTIFYICONDATA
包装这个资源struct NID
:
NID nid; // <--- automatic storage duration, cleared after WinMain return
// even if it returns normal or abnormally
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
// GetMessage(&message, NULL, 0, 0) loop ...
// ...
// use nid.icon_data as you please
}
catch (...)
{
// something bad happened...
}
return 0;
}
上例调用~NID()
当程序终止时(异常后或关闭程序后),析构函数会调用Shell_NotifyIcon(NIM_DELETE, &icon_data);
,图标从通知区删除;此代码涵盖了正常终止和异常终止,您可以在NPE的这个好答案中阅读有关此主题的更多信息:
至于杀死进程的情况,没有简单的方法可以做到这一点。
我已经测试过了,std::atexit
并且std::at_quick_exit
在通过任务管理器杀死程序后不会调用函数,所以我想你必须挂钩终止调用......这似乎是一个非常复杂的任务,但在 BSH 的这个答案中进行了解释:
当一个进程终止(未关闭)时,除非你开始做一些挂钩,要么通过挂钩TerminateProcess
或NtTerminateProcess
在任务管理器进程中,否则什么都做不了
希望它有所帮助(虽然是 6 年后的答案,哈哈)