2011-02-01 51 views
3

我正在写一个实用程序应用程序来通过我的GF的热键控制系统主音量,其笔记本电脑出于某种原因被剥夺了此类功能键。我非常快速地编写了代码,并且我的主要功能完美运行;然而,由于我没有创建任何窗口(只是一个处理WM_HOTKEY消息的消息循环),我不能以更优雅的方式终止应用程序,而不是无条件地终止该过程(同样,当系统关闭时,它显示了“我应该等待这个过程结束还是立即杀掉它”窗口,在窗口标题通常所在的位置有一些垃圾)。优雅地关闭WinAPI中的无窗口应用程序

有没有这样做的方法,不涉及创建一个假的窗口只是为了拦截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

你检查了你的笔记本电脑制造商的支持网站,看看他们是否已经提供这样的实用程序? – Ferruccio 2011-02-01 21:20:31

+0

我有,他们没有。这是惠普nx6110,它甚至没有按钮,正如我在问题中已经说过的那样。 – IneQuation 2011-02-07 17:26:39

回答

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()的作品无论申请者是否是一个控制台应用程序。

0

您可以随时在系统托盘中轻松地显示某些内容,从中可以优雅地关闭它。随着应用的增长,这可能是可取的,因为用户可能最终希望能够配置或更改热键,或暂时将其关闭,它会干扰其他应用程序等

,或者让其他热键,显示一个配置选项的小窗口?

+0

该应用程序不会增长,它只是一个小巧的私人应用程序,我特别要求提供无窗口解决方案。 – IneQuation 2011-02-07 17:12:56

1

查看ExitProcess API调用,以便优雅地关闭进程。要检测Windows关机,请在消息处理中包含WM_ENDSESSION。如果您的应用程序比发布的应用程序更复杂,那么您可能还需要查看ExitThread函数。

+0

感谢您提供此消息给我的关注,它会派上用场! – IneQuation 2011-02-07 17:11:58

1

您没有创建任何窗口,甚至没有隐藏窗口,所以没有办法通过向窗口发送消息来退出循环。也是WM_DESTROY永远不会触发的原因。

剩下的就是PostThreadMessage()来发布WM_QUIT。你必须能够以某种方式找到线程ID。使用Shell_NotifyIcon()将是明智的。

+0

是的,但a)我特别要求提供非假窗口解决方案,并且b)发布退出消息是没有问题的。问题在于处理外部请求以正常关闭应用程序。 – IneQuation 2011-02-07 16:44:04