Системные события 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.