Red de conocimiento informático - Consumibles informáticos - Cómo utilizar el gancho del teclado

Cómo utilizar el gancho del teclado

I: Establecer gancho

Establecer gancho a través de la función API de SetWindowsHookEx ().

Prototipo: HHOOK SetWindowsHookEx(int ​​​​idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId)

idhook: el tipo de gancho cargado.

lpfn: la dirección de entrada del proceso de enlace

hMod: el controlador de eventos del application

dwThreadId: Identificador del hilo para cargar el gancho

Parámetros:

idHook:

Este parámetro puede tener los siguientes valores:

WH_CALLWNDPROC, WH_CALLWNDPROCRET, WH_CBT, WH_DEBUG, WH_FOREGROUNDIDLE, WH_GETMESSAGE, WH_JOURNALRECORD, WH_KEYBOARD, WH_KEYBOARD_LL, WH_MOUSE, WH_MOUSE_LL, WH_MSGFILTER, WH_SHELL, WH_SYSMSGFILTER.

No quiero explicar estos parámetros uno por uno, porque hay anotaciones detalladas sobre ellos en MSDN. Sólo seleccioné algunos de ellos y los expliqué en chino.

WH_KEYBOARD: una vez que hay un mensaje de pulsación de teclado (teclado presionado, teclado emergente), WINDOWS llamará a su función de enlace antes de que el mensaje se coloque en la cola de mensajes de la aplicación. Las funciones de enlace pueden alterar y descartar mensajes de pulsación de teclas.

WH_MOUSE: WINDOWS llamará a su función de enlace antes de que cada mensaje del mouse se coloque en la cola de mensajes de la aplicación. Las funciones de enlace pueden alterar y descartar mensajes del mouse.

WH_GETMESSAGE: WINDOWS llamará a su función de enlace cada vez que su aplicación llame a GetMessage() o PeekMessage() para solicitar un mensaje de la cola de mensajes de la aplicación. La función de enlace puede cambiar y descartar este mensaje.

II: Liberar el gancho

El gancho se libera usando la función UnhookWindowsHookEx()

Prototipo: BOOL UnhookWindowsHookEx(HHOOK hhk)

La función UnhookWindowsHookEx() liberará el proceso de enlace cargado por la función SetWindowsHookEx en la cadena de enlace.

hhk: el identificador del proceso de enlace que se liberará.

III: Proceso de enlace

El proceso de enlace utiliza la función HookProc; de hecho, HookProc es solo un símbolo definido por la aplicación. Por ejemplo, puedes escribirlo como KeyBoardHook pero los parámetros permanecen sin cambios. La API de Win32 proporciona funciones como: CallWndProc, GetMsgProc, DebugProc, CBTProc, MouseProc, KeyboardProc, MessageProc, etc. Para su explicación detallada, puede consultar MSDN. Aquí solo explicaré el significado de KeyBoardHook.

Prototipo: LRESULT CALLBACK KeyBoardHook (int nCode, WPARAM wParam, LPARAM lParam)

Explicación: El proceso de enlace son algunas funciones adjuntas a un enlace, por lo que el proceso de enlace solo lo utilizan WINDOWS Llamados sin ser llamados por la aplicación, a veces son necesarios como función de devolución de llamada (CALLBACK).

Descripción del parámetro:

nCode: código de enlace El proceso de enlace utiliza el código de enlace para decidir si se ejecuta. El valor del código de enlace depende del tipo de enlace. Cada tipo de gancho tiene su propio conjunto de códigos para las propiedades. Por ejemplo, para WH_KEYBOARD, los parámetros del código de enlace son: HC_ACTION, HC_NOREMOVE. El significado de HC_ACTION: los parámetros wParam y lParam contienen la información del mensaje de golpe del teclado. El significado de HC_NOREMOVE: los parámetros wParam y lParam contienen la información del mensaje de golpe del teclado, y el mensaje de golpe del teclado no se ha eliminado del mensaje. cola. (La aplicación llama a la función PeekMessage y establece el indicador PM_NOREMOVE). Es decir, cuando nCode es igual a HC_ACTION, el proceso de enlace debe procesar el mensaje. Cuando es HC_NOREMOVE, el proceso de enlace debe pasar el mensaje a la función CallNextHookEx sin procesamiento adicional y debe haber un valor de retorno de la función CallNextHookEx.

wParam: Mensaje de teclado generado al tocar el teclado, código virtual de la tecla del teclado.

lParam: contiene detalles del mensaje.

Nota: Si nCode en el proceso de enlace es menor que cero, el proceso de enlace debe devolver (return) CallNextHookEx(nCode, wParam, lParam); mientras que nCode en el proceso de enlace es mayor que cero, pero el El proceso de enlace no procesa el mensaje. El autor recomienda llamar a CallNextHookEx y devolver el valor de retorno de esta función. De lo contrario, si otra aplicación también carga el enlace WH_KEYBOARD, ese enlace no aceptará notificaciones de enlace y devolverá un valor incorrecto. Si el proceso de enlace maneja el mensaje, puede devolver un valor distinto de cero para evitar que el sistema pase el mensaje a otros procesos de enlace o de Windows restantes. Por lo tanto, es mejor devolver el valor de retorno de CallNextHookEx al final del proceso de enlace.

