Системные события EVENT_SYSTEM_SWITCHSTART и EVENT_SYSTEM_SWITCHEND работают в Windows 7, но не в Windows 10

Добавленная информация:
Когда я использую мой.exe файл в Windows 7, все работает как надо. Это не работает в Windows 10. И я не могу понять, почему.

Исходное сообщение:
Возможно, мне просто нужно больше кофе...... но я пытаюсь написать небольшую программу, которая будет прослушивать события Alt+Tab. Поэтому я добавил SetWinEventHook для прослушивания EVENT_SYSTEM_SWITCHSTART и EVENT_SYSTEM_SWITCHEND. Так как я решил, что это способ сделать это в соответствии с MSDN: SetWinEventHook, обратный вызов WinEventProc, константы событий.

По какой-то причине эти события никогда не происходят. Но, скорее всего, я что-то упустил.

Когда я не запустил его в свое реальное приложение, я создал это небольшое приложение для его тестирования. И оно там тоже не работает. Но другие события работают. EVENT_SYSTEM_FOREGROUND, EVENT_OBJECT_CREATE и EVENT_OBJECT_DESTROY происходят постоянно.

Код моего небольшого тестового приложения:

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

namespace
{
    HWINEVENTHOOK sTabHook;
    HWINEVENTHOOK sFocusHook;
    HWINEVENTHOOK sCreateHook;
}

void CALLBACK tabEventProc(HWINEVENTHOOK hook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
    printf("Never happens!");
    if (EVENT_SYSTEM_SWITCHSTART == event)
    {
        printf("Tab start\n");
    }
    else if (EVENT_SYSTEM_SWITCHEND == event)
    {
        printf("Tab end\n");
    }
}

void CALLBACK focusEventProc(HWINEVENTHOOK hook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
    printf("Window focused\n");
}

void CALLBACK createEventProc(HWINEVENTHOOK hook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
    if (EVENT_OBJECT_CREATE == event)
    {
        printf("Object created\n");
    }
    else if (EVENT_OBJECT_DESTROY == event)
    {
        printf("Object destroyed\n");
    }
}

DWORD WINAPI threadProc()
{
    sTabHook = SetWinEventHook(EVENT_SYSTEM_SWITCHSTART, EVENT_SYSTEM_SWITCHEND, nullptr, tabEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); //no ice, no napkins, no soda, no salt, no pepper... no quaso, NOTHING!
    sFocusHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, nullptr, focusEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
    sCreateHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_DESTROY, nullptr, createEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);

    MSG message;
    while (GetMessage(&message, nullptr, 0, 0)) {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }

    UnhookWinEvent(sTabHook);
    UnhookWinEvent(sFocusHook);
    UnhookWinEvent(sCreateHook);

    return 0;
}

int main()
{
    HANDLE threadHandle;
    DWORD thread;

    threadHandle = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)threadProc, 0, 0, &thread);
    if (threadHandle)
    {
        return WaitForSingleObject(threadHandle, INFINITE);
    }
    else
    {
        return 1;
    }

    return 0;
}

Я получаю много распечаток из методов focusEventProc и createEventProc при нажатии на окна и открытии / закрытии окон. Но нет распечаток из tabEventProc, когда alt + tabbing для других приложений.

То же самое, если я ставлю точки останова в методах. Он никогда не ломается внутри tabEventProc, но все время в двух других методах.

Может кто-нибудь сказать, пожалуйста, что я делаю не так? Потому что Google Ван Кеноби не смог мне помочь. И я действительно сбит с толку.

Я использую Windows 10 и Visual Studio 2017 Community Edition. Проект представляет собой стандартный консольный проект C++, созданный на основе шаблона "Создать новый проект" в Visual Studios.

1 ответ

Решение

Хорошо. Так что я полагаю, что для того, чтобы обнаружение Alt-Tab работало в Windows 10, вы должны соответствовать уродливым хаки

Это уродливое решение, с которым я закончил:

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <string>

namespace
{
    HINSTANCE sInstance = GetModuleHandle(nullptr);
    HHOOK sTabHook;
    HWINEVENTHOOK sFocusHook;
    bool sAltTabHappend = false;
}

LRESULT CALLBACK tabEventProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    auto kbdLlHookStruct = (KBDLLHOOKSTRUCT*)lParam;

    switch (nCode)
    {
        case HC_ACTION:
        {
            if (kbdLlHookStruct->vkCode == VK_TAB && kbdLlHookStruct->flags & LLKHF_ALTDOWN)
            {
                printf("Alt-Tab\n");
                sAltTabHappend = true;
            }
        }
    }


    return CallNextHookEx(sTabHook, nCode, wParam, lParam);
}

void CALLBACK focusEventProc(HWINEVENTHOOK hook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
    if (!sAltTabHappend)
    {
        return;
    }

    char windowTitleOut[256];
    GetWindowTextA(hwnd, windowTitleOut, sizeof(windowTitleOut));
    std::string windowTitle(windowTitleOut);

    if (windowTitle.empty() || 0 == windowTitle.compare("Task Switching"))
    {
        return;
    }

    printf("You just canged to %s by Alt-tabbing... yeah...\n", windowTitleOut);
    sAltTabHappend = false;
}

DWORD WINAPI threadProc()
{
    sTabHook = SetWindowsHookEx(WH_KEYBOARD_LL, tabEventProc, sInstance, 0);
    sFocusHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, nullptr, focusEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);

    MSG message;
    while (GetMessage(&message, nullptr, 0, 0)) {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }

    UnhookWindowsHookEx(sTabHook);
    UnhookWinEvent(sFocusHook);

    return 0;
}

int main()
{
    HANDLE threadHandle;
    DWORD thread;

    threadHandle = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)threadProc, 0, 0, &thread);
    if (threadHandle)
    {
        return WaitForSingleObject(threadHandle, INFINITE);
    }
    else
    {
        return 1;
    }

    return 0;
}

Поэтому вместо подключения к EVENT_SYSTEM_SWITCHSTART и EVENT_SYSTEM_SWITCHEND я подключаюсь к WH_KEYBOARD_LL с помощью SetWindowsHookEx. Затем я проверяю комбинации клавиш Alt+Tab. Если это произойдет, я сохраняю это в статической переменной и в EVENT_SYSTEM_FOREGROUND проверяю, было ли ранее нажатие Alt+Tab, а затем предполагаю, что мы Alt+Tab переключились на это окно.

Я действительно ненавижу это решение, так как оно не гарантирует, что сфокусированное окно - это то, к которому мы переключились. Должен быть лучший способ.

И это не отвечает на вопрос, почему EVENT_SYSTEM_SWITCHSTART и EVENT_SYSTEM_SWITCHEND не работают в Windows 10.

Другие вопросы по тегам