UPDATED 18.02.2007
New Usage of SendInput
Now sendInput
is called twice (with 1 block sendInput
Stuct-Data) instead of once (with 2 struct blocks for double click). Between the two clicks, there is a Thread.Sleep(80)
to simulate a delay.
UInt32 r = User32.SendInput( ( UInt32 ) input.Length,
input, Marshal.SizeOf( input[ 0 ] ) );
System.Threading.Thread.Sleep(80);
r = User32.SendInput((UInt32)input.Length, input, Marshal.SizeOf(input[0]));
Config GUI
- Displays function state
- Enable / disable doubleclick function
- Choose whether to confirm exit of the application
Introduction
Once I had a logitech mouse and everything was fine! Logitech provided you with a handy application called EMEXEC.exe, which would allow you to set up the behavior of the available buttons. The function I most used was the converter for the middle mouse button/wheel which would turn a single click from the specific button into a left mouse button double click. But what if you uninstalled mouseware, or what if you have to work on a machine without LogiMouse. You're not able to install MouseWare until you have a LogiMouse connected. Pretty soon I began to miss this cool feature from Logitech and said to myself that I am going to write a tool which implements exactly this feature. And here we go....
Problem
The trickiest part I was facing was that the application has to get the clicks from all the other applications running at this time. Therefore a global mousehook has to be set and that might be a little bit tricky. But 'good luck' I found a ready made MouseHookManager
already written in C#. It's the MouseHookManager
class from Olvio which was also available here on The Code Project two years ago. (Thanks to Olvio for putting the source online.)
Setting Up the MouseHook
Setting up the MouseHook
is easy with Olvios MouseHookManager
. Just follow these steps:
public class Form1 : System.Windows.Forms.Form,
Olvio.Windows.Forms.Docking.IMouseHookUser {
private Olvio.Windows.Forms.Docking.SafeNativeMethods.MouseHookManager hooker;
...
public Form1() {
InitializeComponent();
hooker = new Olvio.Windows.Forms.Docking.SafeNativeMethods.MouseHookManager
(base.Handle, this);
}
public bool MouseHookProc(int code, int mainParameter,
int additionalParameter, Point point, int extraInfo)
{
if (mainParameter == WM_MBUTTONUP ) {
doubleClick();
}
return false;
}
Using the MouseHook
Now after you've setup the mousehook
, we can use the MouseHookProc
we implemented to handle the mouseevents as needed.
public bool MouseHookProc
(int code, int mainParameter, int additionalParameter, Point point, int extraInfo)
{
if (mainParameter == WM_MBUTTONUP ) {
doubleClick();
}
return false;
}
Generate a Doubleclick Out of the 'singleclick'
Here you see how to reformat the message and send it back as doubleclick. We use SendInput
to send the doubleclick to the control.
public void doubleClick() {
Point defPnt = new Point();
GetCursorPos(ref defPnt);
int nX = defPnt.X;
int nY = defPnt.Y;
Rectangle screen = Screen.PrimaryScreen.Bounds;
int x2 = ( 65535 * nX ) / screen.Width;
int y2 = ( 65535 * nY ) / screen.Height;
Input[] input = new Input[ 2 ];
addMouseUpDown(ref input, x2, y2);
UInt32 r = User32.SendInput( ( UInt32 ) input.Length, input,
Marshal.SizeOf( input[ 0 ] ) );
System.Threading.Thread.Sleep(80);
r = User32.SendInput((UInt32)input.Length, input, Marshal.SizeOf(input[0]));
}
private void addMouseUpDown(ref Input[] input, int x2, int y2) {
for (int i = 0; i < input.Length; i++) {
input[i].type = INPUT.MOUSE;
input[i].mi.dx = x2;
input[i].mi.dy = y2;
input[i].mi.dwFlags = MOUSEEVENTF.MOVE | MOUSEEVENTF.ABSOLUTE;
if ((i % 2) == 0)
input[i].mi.dwFlags |= MOUSEEVENTF.LEFTDOWN;
else
input[i].mi.dwFlags |= MOUSEEVENTF.LEFTUP;
}
}
...
(Win32 API)
[ DllImport( "User32.dll" ) ]
public static extern UInt32 SendInput (
UInt32 nInputs,
Input[] pInputs,
Int32 cbSize
);
[ StructLayout( LayoutKind.Explicit ) ]
internal struct Input {
[ FieldOffset( 0 ) ] public int type;
[ FieldOffset( 4 ) ] public MOUSEINPUT mi;
[ FieldOffset( 4 ) ] public KEYBDINPUT ki;
[ FieldOffset( 4 ) ] public HARDWAREINPUT hi;
}
And that's basically what my application MBtn2DblClick
does. It waits for any middle mouse button and converts it into a left button doubleclick.
Credits
- Olvio for his
MouseHookManager
class
I hope this article is useful to someone and/or helps to understand how mousehooks work. If you are interested in the source of MouseHookManager
, I'd also recommend you to download this source since the original location of MouseHookManager
is gone and I couldn't find it on the Internet anymore so far. So hope you enjoy this and all the best - hope you'll be reading my next articles as well.
Cheers, Kim