В приложении 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 +, GetForegroundWindow всегда возвращает дескриптор окна моего собственного приложения, независимо от того, как рано я его поместил, например, перехватывая основную очередь сообщений приложения. единственное жизнеспособное решение, хотя мне не очень нравится идея.)