2011-02-01 49 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