SetWindowsHookEx создает локальный хук. Как сделать это глобальным?
В приложении Delphi XE я пытаюсь настроить глобальный хук для отслеживания изменений фокуса. Хук создан в dll:
focusHook := SetWindowsHookEx( WH_CBT, @FocusHookProc, HInstance, 0 );
// dwThreadId (the last argument) set to 0 should create a global hook
В той же DLL у меня есть процедура подключения, которая отправляет сообщение в окно приложения хоста:
function FocusHookProc( code : integer; wParam: WPARAM; lParam: LPARAM ) : LResult; stdcall;
begin
if ( code < 0 ) then
begin
result := CallNextHookEx( focusHook, code, wParam, lParam );
exit;
end;
result := 0;
if ( code = HCBT_SETFOCUS ) then
begin
if ( hostHWND <> INVALID_HANDLE_VALUE ) then
PostMessage( hostHWND, cFOCUSMSGID, wParam, lParam );
end;
end;
Это работает, но хост получает уведомления только об изменениях фокуса внутри самого приложения. На главной форме есть памятка и несколько кнопок, а переключение между ними приводит к ожидаемому сообщению. Однако о любых изменениях фокуса вне самого приложения никогда не сообщается.
Я предполагаю, что это как-то связано с несколькими экземплярами DLL, внедряемыми в другие процессы. Есть похожий вопрос с принятым ответомВот, но это для C, и я не могу понять, как я могу сделать то же самое в DLL Delphi (например, прагматические операторы для настройки общей памяти).
(Это в основном подтверждение концепции, но я все же хотел бы заставить ее работать. Мне нужно знать, какое окно было активным непосредственно перед тем, как мое приложение было активировано, с помощью нажатия, alt + tab, горячей клавиши активации и т. Д. Проблема является то, что если используется мышь или Alt + Tab, GetForegroundWindow всегда возвращает дескриптор окна моего собственного приложения, независимо от того, как рано я его поставил, например, перехватывая основную очередь сообщений приложения. Таким образом, ловушка кажется единственным жизнеспособным решением, хотя Мне не очень нравится идея.)