 |
Club Builder Foro de C++Builder en español
|
| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
Cesar C. Salazar Gonzalez Master


Registrado: 01 Oct 2002Mensajes: 2155Ubicación: San Cristóbal de Las Casas, Chiapas
|
Publicado: Dom 12 May, 2019 11:26 pm Asunto: [Cerrado] HookMouse y botón medio |
|
|
¡Un gusto regresar al foro y saber que sigue vigente!
(algunos problemas en el acceso pero nada que no tengan mis viejas notas y asunto solucionado).
Pasando al tema.
Tengo el siguiente código para interceptar los botones del teclado, por cuestiones de plataforma, trabajo en una versión de Windows 2008 R2 y la versión de prueba de 30 días de Embarcadero Rio 10.3 (Muchos cambios en el IDE pero mismos bugs pasados) sobre una maquina virtual de VMWare.
Copie una DLL (el código está en la siguiente página https://www.developpez.net/forums/d1596709/c-cpp/outils-c-cpp/code-blocks/hook-probleme-tuto/ )
Y le hice algunas modificaciones para "capturar" el botón medio del Mouse, funciona "bien" ya que en veces no realiza la captura y otras veces sin pena ni gloria trabaja como debe ser.
MouseHook.cpp
| Código: |
#pragma hdrstop
#include <vcl.h>
#include <windows.h>
#define _DLL_CCSG_
#include "MouseHook.h">
typedef struct _TDonnees
{
HHOOK MouseHookHandle;
HHOOK KeybdHookHandle;
HWND hDestWindow;
} TDonnees;
//-------------------------------------------------------------
HANDLE MemPartagee;
TDonnees * VueDonnees;
HINSTANCE HInst;
//-------------------------------------------------------------
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam);
//---------------------------------------------------------------
HHOOK HookHandle;
bool IsInRect=false;
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
HInst = hinst;
switch(reason)
{
case DLL_PROCESS_ATTACH:
MemPartagee = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, sizeof(TDonnees), L"Monedero");
VueDonnees = (TDonnees*) (MapViewOfFile((HANDLE) MemPartagee, FILE_MAP_WRITE, 0, 0, 0));
break;
case DLL_PROCESS_DETACH:
UnmapViewOfFile((LPVOID)VueDonnees);
CloseHandle(MemPartagee);
break;
default:
break;
}
return 1;
}
//---------------------------------------------------------------------------
FUNCION_DLL bool __stdcall InstallMouseHook(HWND hDest)
{
VueDonnees->hDestWindow = hDest;
if( VueDonnees->hDestWindow == NULL)
return false;
else
{
VueDonnees->MouseHookHandle = SetWindowsHookEx( WH_MOUSE_LL,
reinterpret_cast<HOOKPROC>(MouseProc),
HInst,
return true;
}
}
//---------------------------------------------------------------------------
FUNCION_DLL bool __stdcall RemoveMouseHook()
{
return !UnhookWindowsHookEx(VueDonnees->MouseHookHandle);
}
//---------------------------------------------------------------------------
#define WM_ABS_MOUSE WM_USER + 25
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam)
{
if ( code == HC_ACTION && (wParam == WM_MBUTTONUP) )
{
PostMessage(VueDonnees->hDestWindow, WM_ABS_MOUSE, wParam, lParam);
}
else
return CallNextHookEx(VueDonnees->MouseHookHandle,code ,wParam,lParam);
return CallNextHookEx(VueDonnees->MouseHookHandle,code ,wParam,lParam);
}
//---------------------------------------------------------------------------
|
MouseHook.h
| Código: |
#include <vcl.h>
//---------------------------------------------------------------------------
#ifndef MouseHookH
#define MouseHookH
#include <SysInit.hpp>
#include <windows.h>
#ifdef _DLL_CCSG_
#define FUNCION_DLL extern "C" __declspec(dllexport)
#else
#define FUNCION_DLL extern "C" __declspec(dllimport)
#endif
#endif
|
Y uso la siguiente información para cargar la DLL en un formulario.
Archivo.h
| Código: |
TIniciar InitHooks;
TFinalizar EndHooks;
HINSTANCE hinstDLL;
bool bHook;
void __fastcall Moneda(TWMNoParams &p);
protected: // déclaration du gestionaire de messages
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_ABS_MOUSE, TWMNoParams, Moneda)
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
|
y este es el proceso para cargar la DLL en el formulario principal
Archivo.cpp
| Código: |
void __fastcall Tabs_FPrincipal::FormCreate(TObject *Sender)
{
Screen->OnActiveControlChange = this->ActiveControlChanged;
::abs_dmConexion->ArranqueAplicacion();
// cargamos la DLL
bHook = false;
hinstDLL = ::LoadLibraryW(L"MouseHook.dll");
if (!hinstDLL)
{
Application->MessageBox(L"Dll no cargada",L"Sistema",MB_OK);
Application->Terminate();
exit(EXIT_SUCCESS);
}
else
{
InitHooks = (TIniciar)GetProcAddress(hinstDLL, "InstallMouseHook");
InitHooks(this->Handle);
}
}
//---------------------------------------------------------------------------
// proceso para cuando se captura el clic del botón medio
void __fastcall Tabs_FPrincipal::Moneda(TWMNoParams &p)
{
this->moneda++; // solo se incrementa por cada clic
}
//---------------------------------------------------------------------------
|
la pregunta es: ¿Existe alguna manera de realizar dicha DLL de otra forma y capturar "siempre" el clic del botón medio del ratón?
por la lectura a este post, muchas gracias. _________________

