Compartir a través de


Introducción a los enlaces

Un gancho es un mecanismo por el que una aplicación puede interceptar eventos, como mensajes, acciones del ratón y pulsaciones de tecla. Una función que intercepta un tipo determinado de evento se conoce como procedimiento de enlace. Un procedimiento hook puede actuar sobre cada evento que recibe, y luego modificar o descartar el evento.

Algunos usos de ejemplo para los ganchos son los siguientes:

  • Monitorizar mensajes con fines de depuración.
  • Proporcionar compatibilidad con la grabación y reproducción de macros
  • Proporcionar compatibilidad con una tecla de ayuda (F1)
  • Simular la entrada del mouse y el teclado
  • Implementar una aplicación de formación basada en computadora (CBT)

Nota:

Los enlaces tienden a ralentizar el sistema porque aumentan la cantidad de procesamiento que el sistema debe realizar para cada mensaje. Debe instalar un gancho solo cuando sea necesario y quitarlo lo antes posible.

 

En esta sección se describe lo siguiente:

Cadenas de gancho

El sistema admite muchos tipos diferentes de enlaces; cada tipo proporciona acceso a un aspecto diferente de su mecanismo de control de mensajes. Por ejemplo, una aplicación puede usar el hook WH_MOUSE para supervisar el tráfico de mensajes del mouse.

El sistema mantiene una cadena de enlace independiente para cada tipo de gancho. Una cadena de hooks es una lista de punteros a funciones callback especiales, definidas por la aplicación, llamadas procedimientos de hooks. Cuando se produce un mensaje asociado a un tipo determinado de enlace, el sistema pasa el mensaje a cada procedimiento de enlace al que se hace referencia en la cadena de enlace, uno después del otro. La acción que puede realizar un procedimiento de enlace depende del tipo de enlace implicado. Los procedimientos de enlace para algunos tipos de enlaces solo pueden supervisar mensajes; otros pueden modificar los mensajes o detener su progreso a través de la cadena, evitando que lleguen al siguiente procedimiento de enlace o a la ventana de destino.

Procedimientos de hook

Para aprovechar un tipo determinado de enlace, el desarrollador proporciona un procedimiento de enlace y usa la función SetWindowsHookEx para instalarlo en la cadena asociada al enlace. Un procedimiento de enlace debe tener la siguiente sintaxis:

LRESULT CALLBACK HookProc(
  int nCode, 
  WPARAM wParam, 
  LPARAM lParam
)
{
   // process event
   ...

   return CallNextHookEx(NULL, nCode, wParam, lParam);
}

HookProc es un marcador de posición para un nombre definido por la aplicación.

El parámetro nCode es un código de enlace que usa el procedimiento de enlace para determinar la acción que se va a realizar. El valor del código de enlace depende del tipo del enlace; cada tipo tiene su propio conjunto de características de códigos de enlace. Los valores de los parámetros wParam y lParam dependen del código de enlace, pero normalmente contienen información sobre un mensaje enviado o publicado.

La función SetWindowsHookEx siempre instala un procedimiento de enlace al principio de una cadena de enlace. Cuando se produce un evento monitorizado por un tipo determinado de gancho, el sistema llama al procedimiento al inicio de la cadena de ganchos asociada al mismo. Cada procedimiento de enlace de la cadena determina si se debe pasar el evento al procedimiento siguiente. Un procedimiento de enlace pasa un evento al siguiente procedimiento llamando a la función CallNextHookEx .

Tenga en cuenta que los procedimientos de enlace para algunos tipos de enlaces solo pueden supervisar los mensajes. El sistema pasa mensajes a cada procedimiento de gancho, independientemente de si un procedimiento determinado llama CallNextHookEx.

Un hook global supervisa los mensajes de todos los subprocesos del mismo escritorio que el subproceso de llamada. Un hook específico de subproceso supervisa los mensajes solo de un subproceso individual. Se puede llamar a un procedimiento de enlace global en el contexto de cualquier aplicación del mismo escritorio que el subproceso de llamada, por lo que el procedimiento debe estar en un módulo DLL independiente. Un procedimiento de hook específico de subproceso solo se ejecuta en el contexto del subproceso asociado. Si una aplicación instala un procedimiento de enlace para uno de sus propios subprocesos, el procedimiento de enlace puede estar en el mismo módulo que el resto del código de la aplicación o en un archivo DLL. Si la aplicación instala un procedimiento de enlace para un subproceso de una aplicación diferente, el procedimiento debe estar en un archivo DLL. Para obtener información, consulte Dynamic-Link Bibliotecas.

Nota:

Debe utilizar hooks globales solo para propósitos de depuración; de lo contrario, debe evitarlos. Los enlaces globales dañan el rendimiento del sistema y provocan conflictos con otras aplicaciones que implementan el mismo tipo de enlace global.

 

