Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > C++ Builder
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 21-11-2014
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Hook de teclado con filtro de pulsaciones

Hola amigos, me gustaria crear un hook el cual me permita capturar las pulsaciones de teclado y poder anular pulsaciones como el Ctrl+C y otras que interfieran con el buen funcionamiento de mi aplicacion. Tengo este codigo:

dll.cpp:
Código PHP:
#include <windows.h>
#include "dll.h"

#pragma data_seg("SharedBlock")
#pragma data_seg()

#define OK -32767 //Necesario para el keylogger

enum {LCtrl,RCtrl,HacerClic,Cerrar,Activar,Desactivar,Mostrar,Ocultar,Maximizar,Restaurar,Minimizar,SiempreEncima,NoEncima,Enviar};

HHOOK gancho;

/**********************************************/
/*FUNCION PARA FILTRAR LOS RESULTADOS DEL HOOK*/
/**********************************************/
LRESULT CALLBACK Filtro(int nCodeWORD wParamDWORD lParam)
{
   
int retval=0;

   if(
nCode<0){
      return(
CallNextHookEx(gancho,nCode,wParam,lParam));
   }

   
//si hay datos, los guardamos
   
if (lParam & (<< 31)) {
      
BYTE KeyboardState[256];
      
GetKeyboardState(KeyboardState);
      
WORD CharValue;
           
      
//Aqui el codigo de filtrado de pulsaciones
      
if(GetAsyncKeyState(VK_LCONTROL)==OK){ //si está pulsada [Ctrl(Izq)]
         
retval LCtrl;
      }else if(
GetAsyncKeyState(VK_RCONTROL)==OK){ //si está pulsada [Ctrl(Dcha)]
         
retval RCtrl;
      }else if((
GetKeyState(76) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+L]
         
retval HacerClic;
      }else if((
GetKeyState(67) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+C]
         
retval Cerrar;
      }else if((
GetKeyState(65) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+A]
         
retval Activar;
      }else if((
GetKeyState(68) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+D]
         
retval Desactivar;
      }else if((
GetKeyState(77) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+M]
         
retval Mostrar;
      }else if((
GetKeyState(79) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+O]
         
retval Ocultar;
      }else if((
GetKeyState(88) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+X]
         
retval Maximizar;
      }else if((
GetKeyState(82) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+R]
         
retval Restaurar;
      }else if((
GetKeyState(73) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+I]
         
retval Minimizar;
      }else if((
GetKeyState(83) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+S]
         
retval SiempreEncima;
      }else if((
GetKeyState(78) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+N]
         
retval NoEncima;
      }else if((
GetKeyState(69) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+E]
         
retval Enviar;
      }
   }
   return 
CallNextHookEx(gancho,nCode,wParam,lParam);
}

/*******************************************************/
/*FUNCIÓN PARA INSTALAR/DESINSTALAR EL HOOK DEL TECLADO*/
/*******************************************************/
extern "C" __declspec(dllexport)int CreaHook(BOOL InstalaHINSTANCE DLLInst)
{
   
int retval;

   if(
Instala==TRUE) {
      
gancho=SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)Filtro,DLLInst,0);
      if(
gancho==NULL){
         
retval 0;
      }else{
         
retval 1;
      }
   }else{
      
retval UnhookWindowsHookEx(gancho);
   }
   return 
retval;
}

/*************************/
/*PROCEDIMIENTO PRINCIPAL*/
/*************************/
BOOL WINAPI DllMain(HANDLE hModuleDWORD dwFunctionLPVOID lpNot)
{
  return 
TRUE;

dll.h:
Código PHP:
#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT extern "C" __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT extern "C" __declspec (dllimport)
#endif /* Not BUILDING_DLL */

LRESULT CALLBACK Filtro(int nCodeWORD wParamDWORD lParam);
extern "C" __declspec(dllexport)int CreaHook(BOOL Instala,HINSTANCE DLLInst);

#endif /* _DLL_H_ */ 
Unit1.cpp:
Código PHP:
#include <vcl.h>
#pragma hdrstop
#include <windows.h>

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

HMODULE Dll;

typedef void (*LPFuncion)(BOOL,HINSTANCE/*Redefiní la funcion*/);
LPFuncion Funcion=NULL;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
   : 
TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    
//cargamos la Dll
    
Dll=LoadLibrary("HookKeyboard.dll");
    if(!
Dll){
      
ShowMessage("No se encontró la Dll: RBT_KLogger.dll");
      return;
    }
  
    
//buscamos la funcion en la dll
    
Funcion = (LPFuncion)GetProcAddress(Dll"_CreaHook");
    if(!
Funcion){
      
ShowMessage("ERROR");
      
FreeLibrary(Dll);
      return;
    }
  
    
//ejecutamos la función
    
Funcion(TRUE,Dll);//instalamos el hook
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
   
//desinstalamos el hook
    
Funcion(FALSE,NULL);

    
//liberamos la memoria
    
FreeLibrary(Dll);
}
//--------------------------------------------------------------------------- 
De momento no se como aplicar el filtro. El hook funciona pero no se que hacer para filtrar esas pulsaciones.
Otra cosa, ¿por que me exporta CreaHook como _CreaHook?¿No se supone que el extern "C" evita eso?
Responder Con Cita
  #2  
