Buscar

Capturar teclas digitadas em qualquer local do windows, mesmo fora do form principal (correcao)

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),
                               'OReceptor');

    {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.
}

Publicidade

Vote na dica




Quantidade de votos: 0 votos
Aceitação: 0%


Detalhes da dica

Categoria: Forms
Adicionada dia: 14/08/07
Por: Rodrigo
Visualizada: 15905 vezes

Planeta Delphi - Tudo sobre programação Delphi Planeta Delphi - www.planetadelphi.com.br - Todos os direitos reservados | Copyright 2001-2009