c#如何让鼠标移动方向?

时间:2012-09-06 10:20:09

标签: c# mouseevent

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

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

1 个答案:

答案 0 :(得分: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);
        } 
    }
}

* Hook代码取自this博客

此方法存在的问题是,如果鼠标移动速度低于每个鼠标消息1个像素,则会生成误报。

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

也许有人更清楚如何消除这些误报。