Antiguo 21-11-2014
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Este me funciona fenomenal pero no me evita que se ejecute el atajo de teclas en la ventana en que esté en ese momento:

Trozo de codigo de Unit1.h:
Código PHP:
   //Comprobamos si se pulsó algún atajos de teclado
   
switch(Combinacion)
   {
      case 
HacerClic:
         
ButtonClic->Click();
         
Sleep(150);
         break;

      case 
Cerrar:
         
ButtonClose->Click();
         break;

      case 
Activar:
         
ButtonEnable->Click();
         break;

      case 
Desactivar:
         
ButtonDisable->Click();
         break;

      case 
Mostrar:
         
ButtonShow->Click();
         break;

      case 
Ocultar:
         
ButtonHide->Click();
         break;

      case 
Maximizar:
         
ButtonMaximize->Click();
         break;

      case 
Restaurar:
         
ButtonRestore->Click();
         break;

      case 
Minimizar:
         
ButtonMinimize->Click();
         break;

      case 
SiempreEncima:
         
ButtonTopmost->Click();
         break;

      case 
NoEncima:
         
ButtonNonTop->Click();
         break;

      case 
Enviar:
         
ButtonSendCaption->Click();
         break;
   } 
Funcion que controla las pulsaciones:
Código PHP:
/*==============================================================
    ESTA FUNCIÓN ES LA QUE CAPTURA LAS TECLAS DE CONTROL
==============================================================*/
bool KeyLogger(int *combinacion)
{
   
bool retval false;
   *
combinacion 0;
   
   if(
GetAsyncKeyState(VK_LCONTROL)==OK){ //si está pulsada [Ctrl(Izq)]
      
retval true;
   }else if(
GetAsyncKeyState(VK_RCONTROL)==OK){ //si está pulsada [Ctrl(Dcha)]
      
retval true;
   }else if((
GetKeyState(76) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+L]
      
*combinacion HacerClic;
   }else if((
GetKeyState(67) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+C]
      
*combinacion Cerrar;
   }else if((
GetKeyState(65) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+A]
      
*combinacion Activar;
   }else if((
GetKeyState(68) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+D]
      
*combinacion Desactivar;
   }else if((
GetKeyState(77) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+M]
      
*combinacion Mostrar;
   }else if((
GetKeyState(79) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+O]
      
*combinacion Ocultar;
   }else if((
GetKeyState(88) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+X]
      
*combinacion Maximizar;
   }else if((
GetKeyState(82) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+R]
      
*combinacion Restaurar;
   }else if((
GetKeyState(73) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+I]
      
*combinacion Minimizar;
   }else if((
GetKeyState(83) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+S]
      
*combinacion SiempreEncima;
   }else if((
GetKeyState(78) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+N]
      
*combinacion NoEncima;
   }else if((
GetKeyState(69) < 0) && ((GetKeyState(VK_LCONTROL) < 0) || (GetKeyState(VK_RCONTROL) < 0))){ //si pulsamos [Alt+E]
      
*combinacion Enviar;
   }

   return 
retval;
}
//--------------------------------------------------------------------------- 
Si por ejemplo estoy seleccionando un texto del notepad y doy a Ctrl+C me funciona mi codigo perfectamente pero tambien me copia el texto que estaba seleccionado al portapapeles. Eso es lo que me gustaria evitar que, por ejemplo en este caso, no se entere de que tiene que copiar al portapapeles.
Responder Con Cita
  #3  
Antiguo 22-11-2014
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
me han comentado que lo que quiero hacer se hace con RegisterHotKey y UnregisterHotKey. He encontrado algun ejemplo incluso aqui y quiero probar pero mi duda es ¿Que pasa si el HotKey global ya existe? Por ejemplo Ctrl+C si yo creo la mia supongo que la mia sobreescribe la que hay y al eliminar la mia ¿Vuelve a estar operativa la anterior o me la he cargado? Evidentemente el Id seria diferente.
Responder Con Cita
  #4  
Antiguo 22-11-2014
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Puedes hacerlo como quieras. El Hook engancha antes de procesar la pulsación. HotKey te envía un mensaje.
El problema es actuar en el ClipBoard, tienes que trampearlo.

No es necesaria una dll para un hook de teclado, hazlo a bajo nivel.

Te muestro un ejemplo simple para evitar la copia al ClipBoard con un Hook LL al teclado:

Código PHP:
HHOOK  hKeybHook;

LRESULT WINAPI KeybEvent(int nCodeWPARAM wParamLPARAM lParam)
{
   if( (
nCode == HC_ACTION) && ((wParam == WM_SYSKEYDOWN) || (wParam == WM_KEYDOWN)) ){

     
bool Ctl_C GetAsyncKeyState(VK_CONTROL) && (*(PDWORD)lParam == 0x43); //VK_C;
     
bool Ctl_V GetAsyncKeyState(VK_CONTROL) && (*(PDWORD)lParam == 0x56); //VK_V;

     
if(Ctl_C){
       
CloseClipboard();
       
OpenClipboard(0);
       
EmptyClipboard();
     }
     else if(
Ctl_V
       
CloseClipboard();
   }

   return 
CallNextHookEx(hKeybHooknCodewParamlParam);
}

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  
hKeybHook  SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeybEventGetModuleHandle(NULL), 0);
  
