Código
O funcionamento eh o seguinte:
# Criamos uma DLL com duas funcoes que exportaremos, uma para instalar o hook e outra para desinstala-lo.
# Ha uma terceira funcao que eh a que executará o hook uma vez instalado (CallBack). Nela, o que faremos eh enviar os dados da mensagem capturado a nossa aplicacao.
A DLL deve saber em todo momento o handle da aplicacao receptora, de modo que faremos que o leia de um arquivo mapeado na memoria que criaremos desde a propria aplicacao.
Eis um exemplo de uso de arquivos mapeados na memoria:
- Compartilhar dados entre dois aplicativos Delphi
Enviaremos os dados desde a DLL para a aplicacao através de uma mensagem do usuario. Tambem se usa esta técnica da seguinte maneira:
- Prevenir duas execucoes simultaneas da sua aplicacao
Bem, vamos ao exemplo:
****** A DLL QUE INSTALA O HOOK: ******
1. Crie o esqueleto de uma DLL (File / New / DLL);
2. Troque o codigo do projeto por este outro abaixo:
}
////// AQUI COMECA O CODIGO DA DLL//////
library HookTeclado;
{
Demonstracao de Hook de teclado a nivel de sistema, Radikal.
Como o que queremos é capturar as teclas pressionadas em qualquer parte
do Windows, precisamos instalar a função CallBack que chamará
o Hook em uma DLL, que é esta mesma.
}
uses
Windows,
Messages;
const
CM_MANDA_TECLA = WM_USER + $1000;
var
HookDeTeclado : HHook;
ArquivoM : THandle;
PReceptor : ^Integer;
function CallBackDelHook( Code : Integer;
wParam : WPARAM;
lParam : LPARAM
) : LRESULT; stdcall;
{Esta é a funcao CallBack que chamará o hook.}
begin
{Se uma tecla foi pressionada ou liberada}
if code=HC_ACTION then begin
{Observamos se o arquivo existe}
ArquivoM:=OpenFileMapping(FILE_MAP_WRITE,False,'OReceptor');
{Se nao existe, nao enviamos nada para a aplicacao receptora}
if ArquivoM<>0 then begin
PReceptor:=MapViewOfFile(ArquivoM,FILE_MAP_WRITE,0,0,0);
PostMessage(PReceptor^,CM_MANDA_TECLA,wParam,lParam);
UnmapViewOfFile(PReceptor);
CloseHandle(ArquivoM);
end;
end;
{Chamamos ao seguinte hook de teclado da cadeia}
Result := CallNextHookEx(HookDeTeclado, Code, wParam, lParam)
end;
procedure HookOn; stdcall;
{Procedure que instala o hook}
begin
HookDeTeclado:=SetWindowsHookEx(WH_KEYBOARD, @CallBackDelHook, HInstance , 0);
end;
procedure HookOff; stdcall;
begin
{procedure para desinstalar o hook}
UnhookWindowsHookEx(HookDeTeclado);
end;
exports
{Exportamos as procedures...}
HookOn,
HookOff;
begin
end.
////// AQUI TERMINA O CODIGO DA DLL//////
{
3. Salve o projeto com o nome 'HookTeclado.dpr' e compile-o, para gerar a DLL.
É provavel que o Delphi apresente a mensagem de erro:
"Cannot debug project unless a host application is defined. Use the Run|Parameters... dialog box."
Caso esta mensagem apareca, abra o menu Run / Parameters, e preencha o campo *Host Application* com o endereco do executavel do programa que utilizarah esta DLL. Caso o programa ainda nao tenha sido criado, apenas salve a DLL.
MAS LEMBRE-SE!! Apos criar o programa (que faremos na sequencia), retorne ao projeto da DLL e faca isso, caso contrario, o programa NAO FUNCIONARÁ!!
****** APLICACAO QUE RECEBE DADOS DO HOOK ******
1. Crie uma nova aplicacao;
2. Inclua um TMemo(Memo1) no Form1
3. Troque o codigo da Unit do Form por este outro abaixo
}
////// AQUI COMECA O CODIGO DA APLICACAO //////
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
const
NomeDLL = 'HookTeclado.dll';
CM_MANDA_TECLA = WM_USER + $1000;
type
THookTeclado=procedure; stdcall;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
ArquivoM : THandle;
PReceptor : ^Integer;
HandleDLL : THandle;
HookOn,
HookOff : THookTeclado;
procedure LlegaDelHook(var message: TMessage); message CM_MANDA_TECLA;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
{Nao queremos que o memo seja editado conforme a tecla pressionada}
Memo1.ReadOnly:=TRUE;
HandleDLL:=LoadLibrary( PChar(ExtractFilePath(Application.Exename)+NomeDLL ) );
if HandleDLL = 0 then raise Exception.Create('Não foi possível carregar a DLL!');
@HookOn :=GetProcAddress(HandleDLL, 'HookOn');
@HookOff:=GetProcAddress(HandleDLL, 'HookOff');
IF not assigned(HookOn) or
not assigned(HookOff) then
raise Exception.Create('Não foram encontradas as funções na DLL');
{Criamos o arquivo de memoria}
ArquivoM:=CreateFileMapping( $FFFFFFFF,
nil,
PAGE_READWRITE,
0,
SizeOf(Integer),
'ElReceptor');
{Se o arquivo nao se criou, erro}
if ArquivoM=0 then
raise Exception.Create( 'Erro ao criar o arquivo');
{Direcionamos nossa estrutura ao arquivo de memoria}
PReceptor:=MapViewOfFile(ArquivoM,FILE_MAP_WRITE,0,0,0);
{Escrevemos dados no arquivo de memoria}
PReceptor^:=Handle;
HookOn;
end;
procedure TForm1.LlegaDelHook(var message: TMessage);
var
NomeTecla : array[0..100] of char;
Acao : string;
begin
{Traduzimos de "Virtual key Code" a "TEXTO"}
GetKeyNameText(Message.LParam,@NomeTecla,100);
{Observamos se a tecla foi pressionada, soltada o repetida}
if ((Message.lParam shr 31) and 1)=1 then
Acao:='Solta'
else
if ((Message.lParam shr 30) and 1)=1 then
Acao:='Repetida'
else Acao:='Pressionada';
Memo1.Lines.Append( Acao+
' tecla: '+
String(NomeTecla) );
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
{Desativamos o Hook}
if Assigned(HookOff) then
HookOff;
{Liberamos a DLL}
if HandleDLL<>0 then
FreeLibrary(HandleDLL);
{Fechamos a vista do arquivo e o arquivo}
if ArquivoM<>0 then begin
UnmapViewOfFile(PReceptor);
CloseHandle(ArquivoM);
end;
end;
end.
////// AQUI TERMINA O CODIGO DA APLICACAO //////
{
Grave o projeto no mesmo diretorio da DLL e compile-o.
Se voce seguiu todos os passos ateh aqui, deverah ter no diretorio dos projetos uma DLL (HookTeclado.DLL) e o executavel da aplicacao receptora.
Execute a aplicacao e observe como o Memo1 armazena o historico das teclas pressionadas em qualquer parte do Windows.
}
Planeta Delphi - www.planetadelphi.com.br - Todos os direitos reservados | Copyright 2001-2009