pardazeshDev
pardazeshDev

Reputation: 9

How To Detect Mouse wheel Scrolling by Any Function in User32.dll in C#

I am trying to detect user activity by "keyboard and mouse" on any program in Windows.

I detect Keyboard activity and mouse click by GetAsyncKeyState() in user32.Dll".

I detect Mouse Movement by System.Windows.Forms.Cursor.Position;

I am searching to find a way for detecting mouse wheel scrolling on any program in windows and any position on screen.

I know it possible by user32.Dll function like GetMessage(). I am never use widows form control event like MouseWheel Event, Because it work only on current program, not at all.

thanks.

Upvotes: 0

Views: 1262

Answers (2)

Artem Bubnov
Artem Bubnov

Reputation: 25

I edited answer of ang elus a bit, it works for me now, maybe it would for you.

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Forms;
using MouseEventArgs = System.Windows.Forms.MouseEventArgs;
using ScrollEventArgs = System.Windows.Forms.ScrollEventArgs;
using ScrollEventType = System.Windows.Forms.ScrollEventType;

namespace WpfApp1
{
    public static class Win32Api
    {
        [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 delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        [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 class MouseHook
    {
        private Win32Api.POINT point;
        private Win32Api.POINT POINT
        {
            //get { return point; }
            set
            {
                if (point != value)
                {
                    point = value;
                    if (MouseMoveEvent != null)
                    {
                        var e = new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0);
                        MouseMoveEvent(this, e);
                        //MouseClickEvent(this, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0));
                        //MouseDownEvent(this, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0));
                        //MouseUpEvent(this, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0));

                    }
                }
            }
        }
        private int hHook;
        private const int WM_MOUSEMOVE = 0x200;
        private const int WM_LBUTTONDOWN = 0x201;
        private const int WM_RBUTTONDOWN = 0x204;
        private const int WM_MBUTTONDOWN = 0x207;
        private const int WM_LBUTTONUP = 0x202;
        private const int WM_RBUTTONUP = 0x205;
        private const int WM_MBUTTONUP = 0x208;
        private const int WM_LBUTTONDBLCLK = 0x203;
        private const int WM_RBUTTONDBLCLK = 0x206;
        private const int WM_MBUTTONDBLCLK = 0x209;
        private const int WM_MOUSEWHEEL = 0x20A;
        public const int WH_MOUSE_LL = 14;
        public Win32Api.HookProc hProc;
        public MouseHook()
        {
            this.POINT = new Win32Api.POINT();
        }
        public int SetHook()
        {
            hProc = new Win32Api.HookProc(MouseHookProc);
            hHook = Win32Api.SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero, 0);
            return hHook;
        }
        public void UnHook()
        {
            Win32Api.UnhookWindowsHookEx(hHook);
        }
        private IntPtr wParam;
        private IntPtr lParam;
        private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)//, LPARAM Addtl_Info_L
        {
            this.wParam = wParam;
            this.lParam = lParam;
            Win32Api.MouseHookStruct MyMouseHookStruct = (Win32Api.MouseHookStruct)Marshal.PtrToStructure(this.lParam, typeof(Win32Api.MouseHookStruct));
            if (nCode < 0)
            {
                return Win32Api.CallNextHookEx(hHook, nCode, this.wParam, this.lParam);
            }
            else
            {
                if (MouseClickEvent != null)
                {
                    MouseButtons button = MouseButtons.None;
                    int clickCount = 0;
                    switch ((Int32)this.wParam)
                    {
                        case WM_LBUTTONDOWN:
                            button = MouseButtons.Left;
                            clickCount = 1;
                            if (MouseDownEvent != null) MouseDownEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                            break;
                        case WM_RBUTTONDOWN:
                            button = MouseButtons.Right;
                            clickCount = 1;
                            if (MouseDownEvent != null) MouseDownEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                            break;
                        case WM_MBUTTONDOWN:
                            button = MouseButtons.Middle;
                            clickCount = 1;
                            if (MouseDownEvent != null) MouseDownEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                            break;
                        case WM_LBUTTONUP:
                            button = MouseButtons.Left;
                            clickCount = 1;
                            if (MouseUpEvent != null) MouseUpEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                            break;
                        case WM_RBUTTONUP:
                            button = MouseButtons.Right;
                            clickCount = 1;
                            if (MouseUpEvent != null) MouseUpEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                            break;
                        case WM_MBUTTONUP:
                            button = MouseButtons.Middle;
                            clickCount = 1;
                            if (MouseUpEvent != null) MouseUpEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                            break;
                        case WM_MOUSEWHEEL:
                            MSLLHOOKSTRUCT mouseData = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(this.lParam, typeof(MSLLHOOKSTRUCT));
                            Console.WriteLine("out " + mouseData.mouseData + " " + mouseData.dwExtraInfo + " " + mouseData.flags + " " + mouseData.pt);
                            if (MousescrollEvent != null) MousescrollEvent(this, new ScrollEventArgs(ScrollEventType.SmallIncrement, mouseData.pt.Y < 1e-316?1:-1));
                            break;
                        default:
                            break;
                    }

                    var e = new MouseEventArgs(button, clickCount, point.X, point.Y, 0);
                    MouseClickEvent(this, e);
                }
                this.POINT = new Win32Api.POINT { X=MyMouseHookStruct.pt.X, Y=MyMouseHookStruct.pt.Y };
                return Win32Api.CallNextHookEx(hHook, nCode, this.wParam, this.lParam);
            }
        }
        [StructLayout(LayoutKind.Sequential)]
        private struct MSLLHOOKSTRUCT
        {
            public Point pt;        //<-this is what needed (Y part to be precise)
            public int mouseData;   //<-this is time difference
            public int flags;       //<-this and lower, always constant, don't know what is it
            public int time;
            public long dwExtraInfo;
        }

        public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
        public event MouseMoveHandler MouseMoveEvent;

        public delegate void MouseClickHandler(object sender, MouseEventArgs e);
        public event MouseClickHandler MouseClickEvent;

        public delegate void MouseDownHandler(object sender, MouseEventArgs e);
        public event MouseDownHandler MouseDownEvent;

        public delegate void MouseUpHandler(object sender, MouseEventArgs e);
        public event MouseUpHandler MouseUpEvent;

        public delegate void MousescrollHandler(object sender, ScrollEventArgs e);
        public event MousescrollHandler MousescrollEvent;
    }
}

And this is test window

using System.Windows;
using System.Windows.Forms;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        MouseHook mhM = new MouseHook();
        public MainWindow()
        {
            InitializeComponent();

            mhM.SetHook();
            mhM.MouseClickEvent += (object sender, MouseEventArgs e) =>
            { label1.Content = "" + e.Button + " " + e.Clicks + " " + e.X + " " + e.Y; };
            mhM.MousescrollEvent += (object sender, ScrollEventArgs e) => 
            { label2.Content = "" + e.NewValue; };

            Timer timer = new Timer();
            timer.Interval = 1000000;
            timer.Tick += Timer_Tick;
            timer.Start();
        }

        private void Timer_Tick(object sender, System.EventArgs e)
        {
            mhM.UnHook();
        }
    }
}

Upvotes: 1

ang elus
ang elus

Reputation: 11

https://coderedirect.com/questions/511479/mouse-wheel-event-to-work-with-hovered-control https://gist.github.com/HamzaAnis/90d53662a1659be9d2c74f1dc490cb88 https://learn.microsoft.com/en-gb/windows/win32/api/winuser/ns-winuser-msllhookstruct?redirectedfrom=MSDN helpful links

good question

if this helps below is a class that has most of the mouse hooks so you can pick and choose make an to use it you have to assign the standard click

var mhM = new MouseHook();
mhM.SetHook();
mhM.MouseClickEvent += (object sender, MouseEventArgs e) =>
{ }; 

public class MouseHook
{
    private Point point;
    private Point Point
    {
        get { return point; }
        set
        {
            if (point != value)
            {
                point = value;
                if (MouseMoveEvent != null)
                {
                    var e = new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0);
                    MouseMoveEvent(this, e);
                    //MouseClickEvent(this, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0));
                    //MouseDownEvent(this, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0));
                    //MouseUpEvent(this, new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0));
                    
                }
            }
        }
    }
    private int hHook;
    private const int WM_MOUSEMOVE = 0x200;
    private const int WM_LBUTTONDOWN = 0x201;
    private const int WM_RBUTTONDOWN = 0x204;
    private const int WM_MBUTTONDOWN = 0x207;
    private const int WM_LBUTTONUP = 0x202;
    private const int WM_RBUTTONUP = 0x205;
    private const int WM_MBUTTONUP = 0x208;
    private const int WM_LBUTTONDBLCLK = 0x203;
    private const int WM_RBUTTONDBLCLK = 0x206;
    private const int WM_MBUTTONDBLCLK = 0x209;
    private const int WM_MOUSEWHEEL = 0x20A;
    public const int WH_MOUSE_LL = 14;
    public Win32Api.HookProc hProc;
    public MouseHook()
    {
        this.Point = new Point();
    }
    public int SetHook()
    {
        hProc = new Win32Api.HookProc(MouseHookProc);
        hHook = Win32Api.SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero, 0);
        return hHook;
    }
    public void UnHook()
    {
        Win32Api.UnhookWindowsHookEx(hHook);
    }
    private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)//, LPARAM Addtl_Info_L
    {
        Win32Api.MouseHookStruct MyMouseHookStruct = (Win32Api.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.MouseHookStruct));
        if (nCode < 0)
        {
            return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
        }
        else
        {
            //Console.WriteLine("mouse" + MouseClickEvent.ToString());
            if (MouseClickEvent != null)
            {
                MouseButtons button = MouseButtons.None;
                int clickCount = 0;
                switch ((Int32)wParam)
                {
                    case WM_LBUTTONDOWN:
                        button = MouseButtons.Left;
                        clickCount = 1;
                        if (MouseDownEvent != null) MouseDownEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                        break;
                    case WM_RBUTTONDOWN:
                        button = MouseButtons.Right;
                        clickCount = 1;
                        if (MouseDownEvent != null) MouseDownEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                        break;
                    case WM_MBUTTONDOWN:
                        button = MouseButtons.Middle;
                        clickCount = 1;
                        if (MouseDownEvent != null) MouseDownEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                        break;
                    case WM_LBUTTONUP:
                        button = MouseButtons.Left;
                        clickCount = 1;
                        if (MouseUpEvent != null) MouseUpEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                        break;
                    case WM_RBUTTONUP:
                        button = MouseButtons.Right;
                        clickCount = 1;
                        if (MouseUpEvent != null) MouseUpEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                        break;
                    case WM_MBUTTONUP:
                        button = MouseButtons.Middle;
                        clickCount = 1;
                        if (MouseUpEvent != null) MouseUpEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
                        break;
                    case WM_MOUSEWHEEL:
                        int data = GET_WHEEL_DELTA_WPARAM(lParam.ToInt32());
                        MSLLHOOKSTRUCT mouseData = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                        int wheelMovement = GET_WHEEL_DELTA_WPARAM(mouseData.mouseData);
                        Console.WriteLine("out" + wheelMovement.ToString());
                        // int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
                        if (MousescrollEvent != null) MousescrollEvent(this, new ScrollEventArgs(ScrollEventType.SmallDecrement, wheelMovement));
                        break;


                    default:
                        Console.WriteLine(((Int32)lParam).ToString());
                        break;
                }

                

                
    
    var e = new MouseEventArgs(button, clickCount, point.X, point.Y, 0);
                MouseClickEvent(this, e);
            }
            this.Point = new Point(MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y);
            return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
        }
    }
    [StructLayout(LayoutKind.Sequential)]
    private struct MSLLHOOKSTRUCT
    {
        public Point pt;
        public int mouseData;
        public int flags;
        public int time;
        public long dwExtraInfo;
    }
   


    private static int GET_WHEEL_DELTA_WPARAM(int wparam)
    { 
        return (int)(wparam >> 16); 
    }


    public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
    public event MouseMoveHandler MouseMoveEvent;

    public delegate void MouseClickHandler(object sender, MouseEventArgs e);
    public event MouseClickHandler MouseClickEvent;

    public delegate void MouseDownHandler(object sender, MouseEventArgs e);
    public event MouseDownHandler MouseDownEvent;

    public delegate void MouseUpHandler(object sender, MouseEventArgs e);
    public event MouseUpHandler MouseUpEvent;

    public delegate void MousescrollHandler(object sender, ScrollEventArgs e);
    public event MousescrollHandler MousescrollEvent;

    // public delegate void MouseUpHandler(object sender, MouseEventArgs e);
    //public event MouseUpHandler Mow;
}

Upvotes: 1

Related Questions