使用SetWindowsHookEx的C++只能在BCB2009中添加奇怪的vcl代码
C++ using SetWindowsHookEx only works with strange vcl code added to it. in BCB2009
我在使用SetWindowsHookEx 时遇到了一个奇怪的情况
我有一个bcb 2009项目,上面有一张表格和一份备忘录。
在创建过程中,我们加载Dll并将函数处理程序附加到两侧。
其想法是,当按下键盘时,备忘录框中会显示一条消息,当鼠标事件发生时,备忘录盒中会显示其他文本。
奇怪的是,当我从调试信息中清除代码时,它停止了工作。这意味着钩子被触发了一次,然后就结束了。在调试中,我使用了一些VCL TStringList将密钥stokes数据记录到磁盘。玩那个代码,我终于通过添加检测到了
[代码]
TList* lList = new TList();
delete lList;
对于每一个钩子函数(键盘、鼠标),代码都在重新工作。
我的代码出了什么问题,我必须这样做?
这是我15年来第一次制作dll。因此,在创建dll或导出函数时,它可能是非常基本的东西。
欢迎提出任何建议。
关于
JVDN-
一些新的附加信息:
[已解决]我的目标是嵌入式win XP。我的应用程序创建了一个错误,导致windows关闭资源管理器。钩子在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
如果要安装全局系统挂钩,则会在每个运行进程中注入挂钩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
中,如果reason == DLL_PROCESS_ATTACH
:,则将hinst
保存在g_hInstance
中
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
if ((reason == DLL_PROCESS_ATTACH) && (g_hInstance == NULL))
g_hInstance = hinst;
return 1;
}
在应用程序中,您可以使用RegisterWindowMessage函数注册2条窗口消息,并将这些值从挂钩DLL传递给InstallHook
函数。然后,您的应用程序需要在其消息循环中处理这些消息。
registeredKeybMsg = RegisterWindowMessage("MyOwnKeybHookMsg");
registeredMouseMsg = RegisterWindowMessage("MyOwnMouseHookMsg");
InstallHook(hwnd, registeredKeybMsg, registeredMouseMsg);
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 如何在C++中从两个单独的for循环中添加两个数组
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 如何仅为一个函数添加延迟
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 如何将更多文件夹添加到c++include路径
- 如何将元素添加到数组的线程安全函数?
- QT通过C++添加映射QML项目
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 只能向C++添加一定数量的字符
- Qt和C++:将QLineEdit添加到QTabWidget中
- 将QIcon添加到QTableView单元格
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- 将图像添加到资源文件夹UWP C++
- 使用SetWindowsHookEx的C++只能在BCB2009中添加奇怪的vcl代码