Ultima edición por Cesar C. Salazar Gonzalez el Vie 17 May, 2019 12:59 pm, editado 1 vez |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Jue 16 May, 2019 2:33 pm Asunto: |
|
|
Hola Cesar, que tal?
Una de las ventajas de WH_MOUSE_LL y WH_KEYBOARD_LL es que no es necesario usar una .DLL
Yo uso algo similar a esto, pero para el teclado en aplicaciones desde hace años y me funciona sin problemas:
Unit1.h
| Código: |
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private: // User declarations
static const UINT WM_MOUSE_HOOK = WM_APP + 130;
HHOOK hook;
static LRESULT CALLBACK LLMouseProc(int code, WPARAM w, LPARAM l);
void __fastcall WmMouseHook(TMessage& msg);
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_MOUSE_HOOK, TMessage, WmMouseHook)
END_MESSAGE_MAP(TForm)
public: // User declarations
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
|
Unit1.cpp
| Código: |
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner),
hook(SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)LLMouseProc, HInstance, 0))
{
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
UnhookWindowsHookEx(hook);
}
//---------------------------------------------------------------------------
LRESULT CALLBACK TForm1::LLMouseProc(int code, WPARAM w, LPARAM l)
{
if (code == HC_ACTION)
{
switch (w)
{
case WM_MBUTTONUP:
PostMessage(Form1->Handle, WM_MOUSE_HOOK, w, l);
return TRUE;
case WM_MBUTTONDOWN:
return TRUE;
}
}
return CallNextHookEx(Form1->hook, code, w, l);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WmMouseHook(TMessage& msg)
{
ShowMessage("Botón central pulsado");
}
//---------------------------------------------------------------------------
|
En este ejemplo intercepto WM_MBUTTON_UP y una vez interceptado evito que cualquier otro proceso reciba ese mensaje. Y luego en WM_MBUTTONDOWN, aunque no hace nada, también lo intercepta para que no entren en la cola de mensajes DOWN sin UP que causaría problemas, ya que se vería como que el botón se ha quedado pulsado fijo.
Lo del PostMessage no es estrictamente necesario, pero es una forma de evitar problemas. Se podría poner el código necesario dentro de la propia "LLMouseProc(...)", pero hay un limite de tiempo que tienes para atender lo que sucede dentro de esa función, si te pasas del tiempo (según la documentación de la API son 5 segundos) se pasaría al siguiente HOOK de la cadena y puede ser interceptado por otro proceso aparte del tuyo.. |
|
| Volver arriba |
|
 |
Cesar C. Salazar Gonzalez Master


Registrado: 01 Oct 2002Mensajes: 2155Ubicación: San Cristóbal de Las Casas, Chiapas
|
Publicado: Vie 17 May, 2019 12:46 am Asunto: |
|
|
Muchas gracias _Leo por contestar.
Una pregunta ¿Esto también me sirve para cuando la aplicación no tiene el foco?
Me falto comentar en el post, que es para la recolección de monedas, existe un dispositivo (chino) que al insertar monedas envía un pulso este pulso lo han adaptado para que envíe el clic del botón medio del mouse conectado a una PC, así que probaré la función y si puedo capturar el botón medio con este proceso, podré eliminar la DLL del programa.
Por lo anterior, muchas gracias!! _________________
 |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Vie 17 May, 2019 1:15 am Asunto: |
|
|
| Si, da igual que no tenga el foco e incluso que la ventana este oculta todo el tiempo. |
|
| Volver arriba |
|
 |
Cesar C. Salazar Gonzalez Master


Registrado: 01 Oct 2002Mensajes: 2155Ubicación: San Cristóbal de Las Casas, Chiapas
|
Publicado: Vie 17 May, 2019 12:58 pm Asunto: |
|
|
Muchas gracias, doy el tema cerrado. _________________
 |
|
| Volver arriba |
|
 |
|
|
No puedes publicar temas nuevos en este foro No puedes responder a temas en este foro No puedes editar tus mensajes en este foro No puedes borrar tus mensajes en este foro No puedes votar en las encuestas de este foro
|
© 2002–2026 Club Builder · Funciona con phpBB.
|