在 Windows 系統中,Alt + Tab 組合鍵是用於在應用程式之間快速切換的系統級熱鍵。因此,其鍵盤訊息(WM_KEYDOWN/WM_KEYUP)會直接由系統核心處理,普通應用程式的訊息迴圈無法攔截到這些事件。
許多應用程式有這樣的需求:當使用者按下 Alt+Tab 將程式切換到背景時,需要執行特定邏輯(如儲存狀態、暫停播放、釋放資源等)。既然無法在標準訊息迴圈中捕獲,該如何實現?
透過 SetWindowsHookEx 設置全域鍵盤鉤子(WH_KEYBOARD_LL)可攔截所有鍵盤輸入。但此方式會導致效能下降、系統穩定性風險,且容易被防毒軟體誤判為惡意軟體行為。
使用 SetWinEventHook 函數監聽系統事件,專門針對視窗切換相關事件:
根據 MSDN 文件說明:
EVENT_SYSTEM_SWITCHSTART:系統發送此事件(伺服器從不發送)。回呼函數的
hwnd參數識別使用者即將切換到的視窗。若系統中僅有一個應用程式運行時按下 Alt+Tab,系統會直接發送EVENT_SYSTEM_SWITCHEND而不發送 START 事件。EVENT_SYSTEM_SWITCHEND:使用者釋放 Alt+Tab 時發送。
hwnd參數識別使用者已切換到的視窗。同樣,單一應用程式情況下不會有對應的 START 事件。
// 安裝事件鉤子
void InstallEventHook() {
g_hWinEventHook = ::SetWinEventHook(
EVENT_SYSTEM_SWITCHSTART,
EVENT_SYSTEM_SWITCHEND,
NULL, // DLL 句柄(進程外模式不需要)
s_HandleWinEvent, // 回呼函數
0, 0, // 進程與執行緒 ID(0 表示所有)
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS // 標誌
);
}
// 回呼函數
void CALLBACK s_HandleWinEvent(
HWINEVENTHOOK hook,
DWORD eventWin,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime
) {
switch (eventWin) {
case EVENT_SYSTEM_SWITCHSTART:
TRACE0(_T("[EVENT_SYSTEM_SWITCHSTART] ")); // Alt+Tab 被按下
break;
case EVENT_SYSTEM_SWITCHEND:
TRACE0(_T("[EVENT_SYSTEM_SWITCHEND] ")); // Alt+Tab 被釋放
break;
}
TRACE1(_T("hwnd=0x%.8x\n"), hwnd);
}
hwnd),便於進一步處理此方案完美解決了在應用程式失去焦點前執行邏輯的需求,是處理 Alt+Tab 切換事件的最佳實踐。