O Gerenciador de Mensagens do Windows fornece aos aplicativos a capacidade de acessar fluxos de mensagens controlados.
O chamado mecanismo de gancho (HOOK) de 'c4. Existem muitos tipos de ganchos, cada um usado para capturar um tipo ou intervalo específico de mensagens. Tais como: mensagens de teclado, mensagens de mouse, etc. Tomamos aqui apenas o uso de ganchos de teclado como exemplo para discutir como escrever programas DLL em DELPHI e como instalar e usar funções de gancho de teclado em seus próprios programas. Também discutimos como compartilhar dados quando programas diferentes usam o mesmo arquivo DLL. .
1. Instruções para escrever funções de filtro de gancho
Como a função de filtro de gancho deve estar em um módulo independente, isso significa que devemos primeiro gerar uma estrutura DLL e, em seguida, adicionar o código de função de gancho e outros códigos de função relacionados a ela. Aqui tomamos a escrita da função de filtro de gancho do teclado como exemplo para ilustrar. As etapas específicas são as seguintes:
1. Primeiro gere uma cesta de DLL 2
2. Escreva sua própria função de filtro de gancho de teclado
A função de filtro de gancho deve ser uma função de retorno de chamada e sua função tem o seguinte formato:
funçãoKeyHookPRoc(
iCode:Inteiro;
wParam:WPARAM;
lParam: LPARAM ): LRESULT; stdcall ;exportar;
Adicione sua própria função de processamento de gancho de teclado à estrutura DLL gerada para lidar com mensagens de teclado.
O código é o seguinte:…
if(iCode>=0) então comece
Resultado:=0; //Valor de retorno de inicialização
//Adicione seu próprio código aqui
fim mais
começar
Resultado:=CallNextHook(hOldKeyHook,iCode,wParam,lParam);
//hOldKeyHook é a função de filtro do teclado original salva?
fim;
3. Instale a função de filtro de gancho do teclado
Para instalar um gancho, a função de filtro _fd deve chamar a função SetWindowsHookEx (a função de instalação do gancho SetWindowsHook para Windows 3.0 agora está obsoleta). O protótipo desta função é o seguinte:
HHOOK SetWindowsHookEx(
int idHook, // Instalado?_b3 subtipo
HOOKPROC lpfn, //Filtro de gancho??f endereço numérico
HINSTANCE hMod, //Identificador de tarefa
DWord dwThreadId // O propósito do gancho
);
Deve-se observar que: ?_a8 geralmente deve chamar a função MakeProcInstance para obter o endereço de entrada do preâmbulo de uma função de saída e, em seguida, usar esse endereço como o segundo parâmetro lpfn de SetWindowsHookEx. No entanto, como o Delphi fornece "retorno de chamada inteligente", MakeProcInstance pode ser omitido e o nome da função do filtro de gancho pode ser usado diretamente como endereço de entrada.
Desta forma, quando a função _c3GetMessage ou PeekMessage da aplicação lê mensagens da fila de mensagens ou possui mensagens-chave (WM_KEYDOWN ou WM_KEYUP) para serem processadas, o sistema chamará a função de filtro de gancho KeyHookProc para processar as mensagens do teclado.
4. Desinstale a função de filtro de gancho.
Quando a função de gancho não for mais necessária, UnHookWindowsHookProc deverá ser chamado para desinstalar o gancho instalado para liberar recursos do sistema.
A lista completa do programa é a seguinte?_ba
Biblioteca CHAVE;
usa Windows;
const BUFFER_SIZE=16*1024;
const HOOK_MEM_FILENAME='AMOSTRA KEY_HOOK_MEM_FILE';
const HOOK_MUTEX_NAME ='AMOSTRA KEY_HOOK_MUTEX_NAME';
tipo
TShared=registro
Chaves: array[0..BUFFER_SIZE] de Char;
KeyCount: Inteiro;
fim;
PShared=^TShared;
var
MemFile,HookMutex: THandle;
hOldKeyHook: HHook;
ProcSaveExit: Ponteiro;
Compartilhado: PShared;
//Função de filtro de gancho do teclado
função KeyHookProc(iCode: Integer; wParam: WPARAM ; lParam: LPARAM):LRESULT
;chamada padrão;
const KeyPressMask = $ 80000000;
começar
se iCode < 0 então
Resultado: = CallNextHookEx (hOldKeyHook, iCode, wParam, lParam)
senão começar
if ((lParam e KeyPressMask)= 0) então // tecla pressionada
começar
Shared^.Keys[Shared^.KeyCount]:=Char(wParam e $00ff);
Inc(Compartilhado^.KeyCount);
se compartilhado^.KeyCount>=BUFFER_SIZE-1 então compartilhado^.KeyCount:=0;
fim;
iCódigo:=-1;
Resultado:= CallNextHookEx(hOldKeyHook, iCode, wParam, lParam);
fim;
fim;
//Definir a função de filtro de gancho
função EnableKeyHook: exportação BOOL;
começar
Shared^.KeyCount:=0; //Inicializa o ponteiro do teclado
se hOldKeyHook=0 então comece
hOldKeyHook := SetWindowsHookEx(WH_KEYBOARD,
KeyHookProc,
HInstância,
0);
fim;
Resultado:= (hOldKeyHook <> 0);
fim;
//Desfaz a função de filtro de gancho
função DisableKeyHook: exportação BOOL;
começar
se hOldKeyHook<> 0 então
começar
UnHookWindowsHookEx(hOldKeyHook); // Solta o Gancho do Teclado
hOldKeyHook:= 0;
Compartilhado^.KeyCount:=0;
fim;
Resultado:= (hOldKeyHook = 0);
fim;
//Obtém o número de teclas digitadas no buffer do teclado
função GetKeyCount: exportação inteira;
começar
Resultado:=Compartilhado^.KeyCount;
fim;
//Obtém as teclas do buffer do teclado
função GetKey (índice: Inteiro): Char exportação;
começar
Resultado:=Compartilhado^.Chaves[índice];
fim;
//Limpa o buffer do teclado
procedimento ClearKeyString exportação;
começar
Compartilhado^.KeyCount:=0;
fim;
//processo de processamento de saída da DLL
procedimento KeyHookExit até agora;
começar
se hOldKeyHook <> 0 então DisableKeyHook;
UnMapViewOfFile(Shared); // Libera o arquivo de imagem de memória
CloseHandle(MemFile); //Fecha o arquivo de imagem
ExitProc := ProcSaveExit;
fim;
exporta // define a função de saída
HabilitarKeyHook,
DesativarKeyHook,
ObterKeyCount,
ClearKeyString,
Obterchave;
começar
//parte de inicialização da DLL
HookMutex:=CreateMutex(nil,True,HOOK_MUTEX_NAME);
//Compartilha memória criando um arquivo de imagem de memória
MemFile:=OpenFileMapping(FILE_MAP_WRITE,Falso,
HOOK_MEM_FILENAME);
se MemFile=0 então
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
SizeOf(TShared),HOOK_MEM_FILENAME);
Compartilhado:=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);
ReleaseMutex(HookMutex);
CloseHandle(HookMutex);
ProcSaveExit := ExitProc; // Salva o ExitProc da DLL
ExitProc := @KeyHookExit; // Define o novo ExitProc da DLL
fim.
//Fim do código fonte
2. Use a função de filtro de gancho de teclado preparada em seu próprio programa.
Depois que a função de gancho é compilada, ela é realmente muito simples de usar: primeiro chame SetWindowsHookEx para instalar sua própria função de filtro de gancho e, ao mesmo tempo, salve o endereço original da função de filtro de gancho. Neste momento, a função de gancho entra em ação e manipulará as mensagens do teclado de acordo com suas necessidades. Quando a execução do programa terminar ou não for mais necessário monitorar as mensagens do teclado, chame a função UnHookWindowsHookProc para desinstalar a função de gancho instalada e restaurar o endereço original da função de filtro de gancho.
A seguir está um exemplo de uso da função hook compilada acima:
unidade Unidade1;
interface
usa
Windows, Mensagens, SysUtils, Classes, Gráficos, Controles, Formulários, Diálogos,
StdCtrls, ExtCtrls;
tipo
TForm1 = classe(TForm)
Memo1: TMemo;
Painel1: TPanel;
bSetHook: TButton;
bCancelHook: TButton;
bReadKeys: TButton;
bClearKeys: TButton;
Painel2: TPanel;
procedimento bSetHookClick(Remetente: TObject);
procedimento bCancelHookClick(Sender: TObject);
procedimento bReadKeysClick(Sender: TObject);
procedimento bClearKeysClick(Sender: TObject);
fim;
var Formulário1: TForm1;
implementação
{$R *.DFM}
função EnableKeyHook: BOOL; externo 'KEYHOOK.DLL';
função DisableKeyHook: BOOL; externo 'KEYHOOK.DLL';
função GetKeyCount: Inteiro; externo 'KEYHOOK.DLL';
função GetKey (idx: Inteiro): Char; externo 'KEYHOOK.DLL';
procedimento ClearKeyString; externo 'KEYHOOK.DLL';
procedimento TForm1.bSetHookClick(Sender: TObject); // Define o gancho do teclado 7ó;
começar
HabilitarKeyHook;
bSetHook.Enabled :=Falso;
bCancelHook.Enabled:=True;
bReadKeys.Enabled :=Verdadeiro;
bClearKeys.Enabled :=Verdadeiro;
Panel2.Caption:='O gancho do teclado foi definido';
fim;
procedimento TForm1.bCancelHookClick(Sender: TObject); // Desinstala o gancho do teclado;
começar
DesabilitarKeyHook;
bSetHook.Enabled :=Verdadeiro;
bCancelHook.Enabled:=Falso;
bReadKeys.Enabled :=Falso;
bClearKeys.Enabled :=Falso;
Panel2.Caption:='O gancho do teclado não está definido';
fim;
procedimento TForm1.bReadKeysClick(Sender: TObject);
var i:Inteiro;
começar
Memo1.Lines.Clear; // Exibe o histórico de teclas digitadas no Memo1
para i:=0 para GetKeyCount-1 faça
Memo1.Text:=Memo1.Text+GetKey(i);
fim;
procedimento TForm1.bClearKeysClick(Sender: TObject); // Limpar histórico de teclas digitadas;
começar
Memo1.Limpar;
ClearKeyString;
fim;
fim.
//Fim do código fonte
3. Implementando memória compartilhada em DLL no Windows95
No arquivo DLL onde a função de gancho acima está localizada, é necessário utilizar memória compartilhada, ou seja, todos os registros de pressionamentos de tecla são armazenados no mesmo segmento de dados. Por que fazemos isso? Isso ocorre porque o método de chamada de DLL do Windows95 é diferente daquele do Windows3.X. Quando cada thread faz login em uma biblioteca de vínculo dinâmico, ele passa um novo identificador de instância (ou seja, o identificador do segmento de dados DLL) para a biblioteca de vínculo dinâmico. Isso permite que as diversas instâncias da DLL não interfiram umas nas outras, mas traz algumas dificuldades quando todas as instâncias da DLL compartilham um conjunto de variáveis. Para resolver este problema, nós o resolvemos aqui criando um arquivo mapeado na memória. Ou seja, usando OpenFileMapping, CreateFileMapping e
MapViewOfFile três funções para alcançar. Como usar:
…
MemFile é um tipo THandle, Shared é um tipo de ponteiro e HOOK_MEM_FILENAME é uma string constante.
…
MemFile:=OpenFileMapping(FILE_MAP_WRITE,Falso,
HOOK_MEM_FILENAME); //Abre arquivo mapeado na memória
if MemFile=0 then //Se a abertura falhar?_c2 Crie um arquivo mapeado na memória
MemFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,
SizeOf(TShared),HOOK_MEM_FILENAME);
//Mapear arquivos para variáveis
Compartilhado:=MapViewOfFile(MemFile,File_MAP_WRITE,0,0,0);
Até agora você já sabe como é fácil compilar funções hook no Delphi. Finalmente, devo lembrar a todos: embora a função de gancho seja relativamente poderosa, se usada incorretamente, ela afetará seriamente a eficiência do sistema, portanto, tente evitar o uso de ganchos do sistema. Deve-se tomar cuidado extra na hora de utilizá-lo, para que afete o menos possível o funcionamento do sistema.
[Fim do texto completo]