我正在编写一个小实用程序应用程序,通过我的GF的热键控制系统主音量,其笔记本电脑由于某些原因被剥夺了这些功能键。我立刻掀起了代码,我的主要功能完美无缺;但是,由于我没有创建任何窗口(只是处理WM_HOTKEY消息的消息循环),我无法以更优雅的方式终止应用程序,而不仅仅是无理地终止进程(同样,当系统关闭时,它显示“我应该等待进程结束或立即终止它”窗口,窗口标题通常是一些垃圾。)
有没有办法做到这一点,只是为了拦截WM_CLOSE消息而不涉及创建假窗口?
这是代码(我故意省略了混音器控制功能,它们与问题无关):
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
MSG msg;
int step;
MixerInfo_t mi;
HANDLE mutex;
mutex = CreateMutex(NULL, TRUE, "volhotkey");
if (mutex == NULL)
return 1;
if (GetLastError() == ERROR_ALREADY_EXISTS)
return 0;
RegisterHotKey(NULL, 1, MOD_ALT | MOD_CONTROL, VK_F5);
RegisterHotKey(NULL, 2, MOD_ALT | MOD_CONTROL, VK_F6);
RegisterHotKey(NULL, 3, MOD_ALT | MOD_CONTROL, VK_F7);
mi = GetMixerControls();
step = (mi.maxVolume - mi.minVolume) / 20;
while (GetMessage(&msg, NULL, 0, 0)) {
switch (msg.message) {
case WM_HOTKEY:
switch (msg.wParam) {
case 1:
AdjustVolume(&mi, -step);
break;
case 2:
AdjustVolume(&mi, step);
break;
case 3:
SetMute(&mi, !IsMuted(&mi));
break;
}
MessageBeep(MB_ICONASTERISK);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
}
UnregisterHotKey(NULL, 1);
UnregisterHotKey(NULL, 2);
return msg.wParam;
}
提前致谢!
哦,为了记录,WM_DESTROY也从未发布过。
答案 0 :(得分:4)
您可以使用SetConsoleCtrlHandler()函数来侦听关闭事件。
SetConsoleCtrlHandler( ShutdownHandler, TRUE );
你的处理程序看起来像这样:
BOOL WINAPI ShutdownHandler( DWORD dwCtrlType )
{
if( dwCtrlType == CTRL_SHUTDOWN_EVENT || dwCtrlType == CTRL_LOGOFF_EVENT )
{
ExitProcess( 0 );
return TRUE; // just to keep the compiler happy
}
return FALSE;
}
尽管名称如此,但无论应用程序是否为控制台应用程序,SetConsoleCtrlHandler()都能正常工作。
答案 1 :(得分:1)
查看ExitProcess API调用,以便正常关闭进程。要检测Windows关闭,请在邮件处理中包含WM_ENDSESSION。如果您的应用程序比发布的内容更复杂,您可能还需要查看ExitThread函数。
答案 2 :(得分:1)
您没有创建任何窗口,甚至没有隐藏窗口,因此无法通过向窗口发送消息来退出循环。也是WM_DESTROY永远不会触发的原因。
剩下的就是PostThreadMessage()来发布WM_QUIT。你必须能够以某种方式找到线程ID。使用Shell_NotifyIcon()是明智的。
答案 3 :(得分:0)
您可以随时轻松地在系统托盘中显示某些内容,从而可以优雅地关闭它。随着应用程序的增长,这可能是可取的,因为用户最终可能希望能够配置或更改热键,或暂时将其关闭,以免干扰其他应用程序等。
或者有另一个热键显示带有配置选项的小窗口?