Открыть сервис

WM_INPUT

WM_INPUT — это системное сообщение операционной системы Microsoft Windows, которое отправляется окну приложения для передачи необработанных (raw) данных от устройств ввода, таких как клавиатура, мышь, джойстик или сенсорная панель. В отличие от стандартных сообщений (например, WM_KEYDOWN или WM_MOUSEMOVE), WM_INPUT предоставляет программе прямой доступ к данным с устройства до их обработки драйвером мыши или клавиатуры, что позволяет реализовать более точное и гибкое управление вводом, особенно в играх, симуляторах и профессиональных приложениях.

История и предпосылки появления

До появления Windows XP (2001 год) разработчики, нуждавшиеся в высокоточной обработке ввода, были ограничены стандартными сообщениями Windows, которые уже проходили через системную очередь сообщений и подвергались обработке драйверами. Это приводило к задержкам, потере точности (например, при работе с мышью — к эффекту «ускорения» или «сглаживания») и невозможности получать данные от нескольких устройств одного типа одновременно.

С ростом популярности трёхмерных игр и профессиональных приложений (CAD, 3D-моделирование) возникла потребность в прямом доступе к данным устройств ввода. В ответ на это корпорация Microsoft ввела в Windows XP механизм Raw Input, частью которого и является сообщение WM_INPUT. Этот механизм был разработан для замены устаревших API DirectInput (из состава DirectX) в задачах, не связанных с геймпадами, и для обеспечения более низкой задержки и точности.

Механизм работы

Регистрация устройств

Для получения сообщения WM_INPUT приложение должно сначала зарегистрировать интересующие его устройства с помощью функции RegisterRawInputDevices. Эта функция принимает массив структур RAWINPUTDEVICE, в которых указываются:

  • usUsagePage и usUsage — идентификаторы типа устройства (например, HID-класс мыши, клавиатуры или джойстика);
  • dwFlags — флаги, определяющие режим работы (например, RIDEV_INPUTSINK — получать данные даже когда окно не в фокусе);
  • hwndTarget — дескриптор окна, которое будет получать сообщения.

Только после успешной регистрации окно начинает получать WM_INPUT при каждом событии от зарегистрированного устройства.

Формат сообщения

Сообщение WM_INPUT передаётся через параметр wParam (содержит флаг RIM_INPUT или RIM_INPUTSINK) и lParam (содержит дескриптор структуры RAWINPUT). Для извлечения данных приложение вызывает функцию GetRawInputData, которая возвращает структуру RAWINPUT, содержащую:

  • header — заголовок с типом устройства (RIM_TYPEMOUSE, RIM_TYPEKEYBOARD, RIM_TYPEHID);
  • dataобъединение (union) с детальными данными:
  • для мыши: смещение по осям X/Y, флаги кнопок, колёсико прокрутки;
  • для клавиатуры: скан-код, виртуальный код, флаги нажатия/отпускания;
  • для HID-устройств: необработанные байты отчёта.

Обработка

После получения данных приложение должно вызвать DefWindowProc или самостоятельно освободить память, связанную с сообщением, с помощью функции GetRawInputData с флагом RID_INPUT. Невыполнение этого требования может привести к утечкам памяти.

Преимущества перед стандартными сообщениями

  1. Точность и отсутствие сглаживания: WM_INPUT передаёт сырые данные от мыши до любых системных фильтров (таких как ускорение указателя). Это критически важно для шутеров от первого лица (FPS) и киберспорта.
  2. Низкая задержка: сообщение минует очередь сообщений Windows и обрабатывается напрямую, что снижает задержку ввода.
  3. Поддержка нескольких устройств: приложение может различать данные от разных мышей или клавиатур, подключённых к одному компьютеру.
  4. Доступ к данным HID-устройств: позволяет работать с нестандартными устройствами (графические планшеты, трекболы, джойстики), которые не имеют стандартных драйверов мыши или клавиатуры.

