Регистрация функции обработчика команд управления
Базовый пример обработчика элементов управления
Это пример функции 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;
}
}