C # SendInput () всегда возвращает 0 в консольном приложении - PullRequest
0 голосов
/ 05 июня 2018

Я разработал простое консольное приложение для опроса контроллера Xbox с помощью xinput.Я хотел бы использовать значения, полученные из одной из кнопок для перемещения мыши.Я могу получить значения x и y из большого пальца, но когда я использую эти значения для SendInput () (используя User32.dll), мышь не двигается, и возвращаемое значение равно 0.

Согласно Microsoft , «Если функция возвращает ноль, вход был уже заблокирован другим потоком».

Как мне найти другой поток, который его блокирует?Это просто простое консольное приложение (exe), запущенное Visual Studio, которое выводит значения x и y на экран и пытается переместить мышь.

long x = controller.x;  // values from the controller
long y = controller.y;  // these are checked and do contain numbers

INPUT mouseMoveInput =  new INPUT();
mouseMoveInput.type = 0; // mouse
mouseMoveInput.mi.dx = x;
mouseMoveInput.mi.dy = y;
mouseMoveInput.mi.mouseData = 0;
mouseMoveInput.mi.dwFlags = MOUSEEVENTF_MOVE;

var result = SendInput(1, ref mouseMoveInput, Marshal.SizeOf(new INPUT());
// result always returns 0

Я что-то упустил?Должно ли это работать?

Вот объявления:

    [StructLayout(LayoutKind.Explicit)]
    public struct MOUSEINPUT
    {
        [FieldOffset(0)]
        public long X;

        [FieldOffset(8)]
        public long Y;

        [FieldOffset(16)]
        public uint MouseData;

        [FieldOffset(20)]
        public uint Flags;

        [FieldOffset(24)]
        public uint Time;

        [FieldOffset(28)]
        public IntPtr ExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct KEYBOARDINPUT
    {
        public ushort Vk;
        public ushort Scan;
        public uint Flags;
        public uint Time;
        public IntPtr ExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct HARDWAREINPUT
    {
        public uint Msg;
        public ushort ParamL;
        public ushort ParamH;
    }


    [StructLayout(LayoutKind.Explicit)]
    public struct INPUT
    {
        [FieldOffset(0)]
        public uint type;

        [FieldOffset(4)]
        public MOUSEINPUT mi;

        [FieldOffset(4)]
        public KEYBOARDINPUT ki;

        [FieldOffset(4)]
        public HARDWAREINPUT hi;
    }

ОБНОВЛЕНИЕ: использование mouse-event работает, но эта функция устарела.Есть ли проблема с использованием его в любом случае, поскольку он работает?

Есть что-то странное, что я получаю с размерами структуры:

Размер тега INPUT: 40
Размер mouseMoveInput: 40
Размер MOUSEINPUT: 32
Размер uint: 4

Но если tagINPUT состоит из MOUSEINPUT и uint, то должен ли его размер быть 36?

1 Ответ

0 голосов
/ 05 июня 2018

2-й параметр SendInput должен быть указателем на массив, а не параметром ref, и особенно не ссылкой непосредственно на структуру.

Я бы также использовал явное расположение только для структуры, котораяна самом деле это нужно, и пусть остальные будут последовательными.Это проще.

Этот код работает для меня:

const int INPUT_MOUSE = 0;
const int MOUSEEVENTF_MOVE = 0x0001;

[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint numberOfInputs, [MarshalAs(UnmanagedType.LPArray)] INPUT[] inputs, int sizeOfInputStructure);

void Main()
{
    INPUT mouseMoveInput = new INPUT();
    mouseMoveInput.type = INPUT_MOUSE;
    mouseMoveInput.mi.dx = 10;
    mouseMoveInput.mi.dy = 10;
    mouseMoveInput.mi.mouseData = 0;
    mouseMoveInput.mi.dwFlags = MOUSEEVENTF_MOVE;

    var result = SendInput(1, new INPUT[] { mouseMoveInput}, Marshal.SizeOf(mouseMoveInput));
    if(result == 0) {
        throw new Win32Exception();
    }
}

[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
    public int dx;
    public int dy;
    public uint mouseData;
    public uint dwFlags;
    public uint time;
    public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
    public ushort wVk;
    public ushort wScan;
    public uint dwFlags;
    public uint time;
    public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)]
public struct HARDWAREINPUT
{
    public uint Msg;
    public ushort ParamL;
    public ushort ParamH;
}


[StructLayout(LayoutKind.Explicit)]
public struct INPUT
{
    [FieldOffset(0)]
    public uint type;
    [FieldOffset(4)]
    public MOUSEINPUT mi;
    [FieldOffset(4)]
    public KEYBDINPUT ki;
    [FieldOffset(4)]
    public HARDWAREINPUT hi;
}
...