Что это за дополнительные параметры при вызове SendInput через win32API

Меня интересует отправка ввода с ключа через Ruby с использованием win32API. Я нашел функцию, которую хотел бы вызвать: SendInput

MSDN описывает подпись следующим образом:

UINT WINAPI SendInput(
  _In_  UINT nInputs,
  _In_  LPINPUT pInputs,
  _In_  int cbSize
);

И ВХОД выглядит как

typedef struct tagINPUT {
  DWORD type;
  union {
    MOUSEINPUT    mi;
    KEYBDINPUT    ki;
    HARDWAREINPUT hi;
  };
} INPUT, *PINPUT;

Итак, мне нужно одно целое число, показывающее тип ввода. Поскольку меня интересуют события клавиатуры, я посмотрел на структуру KEYBDINPUT.

typedef struct tagKEYBDINPUT {
  WORD      wVk;
  WORD      wScan;
  DWORD     dwFlags;
  DWORD     time;
  ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;

И еще 5 аргументов: два 16-битных целых числа и три 32-битных целых числа.

Теперь, из того, что я собрал, SendInput принимает целое число, указатель на структуру INPUT и целое число, представляющее размер структуры INPUT. Создание объекта Win32API выглядит так

SendInput = Win32API.new("User32", "SendInput", "LPL", "L")
INPUT_KEYBOARD = 1

Теперь я создаю свою структуру INPUT:

input = [INPUT_KEYBOARD, 0x5A, 0, 0, 0, 0].pack('ISSIII')

Первый аргумент — это тип ввода, за которым следуют пять аргументов для структуры KEYBDINPUT: виртуальный код клавиши для клавиши, которую я хочу нажать, и некоторые другие флаги, которые мне не нужны для целей тестирования.

Итак, я запускаю его:

SendInput.call(1, input, input.size)

Ничего не произошло.

Когда я проверяю GetLastError, он возвращает код ошибки 87., что означает наличие недопустимых аргументов.

Затем я решил поискать и обнаружил, что кто-то еще строит свою структуру ввода следующим образом:

input = [INPUT_KEYBOARD, 0x5A, 0, 0, 0, 0, 0, 0].pack('ISSIIIII')

Я попытался запустить его, и он выполняется успешно!

Разница? Есть два дополнительных аргумента для ввода. Теперь я в замешательстве: что это за два дополнительных аргумента для входной структуры? Есть ли что-то, что я упустил, когда читал документы?

Я думаю, что это может иметь какое-то отношение к типу ULONG_POINTER, но когда я ищу типы данных, это 32-битное целое число.

Ссылка: http://www.dsprobotics.com/support/viewtopic.php?p=7110&sid=cd256b848d00e64a2e74e093863f837f#p7110


person MxLDevs    schedule 15.01.2015    source источник
comment
Точно такая же ситуация была у меня, но с js-ctypes, большое спасибо, что поделились!!!!   -  person Noitidart    schedule 02.07.2015


Ответы (1)


Вызов функции принимает union из этих структур, я бы поспорил, что это как-то связано с этим.

Похоже, MOUSEINPUT больше, чем KEYBOARDINPUT:

typedef struct tagMOUSEINPUT {
  LONG      dx;
  LONG      dy;
  DWORD     mouseData;
  DWORD     dwFlags;
  DWORD     time;
  ULONG_PTR dwExtraInfo;
} MOUSEINPUT, *PMOUSEINPUT;

Не знаю точно, хотя это кажется довольно ужасающим способом связать эти звонки!

edit: Да, похоже, что при использовании этого размера MOUSEINPUT вы получите 28 байтов данных, отправленных в функцию, что и принесет вам pack('ISSIIIII').

person Nick Veys    schedule 15.01.2015
comment
Я кратко прочитал об объединениях, чтобы получить представление о том, для чего они нужны, но не читал о том, как они на самом деле реализованы. Но, если подумать, это имеет смысл: если вы разрешаете разные типы данных в одном и том же пространстве памяти, вам понадобится как минимум размер самого большого типа... - person MxLDevs; 16.01.2015
comment
@MxyL Ваш комментарий проверен кем-то еще, например, экспертами winapi? Это имеет смысл, но мне просто интересно, проверено ли это, у меня была точно такая же проблема, и я исправил ее, сделав мою структуру kyinput того же размера, что и структура mouseinput. - person Noitidart; 02.07.2015