A
a_deano
Hi,
I am not totally new to programming for Windows but may have bitten off
more than I can chew.
My problem is, I would like to install a hook (using SetWindowsHookEx)
to monitor mouse movements as I am testing some new hardware we are
developing.
So, I decided to tackle the .net managed code realm for what I assumed
would be a pretty simple job (at least in my c builder exp most likely
an hour or less). Anyway two days later I am still going but am
completely stuck. See code below;
Basically, llMouseHook.h is a class that wraps up the calls to the API
function and defines an event to fire when said message is received.
The Form1.h is a visual interface with a button and a text box that I
plan to log the records of the mouse messages (assuming I can see
them). The code compiles but I don't seem to get any mouse messages
routed through, as well the important bits ie: the callback handler
aren't even linked in.....
Anyway the code is posted below, I hope someone out there takes pity on
me and gives me some pointers, as I hate being beaten by these things.
In the meantime it's off to the bookshop for some references and back
to builder to get the job done
Code:
llMouseHook.h
using namespace System;
using namespace System::Runtime::InteropServices;
namespace SystemHook
{
public ref class HookEventArgs : EventArgs
{
public: int HookCode;
IntPtr wParam;
IntPtr lParam;
};
public enum class HookType : int
{
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
};
public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
extern IntPtr SetWindowsHookEx(HookType code,
HookProc ^func,
IntPtr hInstance,
int threadID);
[DllImport("user32.dll")]
extern int UnhookWindowsHookEx(IntPtr hhook);
[DllImport("user32.dll")]
extern int CallNextHookEx(IntPtr hhook,
int code,
IntPtr wParam,
IntPtr lParam);
public delegate void HookEventHandler(Object^ sender, HookEventArgs^
e);
public ref class LocalWindowsHook
{
HookEventHandler^ Hooked;
public:
event HookEventHandler^ HookInvoked {
void add(HookEventHandler^ Ev) {
Hooked += Ev;
}
void remove(HookEventHandler^ Ev) {
Hooked -= Ev;
}
void raise(Object^ sender, HookEventArgs^ e) {
if (Hooked) {
Hooked->Invoke(sender, e);
}
}
}
protected:
IntPtr m_hhook;
HookProc ^ m_filterFunc;
HookType m_hookType;
public:
int CoreHookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code < 0)
return CallNextHookEx(m_hhook, code, wParam, lParam);
HookEventArgs^ e = gcnew HookEventArgs();
e->HookCode = code;
e->wParam = wParam;
e->lParam = lParam;
HookInvoked(this, e);
return CallNextHookEx(m_hhook, code, wParam, lParam);
}
LocalWindowsHook(HookType hook)
{
m_hhook = IntPtr::Zero;
m_hookType = hook;
Hooked = nullptr;
m_filterFunc = gcnew HookProc(this,
&SystemHook::LocalWindowsHook::CoreHookProc);
}
void Install()
{
Threading::Thread^ MainThread = Threading::Thread::CurrentThread;
m_hhook = SetWindowsHookEx(
m_hookType,
m_filterFunc,
IntPtr::Zero,
MainThread->ManagedThreadId);
}
void Uninstall()
{
UnhookWindowsHookEx(m_hhook);
}
};
}
<Form1>
#pragma once
namespace MouseTracker
{
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System:ata;
using namespace System:rawing;
using namespace SystemHook;
/// <summary>
/// Summary for Form1
///
/// WARNING: If you change the name of this class, you will need to
change the
/// 'Resource File Name' property for the managed resource
compiler tool
/// associated with all .resx files this class depends on.
Otherwise,
/// the designers will not be able to interact properly with
localized
/// resources associated with this form.
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
LocalWindowsHook^ MseHook;
HookEventHandler^ Ev;
bool Running;
public:
Form1(void)
{
InitializeComponent();
MseHook = gcnew LocalWindowsHook(HookType::WH_MOUSE_LL);
Ev = gcnew HookEventHandler(this, &Form1::MouseEventReceived);
Running = false;
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">"description of the parameter"</param>
virtual void Dispose(Boolean disposing) override
{
if (disposing && components)
{
delete components;
}
__super:ispose(disposing);
}
private: System::Windows::Forms::RichTextBox^ rtbMouseLog;
protected:
private: System::Windows::Forms::Button^ butStart;
private: System::Windows::Forms::Button^ butClear;
private: System::Windows::Forms::Button^ butSave;
protected:
void MouseEventReceived(Object^ sender, HookEventArgs^ e)
{
System::Console::WriteLine("Mouse Event....");
}
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
//REMOVED.......
#pragma endregion
private: System::Void butStart_Click(System::Object^ sender,
System::EventArgs^ e) {
butClear->Enabled = Running;
butSave->Enabled = Running;
Running = !Running;
if (Running) {
butStart->Text = "Stop";
MseHook->HookInvoked += Ev;
MseHook->Install();
}
else {
butStart->Text = "Start";
MseHook->HookInvoked -= Ev;
MseHook->Uninstall();
}
}
private: System::Void butClear_Click(System::Object^ sender,
System::EventArgs^ e) {
// rtbMouseLog->Lines->Clear;
}
};
}
I am not totally new to programming for Windows but may have bitten off
more than I can chew.
My problem is, I would like to install a hook (using SetWindowsHookEx)
to monitor mouse movements as I am testing some new hardware we are
developing.
So, I decided to tackle the .net managed code realm for what I assumed
would be a pretty simple job (at least in my c builder exp most likely
an hour or less). Anyway two days later I am still going but am
completely stuck. See code below;
Basically, llMouseHook.h is a class that wraps up the calls to the API
function and defines an event to fire when said message is received.
The Form1.h is a visual interface with a button and a text box that I
plan to log the records of the mouse messages (assuming I can see
them). The code compiles but I don't seem to get any mouse messages
routed through, as well the important bits ie: the callback handler
aren't even linked in.....
Anyway the code is posted below, I hope someone out there takes pity on
me and gives me some pointers, as I hate being beaten by these things.
In the meantime it's off to the bookshop for some references and back
to builder to get the job done
Code:
llMouseHook.h
using namespace System;
using namespace System::Runtime::InteropServices;
namespace SystemHook
{
public ref class HookEventArgs : EventArgs
{
public: int HookCode;
IntPtr wParam;
IntPtr lParam;
};
public enum class HookType : int
{
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
};
public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
extern IntPtr SetWindowsHookEx(HookType code,
HookProc ^func,
IntPtr hInstance,
int threadID);
[DllImport("user32.dll")]
extern int UnhookWindowsHookEx(IntPtr hhook);
[DllImport("user32.dll")]
extern int CallNextHookEx(IntPtr hhook,
int code,
IntPtr wParam,
IntPtr lParam);
public delegate void HookEventHandler(Object^ sender, HookEventArgs^
e);
public ref class LocalWindowsHook
{
HookEventHandler^ Hooked;
public:
event HookEventHandler^ HookInvoked {
void add(HookEventHandler^ Ev) {
Hooked += Ev;
}
void remove(HookEventHandler^ Ev) {
Hooked -= Ev;
}
void raise(Object^ sender, HookEventArgs^ e) {
if (Hooked) {
Hooked->Invoke(sender, e);
}
}
}
protected:
IntPtr m_hhook;
HookProc ^ m_filterFunc;
HookType m_hookType;
public:
int CoreHookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code < 0)
return CallNextHookEx(m_hhook, code, wParam, lParam);
HookEventArgs^ e = gcnew HookEventArgs();
e->HookCode = code;
e->wParam = wParam;
e->lParam = lParam;
HookInvoked(this, e);
return CallNextHookEx(m_hhook, code, wParam, lParam);
}
LocalWindowsHook(HookType hook)
{
m_hhook = IntPtr::Zero;
m_hookType = hook;
Hooked = nullptr;
m_filterFunc = gcnew HookProc(this,
&SystemHook::LocalWindowsHook::CoreHookProc);
}
void Install()
{
Threading::Thread^ MainThread = Threading::Thread::CurrentThread;
m_hhook = SetWindowsHookEx(
m_hookType,
m_filterFunc,
IntPtr::Zero,
MainThread->ManagedThreadId);
}
void Uninstall()
{
UnhookWindowsHookEx(m_hhook);
}
};
}
<Form1>
#pragma once
namespace MouseTracker
{
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System:ata;
using namespace System:rawing;
using namespace SystemHook;
/// <summary>
/// Summary for Form1
///
/// WARNING: If you change the name of this class, you will need to
change the
/// 'Resource File Name' property for the managed resource
compiler tool
/// associated with all .resx files this class depends on.
Otherwise,
/// the designers will not be able to interact properly with
localized
/// resources associated with this form.
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
LocalWindowsHook^ MseHook;
HookEventHandler^ Ev;
bool Running;
public:
Form1(void)
{
InitializeComponent();
MseHook = gcnew LocalWindowsHook(HookType::WH_MOUSE_LL);
Ev = gcnew HookEventHandler(this, &Form1::MouseEventReceived);
Running = false;
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">"description of the parameter"</param>
virtual void Dispose(Boolean disposing) override
{
if (disposing && components)
{
delete components;
}
__super:ispose(disposing);
}
private: System::Windows::Forms::RichTextBox^ rtbMouseLog;
protected:
private: System::Windows::Forms::Button^ butStart;
private: System::Windows::Forms::Button^ butClear;
private: System::Windows::Forms::Button^ butSave;
protected:
void MouseEventReceived(Object^ sender, HookEventArgs^ e)
{
System::Console::WriteLine("Mouse Event....");
}
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
//REMOVED.......
#pragma endregion
private: System::Void butStart_Click(System::Object^ sender,
System::EventArgs^ e) {
butClear->Enabled = Running;
butSave->Enabled = Running;
Running = !Running;
if (Running) {
butStart->Text = "Stop";
MseHook->HookInvoked += Ev;
MseHook->Install();
}
else {
butStart->Text = "Start";
MseHook->HookInvoked -= Ev;
MseHook->Uninstall();
}
}
private: System::Void butClear_Click(System::Object^ sender,
System::EventArgs^ e) {
// rtbMouseLog->Lines->Clear;
}
};
}