2

即使鼠标不在屏幕上移动,是否可以获得鼠标移动方向?例如,它与边缘碰撞。

编辑:用户将鼠标移动到顶部并与屏幕的顶部边缘碰撞。然后他继续向上移动鼠标。所以鼠标在现实世界中移动但不在屏幕上移动,因为它不能。我想得到一个信号或其他任何东西来告诉我鼠标在 atm 的哪个方向上移动。

4

1 回答 1

0

正如我所看到的,基本上您要问的是如何检测鼠标位于屏幕边缘并试图向边缘方向移动的情况。自然,MouseMove事件不会检测到这一点,因为坐标没有改变。

即使光标没有改变位置,使用全局低级鼠标钩子可能是获取鼠标移动消息的唯一方法。

这允许检查自上一条消息以来坐标是否已更改。如果没有,我们可能处于屏幕边缘。

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);
        } 
    }
}

*钩子代码取自这个博客

这种方法的问题在于,如果鼠标的移动速度低于每条鼠标消息 1 个像素,则会产生误报。

对此可能的部分解决方案是预先检测屏幕边缘的 X 和 Y 值并对其进行测试,但即使这样也不会消除 100% 的误报,因为鼠标可能会(对于例如)在屏幕的边缘并非常缓慢地向移动(小于 1 个像素),这仍然会被检测为正值。

也许有人对如何消除这些误报有更好的想法。

于 2012-09-06T11:29:20.567 回答