Registrieren einer Steuerelementhandler-Funktion

Beispiel für einfachen Steuerelementhandler

Dies ist ein Beispiel für die SetConsoleCtrlHandler-Funktion , die zum Installieren eines Steuerelementhandlers verwendet wird.

Wenn ein STRG+C-Signal empfangen wird, gibt der Steuerelementhandler TRUE zurück und gibt an, dass das Signal behandelt wurde. Dadurch wird verhindert, dass andere Steuerelementhandler aufgerufen werden.

Wenn ein CTRL_CLOSE_EVENT empfangen wird, gibt der Steuerelementhandler TRUE zurück, und der Prozess wird beendet.

Wenn ein CTRL_BREAK_EVENT, CTRL_LOGOFF_EVENT oder CTRL_SHUTDOWN_EVENT empfangen wird, gibt der Steuerelementhandler FALSE zurück. Dadurch wird das Signal an die nächste Steuerelementhandlerfunktion übergeben. Wenn keine anderen Steuerelementhandler registriert wurden oder keiner der registrierten Handler TRUE zurückgibt, wird der Standardhandler verwendet, was dazu führt, dass der Prozess beendet wird.

Hinweis

Durch Aufrufen von AttachConsole, AllocConsole oder FreeConsole wird die Tabelle der Steuerelementhandler im Clientprozess auf den Ausgangszustand zurückgesetzt. Handler müssen erneut registriert werden, wenn sich die angefügte Konsolensitzung ändert.

// 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;
}

Beispiel zum Lauschen mit ausgeblendeten Fenstern

Wenn die gdi32.dll- oder user32.dll-Bibliothek geladen wird, wird SetConsoleCtrlHandler nicht für die CTRL_LOGOFF_EVENT- und CTRL_SHUTDOWN_EVENT aufgerufen. Die angegebene Problemumgehung besteht in der Erstellung eines ausgeblendeten Fensters, wenn noch kein Fenster vorhanden ist, indem die CreateWindowEx-Methode mit dem dwExStyle-Parameter auf 0 (0) und das Lauschen auf die WM_QUERYENDSESSION- und WM_ENDSESSION-Fenstermeldungen festgelegt wird. Wenn bereits ein Fenster vorhanden ist, fügen Sie die beiden Meldungen der vorhandenen Fensterprozedur hinzu.

Weitere Informationen zum Einrichten eines Fensters und seiner Messagingschleife finden Sie unter Erstellen eines Fensters.

// 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;
    }
}