Tipos de enlace

Cada tipo de enlace permite a una aplicación supervisar un aspecto diferente del mecanismo de control de mensajes del sistema. En las secciones siguientes se describen los enlaces disponibles.

WH_CALLWNDPROC y WH_CALLWNDPROCRET

Los ganchos WH_CALLWNDPROC y WH_CALLWNDPROCRET permiten supervisar los mensajes enviados a los procedimientos de ventana. El sistema llama a un procedimiento de enlace de WH_CALLWNDPROC antes de pasar el mensaje al procedimiento de ventana receptora y llama al procedimiento de enlace de WH_CALLWNDPROCRET después de que el procedimiento de ventana haya procesado el mensaje.

El hook WH_CALLWNDPROCRET pasa un puntero a una estructura CWPRETSTRUCT al procedimiento hook. La estructura contiene el valor devuelto del procedimiento de ventana que procesó el mensaje, así como los parámetros de mensaje asociados al mensaje. La subclasificación de la ventana no funciona para los mensajes establecidos entre procesos.

Para más información, vea las funciones de callback CallWndProc y CallWndRetProc.

WH_CBT

El sistema llama a un procedimiento de gancho WH_CBT antes de activar, crear, destruir, minimizar, maximizar, mover o ajustar el tamaño de una ventana; antes de completar un comando del sistema; antes de quitar un evento de ratón o teclado de la cola de mensajes del sistema; antes de establecer el foco de entrada; o antes de sincronizarse con la cola de mensajes del sistema. El valor que devuelve el procedimiento de enlace determina si el sistema permite o impide una de estas operaciones. El gancho WH_CBT está diseñado principalmente para aplicaciones de entrenamiento informático (CBT).

Para obtener más información, consulte la función de devolución de llamada CBTProc.

Para obtener información, consulte WinEvents.

WH_DEBUG

El sistema llama a un procedimiento hook WH_DEBUG antes de llamar a procedimientos hook asociados con cualquier otro hook en el sistema. Puede utilizar este hook para determinar si permite que el sistema llame a procedimientos hook asociados con otros tipos de hooks.

Para más información, consulte la función callback DebugProc.

WH_FOREGROUNDIDLE

El gancho WH_FOREGROUNDIDLE te permite realizar tareas de baja prioridad cuando el subproceso en primer plano está inactivo. El sistema llama a un procedimiento hook WH_FOREGROUNDIDLE cuando el subproceso en primer plano de la aplicación está a punto de quedar inactivo.

Para más información, ver la función de callback ForegroundIdleProc.

WH_GETMESSAGE

El hook WH_GETMESSAGE permite a una aplicación supervisar los mensajes que están a punto de ser devueltos por la función GetMessage o PeekMessage. Puede utilizar el hook WH_GETMESSAGE para monitorizar las entradas de ratón y teclado y otros mensajes enviados a la cola de mensajes.

Para obtener más información, consulte la función callback GetMsgProc.

WH_JOURNALPLAYBACK

Advertencia

Las APIs de Journaling Hooks no están soportadas desde Windows 11 y serán eliminadas en una futura versión. Por este motivo, es muy recomendable llamar a la API SendInput TextInput en su lugar.

El enlace WH_JOURNALPLAYBACK permite a una aplicación insertar mensajes en la cola de mensajes del sistema. Puede usar este enlace para reproducir una serie de eventos de mouse y teclado grabados anteriormente mediante WH_JOURNALRECORD. La entrada normal de ratón y teclado está deshabilitada mientras esté instalado el hook WH_JOURNALPLAYBACK. Un hook WH_JOURNALPLAYBACK es un hook global-no puede ser usado como hook específico de un thread.

El gancho WH_JOURNALPLAYBACK devuelve un valor de tiempo de espera. Este valor indica al sistema cuántos milisegundos esperar antes de procesar el mensaje actual desde el enlace de reproducción. Esto permite al hook controlar el tiempo de los eventos que reproduce.

Para obtener más información, consulte la función de llamada de retorno JournalPlaybackProc.

WH_JOURNALRECORD

Advertencia

Las APIs de Journaling Hooks no están soportadas desde Windows 11 y serán eliminadas en una futura versión. Por este motivo, es muy recomendable llamar a la API SendInput TextInput en su lugar.

El enlace WH_JOURNALRECORD permite supervisar y registrar eventos de entrada. Normalmente, se usa este enlace para grabar una secuencia de eventos de mouse y teclado para reproducirlos más adelante mediante WH_JOURNALPLAYBACK. El WH_JOURNALRECORD enlace es un enlace global; no se puede usar como un enlace específico del subproceso.

