註冊控制處理常式函式
基本控件處理程式範例
這是用來安裝控件處理程式的 SetConsoleCtrlHandler 函式範例。
收到 CTRL+C 訊號時,控件處理程式會 傳回 TRUE,表示已處理訊號。 這樣做可防止呼叫其他控制件處理程式。
收到CTRL_CLOSE_EVENT訊號時,控制處理程式會傳回 TRUE,而進程會終止。
收到CTRL_BREAK_EVENT、CTRL_LOGOFF_EVENT或CTRL_SHUTDOWN_EVENT訊號時,控制處理程式會傳回 FALSE。 這樣做會使訊號傳遞至下一個控制處理程式函式。 如果尚未註冊其他控件處理程式,或未傳回任何已註冊的處理程式傳回 TRUE,則會使用預設處理程式,導致進程終止。
注意
呼叫 AttachConsole、AllocConsole 或 FreeConsole 會將客戶端進程中的控制處理程式數據表重設為其初始狀態。 附加的主控台工作階段變更時,必須再次註冊處理程式。
// CtrlHandler.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <windows.h>
#include <stdio.h>
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
{
switch (fdwCtrlType)
{
// Handle the CTRL-C signal.
case CTRL_C_EVENT:
printf("Ctrl-C event\n\n");
Beep(750, 300);
return TRUE;
// CTRL-CLOSE: confirm that the user wants to exit.
case CTRL_CLOSE_EVENT:
Beep(600, 200);
printf("Ctrl-Close event\n\n");
return TRUE;
// Pass other signals to the next handler.
case CTRL_BREAK_EVENT:
Beep(900, 200);
printf("Ctrl-Break event\n\n");
return FALSE;
case CTRL_LOGOFF_EVENT:
Beep(1000, 200);
printf("Ctrl-Logoff event\n\n");
return FALSE;
case CTRL_SHUTDOWN_EVENT:
Beep(750, 500);
printf("Ctrl-Shutdown event\n\n");
return FALSE;
default:
return FALSE;
}
}
int main(void)
{
if (SetConsoleCtrlHandler(CtrlHandler, TRUE))
{
printf("\nThe Control Handler is installed.\n");
printf("\n -- Now try pressing Ctrl+C or Ctrl+Break, or");
printf("\n try logging off or closing the console...\n");
printf("\n(...waiting in a loop for events...)\n\n");
while (1) {}
}
else
{
printf("\nERROR: Could not set control handler");
return 1;
}
return 0;
}
使用隱藏視窗範例接聽
根據備註,如果載入 gdi32.dll 或 user32.dll 連結庫, SetConsoleCtrlHandler 就不會針對 CTRL_LOGOFF_EVENT 和 CTRL_SHUTDOWN_EVENT 事件呼叫。 指定的因應措施是呼叫 createWindowEx 方法,並將 dwExStyle 參數設定為 0 並接聽WM_QUERYENDSESSION和WM_ENDSESSION視窗訊息,以建立隱藏視窗。 如果視窗已經存在,請將這兩則訊息新增至現有的 視窗程式。
如需設定視窗及其傳訊循環的詳細資訊,請參閱 建立視窗。
// CtrlHandler.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <Windows.h>
#include <stdio.h>
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
{
switch (fdwCtrlType)
{
// Handle the CTRL-C signal.
case CTRL_C_EVENT:
printf("Ctrl-C event\n\n");
Beep(750, 300);
return TRUE;
// CTRL-CLOSE: confirm that the user wants to exit.
case CTRL_CLOSE_EVENT:
Beep(600, 200);
printf("Ctrl-Close event\n\n");
return TRUE;
// Pass other signals to the next handler.
case CTRL_BREAK_EVENT:
Beep(900, 200);
printf("Ctrl-Break event\n\n");
return FALSE;
case CTRL_LOGOFF_EVENT:
Beep(1000, 200);
printf("Ctrl-Logoff event\n\n");
return FALSE;
case CTRL_SHUTDOWN_EVENT:
Beep(750, 500);
printf("Ctrl-Shutdown event\n\n");
return FALSE;
default:
return FALSE;
}
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_QUERYENDSESSION:
{
// Check `lParam` for which system shutdown function and handle events.
// See https://learn.microsoft.com/windows/win32/shutdown/wm-queryendsession
return TRUE; // Respect user's intent and allow shutdown.
}
case WM_ENDSESSION:
{
// Check `lParam` for which system shutdown function and handle events.
// See https://learn.microsoft.com/windows/win32/shutdown/wm-endsession
return 0; // We have handled this message.
}
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
int main(void)
{
WNDCLASS sampleClass{ 0 };
sampleClass.lpszClassName = TEXT("CtrlHandlerSampleClass");
sampleClass.lpfnWndProc = WindowProc;
if (!RegisterClass(&sampleClass))
{
printf("\nERROR: Could not register window class");
return 2;
}
HWND hwnd = CreateWindowEx(
0,
sampleClass.lpszClassName,
TEXT("Console Control Handler Sample"),
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
nullptr,
nullptr,
nullptr,
nullptr
);
if (!hwnd)
{
printf("\nERROR: Could not create window");
return 3;
}
ShowWindow(hwnd, SW_HIDE);
if (SetConsoleCtrlHandler(CtrlHandler, TRUE))
{
printf("\nThe Control Handler is installed.\n");
printf("\n -- Now try pressing Ctrl+C or Ctrl+Break, or");
printf("\n try logging off or closing the console...\n");
printf("\n(...waiting in a loop for events...)\n\n");
// Pump message loop for the window we created.
MSG msg{};
while (GetMessage(&msg, nullptr, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
else
{
printf("\nERROR: Could not set control handler");
return 1;
}
}