IV: Llamar a la siguiente función de enlace

Utilice la función CallNexHookEx al llamar a la siguiente función de enlace.

Prototipo: LRESULT CallNextHookEx(HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam)

La función CallNexHookEx() se utiliza para transferir información de enlace al siguiente proceso de enlace en el proceso de enlace actual. cadena de gancho, un proceso de gancho puede llamar a esta función antes o después del procesamiento de la información del gancho. El motivo por el que se utiliza esta función se explica en detalle en la "Nota" del proceso de enlace iii.

hhk: el identificador del enlace actual.

nCode: el código del enlace pasado al proceso del enlace.

wParam: El valor pasado al proceso de enlace.

lParam: el valor pasado al proceso de enlace.

Parámetros:

hhk: El identificador del gancho actual. La aplicación acepta este identificador como resultado de una llamada previa a la función SetWindowsHookE

nCode: pasado al proceso de enlace Código de enlace, el siguiente proceso de enlace usa este código para decidir cómo procesar la información del enlace

wParam: valor del parámetro wParam enviado al proceso de enlace, el significado específico del valor del parámetro está relacionado al tipo de gancho de la cadena de gancho actual. Relacionado

lParam: el valor del parámetro wParam enviado al proceso de gancho. El significado específico del valor del parámetro está relacionado con el tipo de gancho de la cadena de gancho actual. /p>

Valor de retorno: el valor de retorno es el valor en la cadena. El valor devuelto por el siguiente proceso de enlace. El proceso de enlace actual debe devolver este valor. El significado específico del valor de retorno está relacionado con el tipo de enlace. Para obtener más información, consulte la descripción del proceso de enlace específico.

V Crear una biblioteca de enlaces dinámicos (DLL)

Después de familiarizarnos con las funciones anteriores, ahora comenzamos a escribir una biblioteca de enlaces dinámicos (DLL). Aquí uso WIN32 DLL en lugar de MFC DLL. Y todos los programas siguientes también están escritos en lenguaje C. Esto se debe principalmente a que el uso de la API WIN32 puede controlar cómo se ejecuta el programa de manera más detallada y completa, mientras que al usar MFC, algunos controles de bajo nivel son imposibles de lograr (por supuesto, MFC también se puede usar solo para este programa).

1: Cree un archivo .cpp de una biblioteca de enlaces dinámicos. Por ejemplo, ahora creamos un archivo llamado hookdll.cpp.

Agregue el siguiente contenido al archivo hookdll.cpp:

#include lt; windows.hgt

#include "string.h"

#include " stdio.h"

HINSTANCE hInst;

#pragma data_seg("hookdata")

HHOOK oldkeyhook=0;

# pragma data_seg()

#pragma comment(linker, "/SECTION: hookdata, RWS")

#define DllExport extern "C"__declspec(dllexport)

DllExport LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam);

DllExport void InstallHook(int nCode);

DllExport void EndHook(void);

BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG What, LPVOID NotUsed)

{

cambiar(What)

{

case DLL_PROCESS_ATTACH :

hInst = hInstance

romper;

caso DLL_PROCESS_DETACH:

romper

caso DLL_THREAD_ATTACH :

romper;

caso DLL_THREAD_DETACH:

romper;

}

devolver 1;

}

void InstallHook(int nCode)

{

oldkeyhook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyBoardProc, hInst, 0);< / p>

}

DllExport LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam)

{

WPARAM j;

ARCHIVO *fp;

if(lParamamp;0x80000000)

{

j = wParam;

fp=fopen( " c:\hook\key.txt", "a");

fprintf(fp, "4d", j);

fclose(fp);

}

return CallNextHookEx(oldkeyhook, nCode, wParam, lParam

}

void EndHook(void)

{

DesengancharWindowsHookEx(oldkeyhook);

}

Esta acción

El código fuente hookdll.cpp de la biblioteca de conexión dinámica incluye funciones de procesamiento de teclado, configuración de enlace y funciones de enlace de salida. Y guarde las teclas presionadas por el teclado en el archivo c:hookkey.txt en formato de valor. A continuación se muestra una explicación detallada de este archivo.

Para utilizar funciones contenidas en una DLL, es necesario importarlas. La operación de importación se completa a través de dllimport. dllexport y dllimport son palabras clave extendidas compatibles con vc (visual C) y bc (Borland C). Sin embargo, las palabras clave dllexport y dllimport no se pueden utilizar por sí solas, por lo que deben ir precedidas de otra palabra clave de extensión __declspec. El formato general es el siguiente: __declspec(especificador) donde especificador es el identificador de clase de almacenamiento. Para las DLL, los especificadores serán dllexport y dllimport. Y para simplificar la declaración de funciones de importación y exportación, se usa un nombre de macro en lugar de __declspec. En este programa, se usa DllExport. Si la DLL del usuario está compilada en un programa C y desea que el programa C pueda usarla, debe agregar una descripción de conexión "C". #define DllExport extern "C"__declspec(dllexport), evitando así la corrupción de nombres estándar de C. (Por supuesto, si el lector está compilando un programa en C, no agregue "C" externo, porque no es necesario y el compilador no lo acepta). Con la definición de macro, ahora puede exportar la función con una declaración simple, como:

DllExport LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam); DllExport void InstallHook(int nCode);DllExport); void EndHook(void);