Para obtener más información, consulte la función de devolución de llamada JournalRecordProc.

WH_KEYBOARD_LL

El hook WH_KEYBOARD_LL permite supervisar los eventos de entrada de teclado que están a punto de publicarse en una cola de entrada de subprocesos.

Para obtener más información, consulte la función de devolución de llamada LowLevelKeyboardProc.

WH_KEYBOARD

El enlace WH_KEYBOARD permite a una aplicación supervisar el tráfico de mensajes de WM_KEYDOWN y WM_KEYUP, mensajes que están a punto de ser devueltos por la función GetMessage o PeekMessage. Puede utilizar el hook WH_KEYBOARD para supervisar la entrada de teclado publicada en una cola de mensajes.

Para más información, ver la función de callback KeyboardProc.

WH_MOUSE_LL

El hook WH_MOUSE_LL permite monitorizar eventos de entrada de ratón a punto de ser publicados en una cola de entrada de hilo.

Para más información, ver la función de callback LowLevelMouseProc.

WH_MOUSE

El enlace de WH_MOUSE le permite supervisar los mensajes del mouse a punto de ser devueltos por la función GetMessage o PeekMessage . Puede utilizar el hook WH_MOUSE para supervisar la entrada del ratón publicada en una cola de mensajes.

Para más información, vea la función de callback MouseProc.

WH_MSGFILTER y WH_SYSMSGFILTER

Los enlaces WH_MSGFILTER y WH_SYSMSGFILTER permiten supervisar los mensajes a punto de ser procesados por un menú, una barra de desplazamiento, un cuadro de diálogo o un cuadro de diálogo, y para detectar cuándo una ventana diferente está a punto de activarse como resultado de que el usuario presione la combinación de teclas ALT+TAB o ALT+ESC. El gancho WH_MSGFILTER solo puede supervisar los mensajes pasados a un menú, una barra de desplazamiento, un cuadro de mensaje o un cuadro de diálogo creados por la aplicación que instaló el procedimiento de gancho. El enlace WH_SYSMSGFILTER supervisa estos mensajes para todas las aplicaciones.

Los enlaces WH_MSGFILTER y WH_SYSMSGFILTER permiten realizar el filtrado de mensajes durante bucles modales equivalentes al filtrado realizado en el bucle de mensajes principal. Por ejemplo, una aplicación suele examinar un nuevo mensaje en el bucle principal entre el momento en que recupera el mensaje de la cola y la hora en que envía el mensaje, realizando un procesamiento especial según corresponda. Sin embargo, durante un bucle modal, el sistema recupera y envía mensajes sin permitir que una aplicación filtre los mensajes en su bucle de mensajes principal. Si una aplicación instala un procedimiento de enganche WH_MSGFILTER o WH_SYSMSGFILTER, el sistema llama al procedimiento durante el bucle modal.

Una aplicación puede llamar directamente al hook WH_MSGFILTER llamando a la función CallMsgFilter. Con esta función, la aplicación puede usar el mismo código para filtrar los mensajes durante los bucles modales que usa en el bucle de mensajes principal. Para hacerlo, encapsula las operaciones de filtrado en un procedimiento de gancho WH_MSGFILTER y llama a CallMsgFilter entre las invocaciones a las funciones GetMessage y DispatchMessage.

while (GetMessage(&msg, (HWND) NULL, 0, 0)) 
{ 
    if (!CallMsgFilter(&qmsg, 0)) 
        DispatchMessage(&qmsg); 
} 

El último argumento de CallMsgFilter se pasa simplemente al procedimiento de enlace; se puede escribir cualquier valor. El procedimiento de enlace, definiendo una constante como MSGF_MAINLOOP, puede usar este valor para determinar desde dónde se llamó al procedimiento.

Para más información, consulte las funciones de devolución de llamada MessageProc y SysMsgProc.

WH_SHELL

Una aplicación de shell puede usar el enlace de WH_SHELL para recibir notificaciones importantes. El sistema llama a un procedimiento de gancho WH_SHELL cuando la aplicación shell está a punto de activarse y cuando se crea o destruye una ventana de nivel superior.

Tenga en cuenta que las aplicaciones de shell personalizadas no reciben mensajes WH_SHELL . Por lo tanto, cualquier aplicación que se registre como shell predeterminado debe llamar a la función SystemParametersInfo antes de que ella (o cualquier otra aplicación) pueda recibir mensajes WH_SHELL. Se debe llamar a esta función con SPI_SETMINIMIZEDMETRICS y una estructura MINIMIZEDMETRICS . Establezca el miembro iArrange de esta estructura en ARW_HIDE.

Para obtener más información, consulte la función callback ShellProc.