Beep(1000100);
}

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
  
UnhookWindowsHookEx(hKeybHook);
  
CloseClipboard();

Saludos.
Responder Con Cita
  #5  
Antiguo 22-11-2014
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
mmm ¿pero eso tendria que hacer trampeos con todas las combinaciones? Segun me dijeron, con RegisterHotKey se ejecuta la que yo quiero y yo me encargo de que se ejecute lo demas que se deba ejecutar para esa combinacion. Creo que si es asi me quedo con ese metodo.
Responder Con Cita
  #6  
Antiguo 22-11-2014
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Mi respuesta responde al título del hilo: "Hook de teclado con filtro de pulsaciones"

Para conseguir tu objetivo con el ClipBoard, el método por hotkeys es más fácil y directo en este caso, pero no es un hook, de forma tendrás que registrar cada combinación de teclas que quieras manejar para otras cuestiones. Tu eliges que técnica usar.


Saludos.
Responder Con Cita
  #7  
Antiguo 23-11-2014
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Bueno, me he decidido por usar el registrado de los atajos y tengo esto:
Código PHP:
private:    // User declarations
   
bool AtajosGlobales;
   
TMessageEvent OldApplicationOnMessage;

protected:
   
virtual void __fastcall AppMessage(tagMSG &Msgbool &Handled); 
Código PHP:
void __fastcall TForm1::AppMessage(tagMSG &Msgbool &Handled)
{
   if(
Msg.message == WM_HOTKEY)
   {
      
//Comprobamos si se pulsó algún atajo de teclado

      
if((LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'L'))
      {
         
ButtonClic->Click();
         
Sleep(150);
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'C'))
      {
         
ButtonClose->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'D'))
      {
         
ButtonDisable->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'A'))
      {
         
ButtonEnable->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'M'))
      {
         
ButtonShow->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'O'))
      {
         
ButtonHide->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'X'))
      {
         
ButtonMaximize->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'R'))
      {
         
ButtonRestore->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'I'))
      {
         
ButtonMinimize->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'S'))
      {
         
ButtonTopmost->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'N'))
      {
         
ButtonNonTop->Click();
      }else if((
LOWORD(Msg.lParam) == MOD_CONTROL) && (HIWORD(Msg.lParam) == 'E'))
      {
         
ButtonSendCaption->Click();
      }else{
         
OldApplicationOnMessage(Msg,Handled);
      }
   }else{
      
OldApplicationOnMessage(Msg,Handled);
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *SenderTCloseAction &Action)
{
   if(
AtajosGlobales == true)
   {
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey1"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey2"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey3"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey4"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey5"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey6"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey7"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey8"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey9"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey10"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey11"));
      
UnregisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey12"));
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
   
OldApplicationOnMessage Application->OnMessage;
   
Application->OnMessage AppMessage;

   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey1"), MOD_CONTROL,'L');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey2"), MOD_CONTROL,'C');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey3"), MOD_CONTROL,'D');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey4"), MOD_CONTROL,'A');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey5"), MOD_CONTROL,'M');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey6"), MOD_CONTROL,'O');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey7"), MOD_CONTROL,'X');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey8"), MOD_CONTROL,'R');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey9"), MOD_CONTROL,'I');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey10"), MOD_CONTROL,'S');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey11"), MOD_CONTROL,'N');
   
RegisterHotKey(Application->HandleGlobalAddAtomA("MiHotKey12"), MOD_CONTROL,'E');

Lo que quiero es que cuando no sea uno de los atajos que yo he registrado el programa el resto funcione perfectamente pero no consigo ni que compile. ¿alguna ayuda para hacerlo bien?
Responder Con Cita
  #8  
Antiguo 25-11-2014
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Poder: 11
aguml Va por buen camino
Yo uso MAKEINTATOM para obtener el id con lo que para poder hacerlo como indicas tendria que almacenar todos los ids de los atoms y luego usar estos en los cases. La verdad es que asi ya funciona perfectamente y el codigo lo saque de codegear.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
como capturar pulsaciones del teclado y guardarlo en un archivo txt kurono Varios 25 15-01-2008 12:25:26
Hook de Teclado + DLL FeLiXxUcO C++ Builder 12 12-02-2006 19:59:53
capturar pulsaciones de teclado i_berbeu C++ Builder 3 08-02-2006 23:00:35
Hook de teclado! marceloalegre Varios 2 17-10-2005 00:59:47
Obtenert el handler de la ventana donde se han de enviar las pulsaciones del teclado ASAPLTDA API de Windows 0 07-04-2005 23:38:56


La franja horaria es GMT +2. Ahora son las 22:50:36.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi