An application created with C # has a thread hang - c#

In Visual Studio C #, I'm creating an application that records mouse movements through hooking to track mouse movement.
This application works well under normal circumstances, but when the task manager or a particular game is running, the thread stops and the application does not work.
However, when I click the application window again, it tracks mouse movement again.
How do I get this application to work when I'm running Task Manager or a particular game?
class Hook
{
static private DateTime Set_time;
public static class GlobalMouseHook
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc Ipfn, IntPtr hlnstance, int threadld);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParm);
}
public static class MouseHook
{
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}
public const int WH_MOUSE_LL = 14;
public static int hookHandle = 0;
private static GlobalMouseHook.HookProc callbackDelegate;
public static void StartHook(DateTime Set_time)
{
Hook.Set_time = Set_time;
callbackDelegate = new GlobalMouseHook.HookProc(CallBack);
if (hookHandle != 0)
{
return;
}
hookHandle = GlobalMouseHook.SetWindowsHookEx(WH_MOUSE_LL, callbackDelegate, IntPtr.Zero, 0);
}
public static void StopHook()
{
GlobalMouseHook.UnhookWindowsHookEx(hookHandle);
}
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
public static int CallBack(int nCode, IntPtr wParam, IntPtr lParam)
{
MouseHookStruct mouseInput = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
System.Diagnostics.Debug.WriteLine(mouseInput.pt.x + " : " + mouseInput.pt.y);
System.Diagnostics.Debug.WriteLine((MouseMessages)wParam);
System.Diagnostics.Debug.WriteLine(DateTime.Now-Set_time);
return GlobalMouseHook.CallNextHookEx(hookHandle, nCode, wParam, lParam);
}
}
}
I have attached additional code to use that hooking code.
public Form1 ()
{
Hook.MouseHook.StartHook (DateTime.Now);
InitializeComponent ();
}

Related

SetWindowsHookEx does not work in C# .net core?

I'm using the following code trying to get OS wide keyboard inputs with no luck:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
class InterceptKeys
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
while(true)
continue;
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine(vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
HookCallback is simply not being called. I have a suspicion it's trying to listen only to a form which doesn't exist rather than running system wide.
Low-level Windows hooks internally use Windows messaging. The thread that calls SetWindowsHookEx must have the message loop in the end, which allows to call HookCallback function. In C++ message loop looks like this:
MSG msg;
BOOL result;
for (;;)
{
result = GetMessage(&msg, nullptr, 0, 0);
if (result <= 0)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Find all required PInvoke definitions for GetMessage, TranslateMessage, DispatchMessage and MSG, translate this code to C# and place it instead of your endless loop while(true). You can find all this stuff at PInvoke.Net, see also this Microsoft forum discussion:
Console keyboard hook not getting called
https://social.msdn.microsoft.com/Forums/vstudio/en-US/ed5be22c-cef8-4615-a625-d05caf113afc/console-keyboard-hook-not-getting-called?forum=csharpgeneral
I'm obviously very late but just hoping I could help (if the OP haven't have yet the help he/she needed) so I'm posting my answer.
It says in the MSDN documentation that when you want to set a system-wide hook, you must give the hMod parameter a
handle to the DLL containing the hook procedure pointed to by the lpfn
parameter
and
If the dwThreadId parameter is zero or specifies the identifier of a
thread created by a different process, the lpfn parameter must point
to a hook procedure in a DLL
but, look at this:
SetWindowsHookEx(2, kbdHookProc, GetModuleHandle("user32"), 0)
kbdHookProc is a function in my C# winforms application but the value I gave in the hMod parameter is the hinstance obtained by loading user32.dll via GetModuleHandle. I am using the keyboard hook (WH_KEYBOARD) to monitor locking of capslock, numlock and scroll lock keys. Don't ask me why I did that and would it work or why it works because I don't know but, yes, IT WORKS!
For a full answer to this;
As Alex says, you'll need a message loop to process windows messages and call your hooks,
public class MessageLoop
{
[DllImport("user32.dll")]
private static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin,
uint wMsgFilterMax);
[DllImport("user32.dll")]
private static extern bool TranslateMessage([In] ref MSG lpMsg);
[DllImport("user32.dll")]
private static extern IntPtr DispatchMessage([In] ref MSG lpmsg);
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
IntPtr hwnd;
uint message;
UIntPtr wParam;
IntPtr lParam;
int time;
POINT pt;
int lPrivate;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
X = x;
Y = y;
}
public static implicit operator System.Drawing.Point(POINT p)
{
return new System.Drawing.Point(p.X, p.Y);
}
public static implicit operator POINT(System.Drawing.Point p)
{
return new POINT(p.X, p.Y);
}
public override string ToString()
{
return $"X: {X}, Y: {Y}";
}
}
private Action InitialAction { get; }
private Thread? Thread { get; set; }
public bool IsRunning { get; private set; }
public MessageLoop(Action initialAction)
{
InitialAction = initialAction;
}
public void Start()
{
IsRunning = true;
Thread = new Thread(() =>
{
InitialAction.Invoke();
while (IsRunning)
{
var result = GetMessage(out var message, IntPtr.Zero, 0, 0);
if (result <= 0)
{
Stop();
continue;
}
TranslateMessage(ref message);
DispatchMessage(ref message);
}
});
Thread.Start();
}
public void Stop()
{
IsRunning = false;
}
}
I use a separate thread here to avoid blocking the main thread.
The InterceptKeys class as shown in the question needs no modification;
class InterceptKeys
{
// ...
public static void Main()
{
var loop = new MessageLoop(() => {
_hookID = SetHook(_proc);
});
while (Console.ReadKey(true) != ConsoleKey.X) // For exemplary purposes
{
continue;
}
loop.Stop();
}
// ...
}

Show location of Pointer

I'm trying to implement a screencast application and i need to show the location of mouse on click.
How can I show the location of the pointer(mouse) like there is default on windows with the CTRL key if you enable that option on (Mouse Properties-> Pointer Options -> Show location of pointer when I press the CTRL key)
Is there any good solution rather than just draw a circle on canvas with a storyboard to getting smaller and then disappear ?
You can get the mouse location using Cursor.Position
Then you can draw your circle around the the cursor location.
So if you need it by a key press like with the ctrl scenario you can bind an event listener for key press or if you need something constant you can set an event listener on the mouse move.
Hope it will help
Liron
After some time i did it with that code.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public static class MouseHook
{
public class MSLLHOOKSTRUCTEventArgs : EventArgs
{
private readonly MSLLHOOKSTRUCT _hookStruct;
public MSLLHOOKSTRUCTEventArgs(MSLLHOOKSTRUCT hookStruct)
{
_hookStruct = hookStruct;
}
public MSLLHOOKSTRUCT HookStruct
{
get { return _hookStruct; }
}
}
public static event EventHandler<MSLLHOOKSTRUCTEventArgs> MouseDown = delegate { };
public static event EventHandler<MSLLHOOKSTRUCTEventArgs> MouseUp = delegate { };
public static event EventHandler<MSLLHOOKSTRUCTEventArgs> MouseMove = delegate { };
public static bool Started { get; set; }
static MouseHook()
{
Started = false;
}
public static void Start()
{
Debug.WriteLine("MouseHook.Start");
_hookID = SetHook(_proc);
Started = true;
}
public static void Stop()
{
Debug.WriteLine("MouseHook.Stop");
UnhookWindowsHookEx(_hookID);
Started = false;
MouseDown = null;
MouseUp = null;
MouseMove = null;
}
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(LowLevelMouseProc proc)
{
IntPtr hook = SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle("user32"), 0);
if (hook == IntPtr.Zero)
throw new System.ComponentModel.Win32Exception();
return hook;
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
if(MouseDown!=null)
MouseDown(null, new MSLLHOOKSTRUCTEventArgs(hookStruct));
}
else if (MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
{
if (MouseUp != null)
MouseUp(null, new MSLLHOOKSTRUCTEventArgs(hookStruct));
}
else
{
if (MouseMove != null)
MouseMove(null, new MSLLHOOKSTRUCTEventArgs(hookStruct));
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE = 7;
private const int WH_MOUSE_LL = 14;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}

Getting Mouse Click Coordinates

I am working on a Project in c# and need to get Mouse Click Coordinates in the textbox. Clicking can be made outside the Screen. I have found a code in the internet but can't make the coordinates bring out in the textbox. Here is the code.. I was trying to write "hookStruct.pt.x" in HookCallBack but it didn't work as well. Does anyone have any idea how to do this?
namespace Mouse_Hook
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static LowLevelMouseProc _proc = HookCallback;
private const int WH_MOUSE_LL = 14;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 &&
MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
Console.Read();
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
private void Form1_Load(object sender, EventArgs e)
{
_hookID = SetHook(_proc);
Application.Run();
UnhookWindowsHookEx(_hookID);
}
}
}
If I understand correctly, the best for your needs would be to put the hook functionality inside a static (global) class and expose a static event. In your case, the form will subscribe on that event when opened (and should unsubscribe when closed). Something like this
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Samples
{
public static class MouseHook
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private const int WH_MOUSE_LL = 14;
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
private static IntPtr _hookID = IntPtr.Zero;
public static void Register()
{
if (_hookID != IntPtr.Zero) return;
_hookID = SetHook(HookCallback);
}
public static void Unregister()
{
if (_hookID == IntPtr.Zero) return;
UnhookWindowsHookEx(_hookID);
_hookID = IntPtr.Zero;
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
var handler = LButtonDown;
if (handler != null) handler(null, EventArgs.Empty);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
public static event EventHandler LButtonDown;
}
// Test
class TestForm : Form
{
Label label;
protected override void OnLoad(EventArgs e)
{
Controls.Add(label = new Label());
MouseHook.LButtonDown += OnHookLButtonDown;
base.OnLoad(e);
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
MouseHook.LButtonDown -= OnHookLButtonDown;
}
private void OnHookLButtonDown(object sender, EventArgs e)
{
var pt = Control.MousePosition;
label.Text = "{" + pt.X + ", " + pt.Y + "}";
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MouseHook.Register();
try { Application.Run(new TestForm()); }
finally { MouseHook.Unregister(); }
}
}
}
Please note that this is just an example. A production code would extract the information from the hook parameters and expose a global events similar to the standard MoseMove, MouseDown etc.

Global Key/MouseHook with UI

I want to make a C# Application with a Keyboard and Mouse on screen.
Every Key or Button that is clicked should be seen in this Application by for example coloring one of the keys ( i know how to do that ). This should also work if the Application is not focused. Currently i am using a global Key- and Mousehook which works fine.
The problem is, the Keyhook does only intercept one Key at a time which means i can only show on Key at a time. I want to be able to show multiple keys at a time on screen.
KeyListeners are unfortunately no option because they dont work outside the Application.
Does anyone has an idea how to make this possible?
Here's the KeyHook i am using:
public class KeyHook
{
private delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
static int hHook = 0;
public static List<Keys> KeyCodes = new List<Keys>();
const int WH_KEYBOARD_LL = 13;
HookProc KeyboardHookProcedure;
[StructLayout(LayoutKind.Sequential)]
private class keyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
public KeyHook()
{
Hook();
}
~KeyHook()
{
UnHook();
}
public int Hook()
{
KeyboardHookProcedure = new HookProc(KeyHook.KeyboardHookProc);
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, (IntPtr)LoadLibrary("User32"), 0);
return hHook;
}
public bool UnHook()
{
bool ret = UnhookWindowsHookEx(hHook);
if (ret)
hHook = 0;
return ret;
}
private static int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode < 0)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
else
{
if (((int)wParam == 256) || ((int)wParam == 260))
{
keyboardHookStruct MyKeyboardHookStruct = (keyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(keyboardHookStruct));
//Adding Key to a log i use for other stuff
KeyCodes.Add((Keys)MyKeyboardHookStruct.vkCode);
//Code for coloring Key in the UI for pressed Key
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
}
}

How to track mouse X/Y position and print it to a label? [duplicate]

This question already has answers here:
Capturing mouse/keyboard events outside of form (app running in background)
(2 answers)
Closed 5 years ago.
I know how to modify cursor position from examples on MSDN.
My question is how to check position of mouse while mouse moves and then print X and Y position to representing labels?
EDIT: Lets say I want to track my mouse position from my entire screen.
EDIT 2: My app will be in the back ground/minimized.
I'm already using Mouse Hooks:
namespace Program
{
public partial class MouseHook
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, IntPtr dwExtraInfo);
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
public void DoMouseClick()
{
int X = Cursor.Position.X;
int Y = Cursor.Position.Y;
IntPtr newP = new IntPtr(Convert.ToInt64("0", 16));
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, newP);
}
}
}
Here is the msdn documentation on system level mouse event handling calls (low level mouse proc).
Here is an example of using low level mouse procs to change the scroll event.
In the answer in the second link use WM_MOUSEMOVE from here instead of WM_MOUSEWHEEL.
One thing to note: for this program to continue to capture mouse events when the mouse is over a program with elevated privileges, this program will have to be launch with elevated privileges.
Code (not tested):
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace CatchMouseMove
{
class InterceptMouse
{
const int INPUT_MOUSE = 0;
const int MOUSEEVENTF_WHEEL = 0x0800;
const int WH_MOUSE_LL = 14;
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
if (_hookID == null)
{
MessageBox.Show("SetWindowsHookEx Failed");
return;
}
Application.Run();
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
int xPos = 0;
int yPos = 0;
if (nCode >= 0 && MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam)
{
xPos = GET_X_LPARAM(lParam);
yPos = GET_Y_LPARAM(lParam);
//do stuff with xPos and yPos
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private enum MouseMessages
{
WM_MOUSEMOVE = 0x0200
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public int mouseData;
public int flags;
public int time;
public IntPtr dwExtraInfo;
}
public struct INPUT
{
public int type;
public MOUSEINPUT mi;
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public uint dwFlags;
public int time;
public int dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
You need to set a Windows hook in order to achieve this. The MSDN article How to set a Windows hook in Visual C# .NET shows how to set a mouse hook.
I tried it, it captures the mouse all over the form, even when the mouse cursor is over a control.
You can use the EventArgs of the MouseMove event, because it holds the mouse coordinates. From there you can easily set the text property of the label to the X or Y coordinate you will take from e (the MouseMove EventArgs).
private void Form_MouseMove(object sender, MouseEventArgs e)
{
// Update the mouse coordinates displayed in the textbox.
myTextBox.Text = e.Location.ToString();
}

Categories

Resources