2

Is it possible to get the mouse moving direction even though the mouse doesn't move on screen? For example it collides with an edge.

edit: The user moves the mouse to the top and collides with the top edge of the screen. Then he keeps on moving the mouse upwards. So the mouse moves in real world but doesn't move on the screen cause it can't. And I want to get a signal or anything else that tells me in which direction the mouse is moving atm.

lorenz albert
  • 1,385
  • 2
  • 11
  • 27
  • Not sure what you mean. Any chance of a little more detail? – Robbie Dee Sep 06 '12 at 10:23
  • If the mouse is not moving, how can it have a move direction? – Oded Sep 06 '12 at 10:26
  • possible duplicate question [How to get cardinal mouse direction](http://stackoverflow.com/questions/1689397/how-to-get-cardinal-mouse-direction-from-mouse-coordinates) – cat916 Sep 06 '12 at 10:26
  • @user861114: Not a duplicate. This question is specifically asking for getting the direction towards which the mouse *would* move it if hadn't already arrived at the edge of the screen. In the question you linked to, two different positions of the cursor (before and after) are assumed. – O. R. Mapper Sep 06 '12 at 10:27
  • Thanks that at least one user understood it without the edit :D – lorenz albert Sep 06 '12 at 10:28
  • 1
    @Oded: It's like when you drive your car into a wall. Your wheels are running and can't go any further, but you can still determine the current direction you'd move towards if there were no wall in front of you. – O. R. Mapper Sep 06 '12 at 10:29
  • 2
    @O.R.Mapper - Yes, due to the fact that a car has a front and back. How would that work with a mouse? A car has an inherent orientation - the mouse icon on the screen does not. – Oded Sep 06 '12 at 10:33
  • 2
    @Oded: That is also true while the mouse cursor is actually moving. The point is that the mouse device, the physical object, is moving to a certain direction, even though the mouse cursor may not. The OP wants to retrieve the former direction, the one that the physical device is moving to. As for the car example, the orientation of front and back of the car is irrelevant, only the force towards which the wheels exert power is. – O. R. Mapper Sep 06 '12 at 10:35
  • But the hardware has a defined up, right, down, left direction. – lorenz albert Sep 06 '12 at 10:36
  • @O.R.Mapper - Meaning that the direction of the force _can_ be extrapolated. How this can work with a mouse (without having previous coordinates), is beyond me. – Oded Sep 06 '12 at 10:41
  • @Oded: The mouse is moved to a certain direction on the table. The OP is simply asking how to detect that movement. – O. R. Mapper Sep 06 '12 at 13:16

1 Answers1

0

As I see it, basically what you are asking is how you can detect a case where the mouse is on the edge of the screen and trying to move in the direction of the edge. Naturally, a MouseMove event will not detect this because the coordinate has not changed.

Using a global low level mouse hook is possibly the only way of getting a mouse move message even if the cursor has not changed position.

This allows to check if the coordinate has changed since the last message or not. If it has not, we might be at the edge of the screen.

public partial class Form1 : Form
{
    private const int WH_MOUSE_LL = 14;
    private const int WM_MOUSEMOVE = 0x200;

    [DllImport("kernel32.dll")]
    static extern IntPtr GetModuleHandle(string moduleName);

    [DllImport("user32.dll")]
    static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll")]
    public static extern int UnhookWindowsHookEx(IntPtr hhook);

    [DllImport("user32.dll")]
    static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, uint wParam, IntPtr lParam);
    delegate IntPtr HookProc(int nCode, uint wParam, IntPtr lParam);

    [StructLayout(LayoutKind.Sequential)]
    public struct MSLLHOOKSTRUCT
    {
        public POINT pt;
        public int mouseData; // be careful, this must be ints, not uints (was wrong before I changed it...). regards, cmew.
        public int flags;
        public int time;
        public UIntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;
    }

    private HookProc hookProc;
    private IntPtr hook;

    private POINT formerPoint = new POINT() { X = 0, Y = 0 };

    public Form1() { InitializeComponent(); }

    IntPtr LowLevelMouseProc(int nCode, uint wParam, IntPtr lParam)
    {
        if (wParam == WM_MOUSEMOVE)
        {
            MSLLHOOKSTRUCT infoStr = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
            if (infoStr.pt.X == formerPoint.X && infoStr.pt.Y == formerPoint.Y)
            {
                Console.WriteLine("Mouse moved without coordinates changing");
                //use the standard way of finding the direction of travel here.
            }
            formerPoint = infoStr.pt;
        }
        return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
    }

    protected override void OnHandleDestroyed(EventArgs e)
    {
        UnhookWindowsHookEx(hook);
        base.OnHandleDestroyed(e);
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (!DesignMode)
        {
            hookProc = new HookProc(LowLevelMouseProc);
            hook = SetWindowsHookEx(WH_MOUSE_LL, hookProc, GetModuleHandle(null), 0);
        } 
    }
}

*Hook code was taken from this blog

The problem with this method is that if the mouse is moving slower than 1 pixel per mouse message, a false positive is generated.

A possible partial solution to this would be to pre-detect the X and Y values of screen edges and test for those as well, but even this will not eliminate 100% of false positives, as it is possible for the mouse to be (for example) on the right edge of the screen and move very slowly left (less than 1 pixel), and this would still be detected as a positive.

Perhaps someone has a better idea how to eliminate these false positives.

Rotem
  • 21,452
  • 6
  • 62
  • 109
  • Another case you have to consider is the corner. If you are at the top right corner. You ll not know if the user wants to move to the right or top just by checking: MouseMoveEvent triggered but noch change in x or y position. – lorenz albert Sep 06 '12 at 11:43
  • @lorenz True. Unfortunately it seems to me that this information can only be intercepted between the mouse device and the OS. – Rotem Sep 06 '12 at 11:45
  • Somehow i couldn't force your case to be popped. I moved the mouse as slow as possible and the cursor didn't move but also the mouse event wasn't fired. – lorenz albert Sep 06 '12 at 11:57
  • @lorenz Is the hook even being registered or entered? – Rotem Sep 06 '12 at 12:05
  • What do you mean by being registered or entered? – lorenz albert Sep 06 '12 at 12:07
  • @lorenz is the `LowLevelMouseProc` method being entered? – Rotem Sep 06 '12 at 12:09
  • It should be Lowlevel. The dll is using WM_MOUSE_LL. And the event occurs also outside of the form or if it is minimized and so on. – lorenz albert Sep 06 '12 at 12:30