在一台显示器上捕捉鼠标

时间:2013-08-12 12:26:04

标签: .net mouse multiple-monitors

我有一个Windows系统,其中多个显示器连接为扩展桌面。只有主监视器对用户来说是物理可见的,所以我想将鼠标捕获在该监视器上。

使用ClipMouse API函数似乎有一个简单的解决方案,如trap-mouse-in-wpf中所述:

[DllImport("user32.dll")]
static extern void ClipCursor(ref System.Drawing.Rectangle rect);

private void TrapMouse()
        {
            System.Drawing.Rectangle r = new System.Drawing.Rectangle(x, y, width, height);
            ClipCursor(ref r);
        }

然而,鼠标容易脱离,例如使用alt-tab更改程序或触摸其中一个辅助触摸屏时。

有没有办法在一台显示器上可靠,永久地捕捉鼠标?

1 个答案:

答案 0 :(得分:0)

您可以尝试使用一些简单的Windows窗体代码。它使用SetWindowsHookEx函数来设置全局鼠标钩子。在钩子方法中,它检查鼠标坐标是否在主屏幕的范围内,并在必要时调整坐标。当您运行此代码时,只要您移动鼠标,鼠标光标仍然可以离开主屏幕区域,但只要发生单击事件,它就会跳回。您可能希望将我的代码与ClipCursor技术结合使用,以防止这种情况发生。

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

    private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);

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

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    Rectangle _ScreenBounds;

    HookProc _HookProc;

    public Form1()
    {
        InitializeComponent();

        _ScreenBounds = Screen.PrimaryScreen.Bounds;
        _HookProc = HookMethod;
        IntPtr hook = SetWindowsHookEx(WH_MOUSE_LL, _HookProc, GetModuleHandle("user32"), 0);
        if (hook == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();
    }

    private int HookMethod(int code, IntPtr wParam, IntPtr lParam)
    {
        if (Cursor.Position.X < _ScreenBounds.Left)
        {
            Cursor.Position = new Point(_ScreenBounds.Left, Cursor.Position.Y);
        }
        else if (Cursor.Position.X > _ScreenBounds.Right)
        {
            Cursor.Position = new Point(_ScreenBounds.Right - 1, Cursor.Position.Y);
        }

        if (Cursor.Position.Y < _ScreenBounds.Top)
        {
            Cursor.Position = new Point(Cursor.Position.X, _ScreenBounds.Top);
        }
        else if (Cursor.Position.Y > _ScreenBounds.Bottom)
        {
            Cursor.Position = new Point(Cursor.Position.X, _ScreenBounds.Bottom - 1);
        }

        return 0;
    }
}