SendInput在扩展屏幕上无法正常工作

时间:2016-08-06 19:08:08

标签: c# wpf windows sendinput

使用SendInput进行鼠标刺激可在MainDisplay上完美运行。但是,当我使用SendInput进行扩展屏幕时(例如,在我的情况下放置在主显示屏左侧的第二个屏幕。无论主显示器周围的任何地方扩展显示但主显示器的分辨率不同,问题都可以复制): 如果我在扩展屏幕上使用SendInput,鼠标位置在X和Y位置都有偏移,在x和40到80点之间略有不同,基于X(宽度)和Y(高度)扩展屏幕的宽度与主显示宽度/高度不同

提前感谢任何有关扩展屏幕上差异的支持

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetCursorPos(ref Win32Point pt);

[DllImport("user32.dll")]
internal static extern bool SetCursorPos(int X, int Y);

[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
    public Int32 X;
    public Int32 Y;
};

internal enum SendInputEventType : int
{
    InputMouse,
    InputKeyboard
}

[DllImport("user32.dll", SetLastError = true)]
    private static extern uint SendInput(uint nInputs, ref Input pInputs, int cbSize);

public struct Input
{
    public uint InputType;
    public MouseInput MI;
}

public struct MouseInput
{
    public int Dx;
    public int Dy;
    public uint MouseData;
    public uint DwFlags;
    public uint Time;
    public IntPtr DwExtraInfo;
}

public enum MouseEventInfo
{
    mouseEventfMove = 0x0001,
    mouseEventfLeftdown = 0x0002,
    mouseEventfLeftup = 0x0004,
    mouseEventfRightdown = 0x0008,
    mouseEventfRightup = 0x0010,
    mouseEventfWheel = 0x0800,
    mouseEventfAbsolute = 0x8000,
    wheelDelta = 0x0078
}

static int CalculateAbsoluteCoordinateX(int x, System.Drawing.Rectangle currentBounds)
    {
        return ((currentBounds.X + x) * 65536) / (currentBounds.Width);
    }

    static int CalculateAbsoluteCoordinateY(int y, System.Drawing.Rectangle currentBounds)
    {
        return (((currentBounds.Y + y) * 65536) / currentBounds.Height);
    }

// for me screen at index 0 (screen no 1) is main display. Screen id 2  
//placed to the left of the main display as per resolution screen i.e.at 
//index 1 (Screen.AllScreens[1]) is extended display and Bound.X is a -ve value 
    public static int ScreenId = 2; 

    public static System.Drawing.Rectangle CurrentBounds
    {
        get
        {
            return SysForms.Screen.AllScreens[ScreenId - 1].Bounds;
        }
    }

    public static void ClickLeftMouseButton(int x, int y)
    {
        Input mouseInput = new Input();
        mouseInput.InputType = SendInputEventType.InputMouse;
        mouseInput.MI.Dx = CalculateAbsoluteCoordinateX(x, CurrentBounds);
        mouseInput.MI.Dy = CalculateAbsoluteCoordinateY(y, CurrentBounds);
        mouseInput.MI.MouseData = 0;

        mouseInput.MI.DwFlags = MouseEventInfo.mouseEventfMove | MouseEventInfo.mouseEventfAbsolute;
        SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));

        mouseInput.MI.DwFlags = MouseEventInfo.mouseEventfLeftdown;
        SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));

        mouseInput.MI.DwFlags = MouseEventFlags.mouseEventfLeftup;
        SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
    }

//Below is code of the WPF MainWindow for testing. Two buttons with click     event.
// For main display with screenid as 1 both setcursor position and sendinput 
//work perfectly, as I get the MousePosition, but when I apply this to   
//extended screen (currently with two screen, main display is screen 1 in my        
//case and screen 2 is extended screen, they put the mouse at two different positions.
//I have my doubts the way I am using the extended screen Bounds.X, but 
//haven't will able to fix the issue

    int x = 600;
    int y = 300;

    private void btnSend_Click(object sender, RoutedEventArgs e)
    {
        SetCursorPos(SysForms.Screen.AllScreens[ScreenId - 1].Bounds.X + x, SysForms.Screen.AllScreens[screenId - 1].Bounds.Y + y);            
    }

    private void btnSend1_Click(object sender, RoutedEventArgs e)
    {
        ClickLeftMouseButton(x, y);
    }

1 个答案:

答案 0 :(得分:0)

发现了这个问题。使用SendInput时,绝对值的x,y转换必须与主/主屏幕相关。 因此改变:

static int CalculateAbsoluteCoordinateX(int x, System.Drawing.Rectangle currentBounds)
{
    return ((currentBounds.X + x) * 65536) / (SystemParameters.PrimaryScreenWidth);
}

static int CalculateAbsoluteCoordinateY(int y, System.Drawing.Rectangle currentBounds)
{
    return (((currentBounds.Y + y) * 65536) / SystemParameters.PrimaryScreenHeight);
}