C ++ Builder — C ++, использующий SetWindowsHookEx, работает только со странным кодом vcl, добавленным в него. в BCB2009

У меня странная ситуация с использованием SetWindowsHookEx

У меня есть проект bcb 2009 с формой и запиской.

при создании мы загружаем Dll и прикрепляем обработчик функции к обеим сторонам.

Идея состоит в том, что при нажатии на клавиатуре сообщение появляется в блокноте, а когда происходит событие мыши, в блоке появляется другой текст.

Странно, что когда я очищаю код от отладочной информации, он перестает работать. Это означает, что один раз крючок сработал, а потом все закончилось.
В отладке я использовал некоторый VCL TStringList для записи данных о том, что данные хранятся на диске. Играя с этим кодом, я наконец обнаружил это, добавив

[код]
TList* lList = new TList();
delete lList;

Для каждой из функций ловушки (клавиатура, мышь) код снова работает.

Что плохого в моем коде, что я должен сделать это?

Впервые за 15 лет я делаю dll. так что это может быть чем-то реальным в создании DLL или экспорте функций.

Любое предложение приветствуется.

С уважением

JVDN

Некоторая новая дополнительная информация:

[решено] Моя цель — встроенная Win XP. мое приложение создает ошибку, которая закрывает проводник окнами. И хук не работает глобально в XP, а только локальный. Но он работает на моей платформе разработки win 7 x64, глобальная типизация и ввод в блокноте приводят к сообщениям в приложении.
[решение] Изменено WH_KEYBOARD на WH_KEYBOARD_LL, а мышь от WH_MOUSE до WH_MOUSE_LL решает вопрос о получении ключа и мыши на встроенной Windows XP.

И в dll, и в приложении нет библиотеки или пакетов времени выполнения.

Код DLL

[код]
//---------------------------------------------------------------------------

#include <vcl.h>
#include <windows.h>
#pragma hdrstop
//---------------------------------------------------------------------------
//   Important note about DLL memory management when your DLL uses the
//   static version of the RunTime Library:
//
//   If your DLL exports any functions that pass String objects (or structs/
//   classes containing nested Strings) as parameter or function results,
//   you will need to add the library MEMMGR.LIB to both the DLL project and
//   any other projects that use the DLL.  You will also need to use MEMMGR.LIB
//   if any other projects which use the DLL will be performing new or delete
//   operations on any non-TObject-derived classes which are exported from the
//   DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
//   EXE's to use the BORLNDMM.DLL as their memory manager.  In these cases,
//   the file BORLNDMM.DLL should be deployed along with your DLL.
//
//   To avoid using BORLNDMM.DLL, pass string information using "char *" or
//   ShortString parameters.
//
//   If your DLL uses the dynamic version of the RTL, you do not need to
//   explicitly add MEMMGR.LIB as this will be done implicitly for you
//---------------------------------------------------------------------------

typedef void __stdcall ( *typFn)(WPARAM,LPARAM);static typFn gGUIProcessingKeyboard = NULL;

static HHOOK gGUIProcessingKeyboardHook = NULL;static typFn gGUIProcessingMouse = NULL;;

static HHOOK gGUIProcessingMouseHook = NULL;#pragma argsused

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)

{

return 1;

}

