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;

Это работает, но хост получает уведомления только об изменении фокуса внутри самого приложения. На главной форме есть памятка и несколько кнопок TButton, и переключение фокуса между ними приводит к ожидаемому сообщению. Однако о любых изменениях фокуса вне самого приложения никогда не сообщается.

Я предполагаю, что это как-то связано с внедрением нескольких экземпляров DLL в другие процессы. Существует аналогичный вопрос с принятым ответом здесь , но он для C, и я не совсем понимаю, как я могу сделать то же самое в dll Delphi (например, операторы прагмы для настройки разделяемой памяти ).

(В основном это проверка концепции, но я все же хотел бы, чтобы она работала. Мне нужно знать, какое окно было активным непосредственно перед тем, как мое приложение было активировано с помощью нажатия, alt+tab, горячей клавиши активации и т. д. Проблема в том, что если используется мышь или alt+tab, GetForegroundWindow всегда возвращает дескриптор окна моего собственного приложения, независимо от того, как рано я его поместил, например, путем перехвата основной очереди сообщений приложения. решение, хотя идея мне не очень нравится.)

9
задан Community 23 May 2017 в 12:17
поделиться