El Administrador de mensajes de Windows ofrece a las aplicaciones la posibilidad de acceder a flujos de mensajes controlados.
El llamado mecanismo de gancho (GANCHO) de 'c4. Hay muchos tipos de ganchos, cada uno de los cuales se utiliza para capturar un tipo o rango específico de mensajes. Tales como: mensajes de teclado, mensajes de mouse, etc. Aquí solo tomamos el uso de enlaces de teclado como ejemplo para discutir cómo escribir programas DLL en DELPHI y cómo instalar y usar funciones de enlaces de teclado en sus propios programas. También analizamos cómo compartir datos cuando diferentes programas usan el mismo archivo DLL. .
1. Instrucciones para escribir funciones de filtro de gancho
Dado que la función de filtro de enlace debe estar en un módulo independiente, eso significa que primero debemos generar un marco DLL y luego agregarle el código de función de enlace y otros códigos de función relacionados. Aquí tomamos la escritura de la función de filtro de enlace del teclado como ejemplo para ilustrar. Los pasos específicos son los siguientes:
1. Primero genere una canasta de DLL 2
2. Escriba su propia función de filtro de enlace de teclado
La función de filtro de enlace debe ser una función de devolución de llamada y su función tiene la siguiente forma:
funciónKeyHookPRoc(
iCode:Entero;
wParam:WPARAM;
lParam:LPARAM): LRESULT; llamada estándar; exportar;
Agregue su propia función de procesamiento de enlace de teclado al marco DLL generado para manejar mensajes de teclado.
El código es el siguiente:…
si (iCode> = 0) entonces comienza
Resultado:=0; //Valor de retorno de inicialización
//Añade tu propio código aquí
fin de otra manera
comenzar
Resultado:=CallNextHook(hOldKeyHook,iCode,wParam,lParam);
// ¿hOldKeyHook es la función de filtro de teclado original guardada?
fin;
3. Instale la función de filtro de gancho del teclado
Para instalar un enlace, la función de filtro _fd debe llamar a la función SetWindowsHookEx (la función de instalación del enlace SetWindowsHook para Windows 3.0 ahora está obsoleta). El prototipo de esta función es el siguiente:
HHOOK EstablecerWindowsHookEx(
int idHook, // ¿Instalado?_b3 subtipo
HOOKPROC lpfn, //¿Filtro de gancho??f número dirección
HINSTANCE hMod, //identificador de tarea
DWord dwThreadId // El propósito del gancho
);
Cabe señalar que: ?_a8 a menudo debe llamar a la función MakeProcInstance para obtener la dirección de entrada del preámbulo de una función de salida y luego usar esta dirección como el segundo parámetro lpfn de SetWindowsHookEx. Sin embargo, dado que Delphi proporciona una "devolución de llamada inteligente", se puede omitir MakeProcInstance y el nombre de la función del filtro de enlace se puede usar directamente como dirección de entrada.
De esta manera, cuando la función _c3GetMessage o PeekMessage de la aplicación lee mensajes de la cola de mensajes o tiene mensajes clave (WM_KEYDOWN o WM_KEYUP) para procesar, el sistema llamará a la función de filtro de enlace KeyHookProc para procesar los mensajes del teclado.
4. Desinstale la función de filtro de gancho.
Cuando la función de enlace ya no sea necesaria, se debe llamar a UnHookWindowsHookProc para desinstalar el enlace instalado y liberar recursos del sistema.
¿La lista completa de programas es la siguiente?_ba
Biblioteca LLAVERO;
utiliza Windows;
constante BUFFER_SIZE=16*1024;
const HOOK_MEM_FILENAME='MUESTRA KEY_HOOK_MEM_FILE';
const HOOK_MUTEX_NAME ='MUESTRA KEY_HOOK_MUTEX_NAME';
tipo
TCompartido=registro
Claves: matriz[0..BUFFER_SIZE] de Char;
KeyCount: Entero;
fin;
PScompartido=^TScompartido;
var
MemFile,HookMutex: THandle;
hOldKeyHook: HHook;
ProcSaveExit: Puntero;
Compartido: PCompartido;
//Función de filtro de gancho de teclado
función KeyHookProc(iCode: Integer; wParam: WPARAM; lParam: LPARAM):LRESULT
; llamada estándar; exportar;
const KeyPressMask = $80000000;
comenzar
si iCode < 0 entonces
Resultado: = CallNextHookEx(hOldKeyHook, iCode, wParam, lParam)
si no, empezar
si ((lParam y KeyPressMask)= 0) entonces // tecla presionada
comenzar
Compartido^.Keys[Shared^.KeyCount]:=Char(wParam y $00ff);
Inc(Compartido^.KeyCount);
si Compartido^.KeyCount>=BUFFER_SIZE-1 entonces Compartido^.KeyCount:=0;
fin;
Código i:=-1;
Resultado := CallNextHookEx(hOldKeyHook, iCode, wParam, lParam);
fin;
fin;
//Establece la función de filtro de gancho
función EnableKeyHook: BOOL;
comenzar
Shared^.KeyCount:=0; //Inicializa el puntero del teclado
si hOldKeyHook=0 entonces comienza
hOldKeyHook := SetWindowsHookEx(WH_KEYBOARD,
proceso de gancho de clave,
H Instancia,
0);
fin;
Resultado := (hOldKeyHook <> 0);
fin;
//Deshacer la función de filtro de gancho
función DisableKeyHook: BOOL;
comenzar
si hOldKeyHook<> 0 entonces
comenzar
UnHookWindowsHookEx(hOldKeyHook); // Desenganchar el gancho del teclado;
hOldKeyHook:= 0;
Compartido^.KeyCount:=0;
fin;
Resultado := (hOldKeyHook = 0);
fin;
//Obtiene el número de pulsaciones de teclas en el búfer del teclado
función GetKeyCount :Entero exportar;
comenzar
Resultado:=Compartido^.KeyCount;
fin;
//Obtener las teclas del buffer del teclado
función GetKey(índice:Entero): Char exportar;
comenzar
Resultado:=Compartido^.Claves[índice];
fin;
//Borrar el buffer del teclado
procedimiento ClearKeyString exportación;
comenzar
Compartido^.KeyCount:=0;
fin;
//Proceso de procesamiento de salida de DLL
procedimiento KeyHookExit lejos;
comenzar
si hOldKeyHook <> 0 entonces DisableKeyHook;
UnMapViewOfFile(Shared); // Libera el archivo de imagen de la memoria
CloseHandle(MemFile); // Cerrar el archivo de imagen
SalirProc := ProcSaveSalir;
fin;
exportaciones // define la función de salida
habilitar KeyHook,
Desactivar KeyHook,
obtener recuento de claves,
borrar cadena de claves,
Obtener clave;
comenzar
//parte de inicialización de DLL
HookMutex:=CreateMutex(nil,True,HOOK_MUTEX_NAME);
// Comparte memoria creando un archivo de imagen de memoria
MemFile:=OpenFileMapping(FILE_MAP_WRITE,Falso,
HOOK_MEM_FILENAME);
si MemFile=0 entonces
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
TamañoDe(TShared),HOOK_MEM_FILENAME);
Compartido:=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);
LiberarMutex(HookMutex);
CerrarMango(HookMutex);
ProcSaveExit := ExitProc; // Guarda el ExitProc de la DLL
ExitProc := @KeyHookExit; // Establece el nuevo ExitProc de la DLL
fin.
//Fin del código fuente
2. Utilice la función de filtro de enlace de teclado preparada en su propio programa.
Una vez compilada la función de enlace, en realidad es muy simple de usar: primero llame a SetWindowsHookEx para instalar su propia función de filtro de enlace y, al mismo tiempo, guarde la dirección de la función de filtro de enlace original. En este momento, entra en juego la función de enlace, que manejará los mensajes del teclado de acuerdo con sus requisitos. Cuando el programa termine de ejecutarse o ya no sea necesario monitorear los mensajes del teclado, llame a la función UnHookWindowsHookProc para desinstalar la función de enlace instalada y restaurar la dirección de la función de filtro de enlace original.
El siguiente es un ejemplo del uso de la función de enlace compilada anteriormente:
unidad Unidad1;
interfaz
usos
Windows, Mensajes, SysUtils, Clases, Gráficos, Controles, Formularios, Cuadros de diálogo,
CtrlStd, CtrlExt;
tipo
TForm1 = clase(TForm)
Memo1: TMemo;
Panel1: Panel T;
bSetHook: TBotón;
bCancelarHook: TButton;
bReadKeys: TButton;
bClearKeys: TButton;
Panel2: Panel T;
procedimiento bSetHookClick(Remitente: TObject);
procedimiento bCancelHookClick(Remitente: TObject);
procedimiento bReadKeysClick (Remitente: TObject);
procedimiento bClearKeysClick (Remitente: TObject);
fin;
var Formulario1: TForm1;
implementación
{$R *.DFM}
función EnableKeyHook: BOOL externo 'KEYHOOK.DLL';
función DisableKeyHook: BOOL externo 'KEYHOOK.DLL';
función GetKeyCount: Entero 'KEYHOOK.DLL' externo;
función GetKey(idx:Integer): Char externo 'KEYHOOK.DLL';
procedimiento ClearKeyString; externo 'KEYHOOK.DLL';
procedimiento TForm1.bSetHookClick(Sender: TObject // Establecer gancho de teclado 7ó);
comenzar
Habilitar KeyHook;
bSetHook.Enabled:=Falso;
bCancelHook.Enabled:=Verdadero;
bReadKeys.Enabled :=Verdadero;
bClearKeys.Enabled:=Verdadero;
Panel2.Caption:='Se ha configurado el gancho del teclado';
fin;
procedimiento TForm1.bCancelHookClick(Sender: TObject // Desinstalar el gancho del teclado);
comenzar
Desactivar KeyHook;
bSetHook.Enabled:=Verdadero;
bCancelHook.Enabled:=Falso;
bReadKeys.Enabled:=Falso;
bClearKeys.Enabled:=Falso;
Panel2.Caption:='El gancho del teclado no está configurado';
fin;
procedimiento TForm1.bReadKeysClick(Sender: TObject // Obtener historial de pulsaciones de teclas);
var i:Entero;
comenzar
Memo1.Lines.Clear // Muestra el historial de pulsaciones de teclas en Memo1;
para i:=0 a GetKeyCount-1 hacer
Memo1.Texto:=Memo1.Texto+GetKey(i);
fin;
procedimiento TForm1.bClearKeysClick(Sender: TObject // Borrar historial de pulsaciones de teclas);
comenzar
Memo1.Borrar;
Borrar cadena de claves;
fin;
fin.
//Fin del código fuente
3. Implementación de memoria compartida en DLL en Windows95
En el archivo DLL donde se encuentra la función de enlace anterior, se debe usar memoria compartida, es decir, todos los registros de pulsaciones de teclas se almacenan en el mismo segmento de datos. ¿Por qué hacemos esto? Esto se debe a que el método de llamada de DLL de Windows95 es diferente al de Windows3.X. Cuando cada hilo inicia sesión en una biblioteca de vínculos dinámicos, pasará un nuevo identificador de instancia (es decir, el identificador del segmento de datos DLL) a la biblioteca de vínculos dinámicos. Esto permite que las distintas instancias de la DLL no interfieran entre sí, pero genera algunas dificultades cuando todas las instancias de la DLL comparten un conjunto de variables. Para resolver este problema, lo solucionamos aquí creando un archivo mapeado en memoria. Es decir, utilizando OpenFileMapping, CreateFileMapping y CreateFileMapping de Windows.
MapViewOfFile tres funciones para lograr. Cómo usarlo:
…
MemFile es un tipo THandle, Shared es un tipo de puntero y HOOK_MEM_FILENAME es una cadena constante.
…
MemFile:=OpenFileMapping(FILE_MAP_WRITE,Falso,
HOOK_MEM_FILENAME); //Abrir archivo mapeado en memoria
si MemFile=0 entonces //Si la apertura falla?_c2 Crear un archivo mapeado en memoria
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
TamañoDe(TShared),HOOK_MEM_FILENAME);
//Asignar archivos a variables
Compartido:=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);
Hasta ahora, ya sabes lo fácil que es compilar funciones de enlace en Delphi. Finalmente, tengo que recordarles a todos: aunque la función de enlace es relativamente poderosa, si se usa incorrectamente, afectará seriamente la eficiencia del sistema, así que trate de evitar el uso de enlaces del sistema. Se debe tener especial cuidado cuando se debe utilizar, para que afecte lo menos posible al funcionamiento del sistema.
[Fin del texto completo]