La primera declaración #pragma crea un segmento de datos, aquí denominado hookdata. De hecho, también puedes ponerle el nombre que quieras. Todas las variables inicializadas después de la declaración #pragma ingresan a la sección hookdata. La segunda declaración #pragma marca el final del segmento de datos. Es importante inicializar las variables específicamente; de ​​lo contrario, el compilador las colocará en una sección normal no inicializada en lugar de en hookdata.

Pero el vinculador debe esperar hasta que haya una sección de datos de enlace. Podemos seleccionar la opción Enlace en el cuadro de diálogo Configuración del proyecto (vc6.0). Cuando se selecciona HOOKDLL, en el campo Opciones del proyecto (disponible en configuraciones de lanzamiento y depuración), incluya la siguiente declaración de conexión: /SECCIÓN: hookdata, RWS. Las letras RWS son Indica que el segmento tiene atributos de lectura, escritura y *compartir. Por supuesto, también puede especificar el vinculador directamente con el código fuente de la DLL como HOOKDLL.c: #pragma comment(linker, "/SECTION: hookdata, RWS").

Porque algunas DLL requieren un código especial de inicio y terminación. Para este propósito, todas las DLL tienen una función llamada DllMain(), que se llama cuando la DLL se inicializa o finaliza. Esta función generalmente se define en el archivo de recursos de la biblioteca de enlaces dinámicos. Sin embargo, si no está definido, el compilador proporcionará automáticamente un formulario predeterminado.

El prototipo es: BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG What, LPVOID NotUsed)

Parámetros:

hInstance: identificador de instancia DLL

Qué: Especifica la operación que ocurrió

NotUsed: Parámetros reservados

El valor de Cuáles pueden ser los siguientes valores:

DLL_PROCESS_ATTACH: El proceso comienza a usar la DLL

p>

DLL_PROCESS_DETACH: El proceso está liberando la DLL

DLL_THREAD_ATTACH: El proceso ha creado un nuevo hilo

DLL_THREAD_DETACH: El proceso ha abandonado un hilo

Total En otras palabras, cada vez que se llama a la función DllMain(), se deben tomar las acciones apropiadas en función del contenido de What. Esta acción apropiada no puede hacer más que devolver un valor distinto de cero.

DllMain()El siguiente paso es configurar el enlace, procesar el teclado y soltar el enlace.

2: Crea un archivo de encabezado

Al igual que cualquier otra función de biblioteca utilizada por la aplicación, el programa también debe contener el prototipo de la función en la dll. Todos los programas de Windows deben incluir windows.h. Así que ahora creamos un archivo de encabezado hookdll.h de la siguiente manera:

#define DllImport extern "C"__declspec(dllimport)

DllImport void InstallHook(int nCode);

DllImport LRESULT CALLBACK KeyBoardProc (int nCode, WPARAM wParam, LPARAM lParam);

DllImport void EndHook(void);

El uso de dllimport es principalmente para hacer que el código sea más eficiente. por lo que se recomienda usarlo. Pero se requiere dllimport al importar datos. Después de completar el procedimiento anterior, cree un proyecto de proyecto, también puede usar hookdll y luego insertar hookdll.c en el proyecto de proyecto importado, compilar y se pueden generar hookdll.dll y hookdll.lib.

3: Cree el archivo del programa principal

Todo el trabajo que hicimos anteriormente es sentar las bases para el programa principal actual. De hecho, cuando completamos el archivo DLL, todo lo que queda es llamar a la función de enlace de instalación: InstallHook. Si está muy familiarizado con la programación de Windows, puede llamar a InstallHook cuando lo necesite. Pero debes recordar que cuando sales del programa necesitas llamar a EndHook para liberar la función de enlace que instalaste. Ahora creé un hookspy.cpp, copié el hookdll.dll y el hookdll.lib generados en un directorio y creé un proyecto de hookspy. Inserte hookspy.cpp, hookdll.dll, hookdll.lib y hookdll.h en el proyecto. Luego configure el enlace al crear la ventana de Windows y salga de la función de enlace al salir del programa.

Por ejemplo:

case WM_CREATE:

InstallHook(TRUE);

break;

case WM_DESTROY: //terminar el programa< / p>

EndHook();

PostQuitMessage(0);

romper;