Недостатки и ограничения

  • Сложность реализации: требуется явная регистрация устройств и ручное извлечение данных, что увеличивает объём кода по сравнению с обработкой стандартных сообщений.
  • Отсутствие автоматической обработки: приложение должно самостоятельно интерпретировать сырые данные, включая расчёт ускорения, фильтрацию дребезга и т.д.
  • Совместимость: не все старые приложения и библиотеки поддерживают Raw Input; для обратной совместимости может потребоваться использование DirectInput (особенно для геймпадов).

Применение

Игры и симуляторы

  • Шутеры от первого лица (Counter-Strike, Overwatch, Valorant) — для исключения ускорения мыши и обеспечения максимальной точности прицеливания.
  • Авиасимуляторы (Microsoft Flight Simulator, X-Plane) — для обработки данных от джойстиков и рулей с высокой частотой опроса.
  • Гоночные симуляторы (Assetto Corsa, iRacing) — для работы с рулевыми колёсами и педалями.

Профессиональные приложения

  • CAD-системы (AutoCAD, SolidWorks) — для точного управления курсором при черчении.
  • Графические редакторы (Adobe Photoshop, Krita) — для работы с графическими планшетами, где требуется передача давления и наклона пера.
  • Медицинское оборудование — для обработки данных от специализированных манипуляторов.

Системные утилиты

  • Программы для записи макросов — для захвата событий от клавиатуры и мыши на низком уровне.
  • Античит-системы — для анализа ввода на предмет автоматизации или ботов.

Пример использования (псевдокод)

```cpp // Регистрация мыши для получения WM_INPUT RAWINPUTDEVICE rid; rid.usUsagePage = 0x01; // HID-класс rid.usUsage = 0x02; // Мышь rid.dwFlags = RIDEV_INPUTSINK; // Получать данные даже в фоне rid.hwndTarget = hWnd;

RegisterRawInputDevices(&rid, 1, sizeof(rid));

// Обработка сообщения case WM_INPUT: { UINT dwSize; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); BYTE buffer = new BYTE[dwSize]; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, buffer, &dwSize, sizeof(RAWINPUTHEADER)); RAWINPUT raw = (RAWINPUT*)buffer; if (raw->header.dwType == RIM_TYPEMOUSE) { int dx = raw->data.mouse.lLastX; int dy = raw->data.mouse.lLastY; // Использовать dx, dy для управления камерой } delete[] buffer; break; } ```

Сравнение с альтернативами

ХарактеристикаWM_INPUT (Raw Input)DirectInputСтандартные сообщения (WM_MOUSEMOVE)
ЗадержкаНизкаяСредняяВысокая (через очередь)
ТочностьМаксимальная (сырые данные)ВысокаяНизкая (сглажена)
Поддержка нескольких устройствДаДаНет
Сложность реализацииВысокаяСредняяНизкая
Совместимость с геймпадамиОграниченнаяПолнаяНет
Поддержка в современных версиях WindowsПолнаяУстаревшая (рекомендуется XInput)Полная

Интересные факты

  • В Windows 8 и более поздних версиях Microsoft рекомендует использовать Raw Input для всех новых приложений, требующих точного ввода, а DirectInput — только для обратной совместимости со старыми геймпадами.
  • Сообщение WM_INPUT может быть отправлено с флагом RIM_INPUTSINK, что позволяет приложению получать данные даже когда оно не активно (например, для программ-кейлоггеров, что требует особых мер безопасности).
  • В некоторых играх (например, Quake III Arena) использование Raw Input стало стандартом де-факто для профессиональных игроков, так как исключает влияние системного ускорения мыши.

Источники

  1. Microsoft Docs: Raw Input (Windows App Development).
  2. MSDN Magazine: "Raw Input in Windows XP" (2002).
  3. "Programming Windows" by Charles Petzold (5th edition, 1998) — глава о вводе.
  4. DirectX SDK Documentation (раздел о DirectInput и Raw Input).
  5. Статья "Raw Input vs DirectInput" на сайте GameDev.net (2005).

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →