Добавленная информация:
Когда я использую мой .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 + вкладки для других приложений.
То же самое, если я ставлю точки останова в методах. Это никогда не ломается внутри tabEventProc, но все время в двух других методах.
Может кто-нибудь сказать, пожалуйста, что я делаю не так? Потому что Google Ван Кеноби не смог мне помочь. И я действительно сбит с толку.
Я использую Windows 10 и Visual Studio 2017 Community Edition. Проект представляет собой стандартный консольный проект C ++, созданный на основе шаблона «Создать новый проект» в Visual Studios.
Хорошо. Так что я полагаю, что для того, чтобы обнаружение 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.
Других решений пока нет …