SetWindowsHookEx cria um gancho local. Como torná-lo global?
Em um aplicativo Delphi XE, estou tentando configurar um gancho global para monitorar as alterações de foco. O gancho é criado em uma dll:
focusHook := SetWindowsHookEx( WH_CBT, @FocusHookProc, HInstance, 0 );
// dwThreadId (the last argument) set to 0 should create a global hook
Na mesma dll, tenho o procedimento de gancho que publica uma mensagem na janela do aplicativo host:
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;
Isso funciona, mas o host recebe apenas notificações sobre alterações de foco no próprio aplicativo. Há um memorando e alguns TButtons no formulário principal, e alternar o foco entre eles produz a mensagem esperada. No entanto, qualquer alteração de foco fora do próprio aplicativo nunca é relatad
Suponho que tenha algo a ver com várias instâncias da DLL sendo injetadas em outros processos. Há uma pergunta semelhante com uma resposta aceitaaqu, mas é para C e não consigo ver como posso fazer o mesmo em uma DLL Delphi (por exemplo, as instruções pragma para configurar a memória compartilhada
(Essa é principalmente uma prova de conceito, mas eu ainda gostaria de fazê-la funcionar. Preciso saber qual janela estava ativa pouco antes de meu aplicativo ser ativado por meio de cliques, alt + tab, tecla de atalho de ativação etc. O problema é que, se o mouse ou a tecla alt + tab são usados, o GetForegroundWindow sempre retorna o identificador da janela do meu aplicativo, não importando o quão cedo eu o indique, como conectar a fila de mensagens principal do aplicativo. embora eu realmente não goste da ideia.)