//---------------------------------------------------------------------------extern "C"
{ __declspec(dllexport) void SetGUIProcessingKeyboard(typFn aHandle);

__declspec(dllexport) void ReleaseGUIProcessingKeyboard(typFn aHandle);

__declspec(dllexport) LRESULT CALLBACK wireKeyboardProc(int code, WPARAM wParam,LPARAM lParam);

__declspec(dllexport) void SetKeyboardHookHandle(HHOOK aHook );__declspec(dllexport) void SetGUIProcessingMouse(typFn aHandle);

__declspec(dllexport) void ReleaseGUIProcessingMouse(typFn aHandle);

__declspec(dllexport) void SetMouseHookHandle(HHOOK aHook );

__declspec(dllexport) LRESULT CALLBACK wireMouseProc(int code, WPARAM wParam,LPARAM lParam);/**
* Set the keyboard loop back handle
*/

void SetGUIProcessingKeyboard(typFn aHandle)
{
if (aHandle != gGUIProcessingKeyboard)
{
gGUIProcessingKeyboard = aHandle;
}
}/**
* Release the keyboard loop back handle
*/
void ReleaseGUIProcessingKeyboard(typFn aHandle)
{
gGUIProcessingKeyboard = NULL;
}

/**
* Set the handle used for tapping the Keyboard
*/
void SetKeyboardHookHandle(HHOOK aHook )
{
gGUIProcessingKeyboardHook = aHook;
}/**
* Tapping the keyboard from the other applications
*/
LRESULT CALLBACK wireKeyboardProc(int code, WPARAM wParam,LPARAM lParam)
{
TList* lList = new TList();
delete lList;
if (code < 0) {
return CallNextHookEx(gGUIProcessingKeyboardHook, code, wParam, lParam);
}
if (NULL != gGUIProcessingKeyboard)
{
gGUIProcessingKeyboard( wParam,lParam);
}
return CallNextHookEx(gGUIProcessingKeyboardHook, code, wParam, lParam);
}/**
* Set the mouse loop back handle
*/

void SetGUIProcessingMouse(typFn aHandle)
{
if (aHandle != gGUIProcessingMouse)
{
gGUIProcessingMouse = aHandle;
}
}/**
* Release the mouse loop back handle
*/

void ReleaseGUIProcessingMouse(typFn aHandle)
{
gGUIProcessingMouse = NULL;
}/**
* Set the handle used for tapping the mouse
*/

void SetMouseHookHandle(HHOOK aHook )
{
gGUIProcessingMouseHook = aHook;
}/**
* Tapping the mouse from the other applications
*/

LRESULT CALLBACK wireMouseProc(int code, WPARAM wParam,LPARAM lParam)
{
TList* lList = new TList();
delete lList;
//  if (gGUIProcessingMouseHook != NULL)
//  {
if (code < 0) {
return CallNextHookEx(gGUIProcessingMouseHook, code, wParam, lParam);
}
if (NULL != gGUIProcessingMouse)
{
gGUIProcessingMouse( wParam,lParam);
}
return CallNextHookEx(gGUIProcessingMouseHook, code, wParam, lParam);
//  }
//  return 0;

}

} // extern C

А вот и приложение.

[код cpp]
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MonitoringToolMain.h"//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
typedef void __stdcall ( __closure *typFn)(WPARAM,LPARAM);

TForm1 *Form1;
HHOOK TForm1::mHook = NULL;
typedef void __stdcall (*typSetHook)(HHOOK);
typedef LRESULT CALLBACK (  *typHookFunc)(int,WPARAM,LPARAM);
static HHOOK gMyGUIProcessingKeyboardHook = NULL;
static HHOOK gMyGUIProcessingMouseHook = NULL;//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}

void __stdcall TForm1::MyKeyboardProc(
WPARAM wParam,
LPARAM lParam
)
{
if (Form1 != NULL)
{
Form1->Memo1->Lines->Add(L"GotA keyboard");
}
}
void __stdcall TForm1::MyMouseProc(
WPARAM wParam,
LPARAM lParam
)
{
if (Form1 != NULL)
{
Form1->Memo1->Lines->Add(L"Pip pip");
}
}

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
if (NULL == mHinst)
{
mHinst = LoadLibrary("KeyboardMouseHookDLL.dll");
}

if (mHinst)
{
typedef void (*Install)(typFn);

// the keyboard

typSetHook SetHook = (typSetHook) GetProcAddress( mHinst, "_SetKeyboardHookHandle" );
typHookFunc wireKeyboardProc = (typHookFunc)GetProcAddress(mHinst, "wireKeyboardProc" );

Install install = (Install) GetProcAddress(mHinst, "_SetGUIProcessingKeyboard");

if (install)
{
install(&MyKeyboardProc);
}

if ((NULL != wireKeyboardProc) &&
(NULL != SetHook) )
{
gMyGUIProcessingKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)wireKeyboardProc,mHinst,NULL);
SetHook(gMyGUIProcessingKeyboardHook);
}

// The mouse
typSetHook  SetMouseHook = (typSetHook) GetProcAddress(mHinst, "_SetMouseHookHandle");
typHookFunc wireMouseProc = (typHookFunc)GetProcAddress(mHinst, "wireMouseProc");

Install installMouse = (Install) GetProcAddress(mHinst, "_SetGUIProcessingMouse");

if (installMouse)
{
installMouse(&MyMouseProc);
}

