win32 usar tutorial introduccion español ejemplos como winapi mfc

winapi - usar - ¿Cómo puedo monitorear qué ventana tiene actualmente foco de teclado?



winapi tutorial (7)

¿Hay alguna manera de rastrear qué ventana tiene actualmente el foco del teclado? Podría manejar WM_SETFOCUS para cada ventana pero me pregunto si hay un método alternativo, más simple (es decir, un manejador de mensajes único en alguna parte).

Podría usar OnIdle () en MFC y llamar a GetFocus (), pero eso parece un poco hacky.



Bueno, esto puede no ser muy elegante ... pero puedes recuperar el control enfocado actual con bastante facilidad. Entonces, podría considerar configurar un temporizador que pregunte cada 1/2 segundo más o menos "¿Dónde está el foco actual?" ... Entonces puede observar los cambios. Ejemplo de código Delphi está abajo; debería ser bastante fácil de adaptar, ya que el trabajo real está en las llamadas a la API de Windows.

<snip> function TForm1.GetCurrentHandle: integer; var activeWinHandle: HWND; focusedThreadID : DWORD; begin //return the Windows handle of the currently focused control Result := 0; activeWinHandle := GetForegroundWindow; focusedThreadID := GetWindowThreadProcessID(activeWinHandle,nil); if AttachThreadInput(GetCurrentThreadID,focusedThreadID,true) then begin try Result := GetFocus; finally AttachThreadInput(GetCurrentThreadID, focusedThreadID, false); end; end; //if attached end; procedure TForm1.Timer1Timer(Sender: TObject); begin //give notification if the handle changed //(this code gets fired by a timer) CurrentHandle := GetCurrentHandle; if CurrentHandle <> PreviousHandle then begin Label1.Caption := ''Last focus change occurred @ '' + DateTimeToStr(Now); end; PreviousHandle := CurrentHandle; end; <snip>


Entonces, por la forma en que redactó la pregunta, infiero que desea tener un controlador de eventos que se invoca cada vez que se cambia de foco entre ventanas. Desea que lo notifiquen, en lugar de tener que sondear.

De hecho, no creo que llamar a GetFocus desde OnIdle es mucho más un hack, seguro que es un sondeo, pero es un sondeo bajo sin efectos secundarios, pero si realmente quieres hacer un seguimiento de esto, Windows Hooks es probablemente tu mejor opción. Específicamente, puede instalar un gancho CBT (WH_CBT) y escuchar la notificación HCBT_SETFOCUS.

Windows llama al enlace WH_CBT con este código de enlace cuando Windows está a punto de establecer el foco en cualquier ventana. En el caso de ganchos específicos de subprocesos, la ventana debe pertenecer al subproceso. Si la función de filtro devuelve TRUE, el enfoque no cambia.

También podría hacerlo con un enlace WH_CALLWNDPROC y escuchar el mensaje WM_SETFOCUS.

Dependiendo de si lo convierte en un gancho global o local de aplicación, puede rastrear el enfoque en todas las ventanas del sistema, o solo en las ventanas que pertenecen a su proceso.


Existe una manera sencilla de utilizar .Net Framework 3.5: la UI de la biblioteca Automatización proporciona un enfoque de evento modificado que se activa cada vez que el foco cambia a un nuevo control.

Página en MSDN

Muestra:

public void SubscribeToFocusChange() { AutomationFocusChangedEventHandler focusHandler = new AutomationFocusChangedEventHandler(OnFocusChanged); Automation.AddAutomationFocusChangedEventHandler(focusHandler); } private void OnFocusChanged(object src, AutomationFocusChangedEventArgs e) { AutomationElement focusedElement = sender as AutomationElement; //... }

De hecho, esta api utiliza Windows hook detrás de las escenas para hacer eso. Sin embargo, debe usar .Net Framework ...



Si está programando en .net 3.5, el paquete de automatización que menciona olorin es de lejos el más fácil, pero tenga cuidado de usarlo en un programa que tenga una IU, al menos si la interfaz de usuario está hecha en WPF: los enganches de seguimiento de foco confundirse con los eventos en su propia aplicación y bloquear rápidamente la interfaz de usuario. Le envié a MS un informe de error . No he observado el mismo problema usando una interfaz de usuario de Windows Forms tradicional. Por supuesto, podría poner el código de seguimiento en una aplicación de consola separada y usar algún tipo de ipc para transmitir la información que necesita.

La tentadora alternativa de utilizar Interop para acceder al WH_CBT Windows Hook desde C # no funcionará: los únicos ganchos globales que puede obtener desde C # son el mouse y el teclado .