if ((NULL != wireMouseProc) &&
(NULL != SetMouseHook) )
{
gMyGUIProcessingMouseHook = SetWindowsHookEx(WH_MOUSE,(HOOKPROC)wireMouseProc,mHinst,NULL);
SetMouseHook(gMyGUIProcessingMouseHook);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
if (NULL == mHinst)
{
mHinst = LoadLibrary("KeyboardMouseHookDLL.dll");
}

if (mHinst)
{

if (NULL != gMyGUIProcessingKeyboardHook )
{
UnhookWindowsHookEx(gMyGUIProcessingKeyboardHook);
gMyGUIProcessingKeyboardHook = NULL;
}
typedef void (*Uninstall)(typFn);

Uninstall uninstall = (Uninstall) GetProcAddress(mHinst, "_ReleaseGUIProcessingKeyboard");

if (uninstall)
{
uninstall(&MyKeyboardProc);
}

if (NULL != gMyGUIProcessingMouseHook )
{
UnhookWindowsHookEx(gMyGUIProcessingMouseHook);
gMyGUIProcessingMouseHook = NULL;
}

Uninstall uninstallMouse = (Uninstall) GetProcAddress(mHinst, "_ReleaseGUIProcessingMouse");

if (uninstallMouse)
{
uninstallMouse(&MyMouseProc);
}

FreeLibrary(mHinst);
mHinst = NULL;
}
}
//---------------------------------------------------------------------------

И заголовок формы

[код]
//---------------------------------------------------------------------------

#ifndef MonitoringToolMainH
#define MonitoringToolMainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
TMemo *Memo1;
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
private:    // User declarations
int __stdcall lKeyBoard();
void __stdcall MyKeyboardProc( WPARAM wParam, LPARAM lParam );
void __stdcall MyMouseProc( WPARAM wParam, LPARAM lParam );
HINSTANCE mHinst;
static  HHOOK mHook;

public:     // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

0

Решение

Если вы устанавливаете глобальный системный хук, DLL-файл хука будет вставляться в каждый работающий процесс. Поскольку каждый процесс имеет свое собственное пространство памяти, вам нужно определить раздел общих данных для размещения переменных, таких как дескрипторы хуков, иначе они будут разными для каждого процесса.

#pragma data_seg(".SHARDAT")
static HHOOK gGUIProcessingKeyboardHook = NULL;
static HHOOK gGUIProcessingMouseHook = NULL;
#pragma data_seg()

Также не регистрируйте указатели функций на подключаемую DLL, так как вы будете просить другие процессы вызывать зарегистрированные функции в вашем приложении. Лучше зарегистрировать HWND вашего приложения и сообщение окна.

Создайте экспортированную функцию в вашей DLL, которая устанавливает хук и хранит HWND и пользовательский номер сообщения, например:

#pragma data_seg(".SHARDAT")
static HHOOK g_keybHook = NULL;
static HHOOK g_mouseHook = NULL;
HWND g_registeredWnd = NULL;
UINT g_registeredKeybMsg = 0;
UINT g_registeredMouseMsg = 0;
#pragma data_seg()
HINSTANCE g_hInstance = NULL;

BOOL InstallHook(HWND registeredWnd, UINT registeredKeybMsg, UINT registeredMouseMsg)
{
if (g_hHook != NULL) return FALSE;  // Hook already installed
g_keybHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)KeybProc, g_hInstance, 0);
if (g_keybHook == NULL) return FALSE;   // Failed to install hook
g_registeredWnd = registeredWnd;
g_registeredKeybMsg = registeredKeybMsg;
g_registeredMouseMsg = registeredMouseMsg;
return TRUE;
}

в DllEntryPoint вы сэкономили hinst в g_hInstance в случае reason == DLL_PROCESS_ATTACH:

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
if ((reason == DLL_PROCESS_ATTACH) && (g_hInstance == NULL))
g_hInstance = hinst;

return 1;
}

В вашем приложении вы регистрируете 2 сообщения окна с Функция RegisterWindowMessage и передать эти значения InstallHook функция из хука DLL. Тогда ваше приложение должно обрабатывать эти сообщения в своем цикле сообщений.

registeredKeybMsg = RegisterWindowMessage("MyOwnKeybHookMsg");
registeredMouseMsg = RegisterWindowMessage("MyOwnMouseHookMsg");
InstallHook(hwnd, registeredKeybMsg, registeredMouseMsg);
0

Другие решения

Других решений пока нет …