Инициализация DirectInput
Дата создания: 2009-07-05 15:34:49
Последний раз редактировалось: 2012-02-08 10:52:17
Меня всегда удивляло следующее: в большинстве книжек по DirectX рассказывается как создавать графику, а вот чтобы эта графика ожила - не рассказывается. Где взаимодействие с пользователем? Где экшн??? Всегда считал что это есть не правильно. Вроде бы уже наложил на треугольник текстуру, напустил туману, а как теперь заставить объекты двигаться по мановению мышки или клавиатуры не знаешь. И сидишь как дурак.
Единственным правильным решением в данной ситации, будет изучение работы с клавиатурой и мышкой по ходу освоения Direct3D.
В WinAPI есть набор функций для работы с вводом с клавиатуры и мышки, но мы не будем ими пользоваться, так как для этого есть более подходящая штука - DirectInput.
DirectInput - это часть DirectX отвечающая за ввод: с клавиатуры, с мышки, с джойстика и других устройств.
Инициализация DirectInput
Для начала нужно добавить к проекту следующие библиотечные файлы: dinput8.lib, dxguid.lib. Заголовочный файл для DirectInput следующий: dinput.h.
Инициализация DirectInput включает следующие шаги:
- Получение интерфейса IDirectInput8.
- Создание устройства.
- Установка формата данных.
- Установка уровня взаимодействия с операционной системой.
- Получение доступа к устройству ввода.
После инициализации программа сможет принимать ввод от устройства.
Теперь по порядку:
1. Создание объекта DirectInput. Функция DirectInput8Create.
Прежде всего необходимо получить указатель на интерфейс IDirectInput8. Этот интерфейс является основным в DirectInput и c помощью него создаются устройства (клавиатура, мышь). Для создания объекта DirectInput в функцию DirectInput8Create нужно передать указатель на интерфейс IDirectInput8 (4-ый аргумент):
HRESULT DirectInput8Create( HINSTANCE hinst, // экземпляр приложения DWORD dwVersion, // версия DirectInput REFIID riidltf, // какая-то COM'овская фигня LPVOID * ppvOut, // указатель на IDirectInput8 LPUNKNOWN pUnkOuter // тоже относится к COM );
Как мы видим, функция DirectInput8Create сложнее аналогичной функции из Direct3D (Direct3DCreate9).
hinst
Экземпляр приложения.
dwVersion
Версия DirectInput. Всегда передавайте DIRECTINPUT_VERSION
.
riidltf
Уникальный идентификатор устройства. Данный параметр относится к COM. Всегда передавайте IID_IDirectInput8
.
ppvOut
указатель на IDirectInput8. Функция DirectInput8Create вызывается именно для того, чтобы создать объект DirectInput.
pUnkOuter
Ещё одно поле связанное с COM. Заполняется при агрегации. Передавайте NULL.
2. Создание устройства
После создания объекта DirectInput, через него можно создать устройство (например, клавиатуру) - получить указатель на интерфейс IDirectInputDevice8. Получить IDIrectInputDevice8 можно через метод IDirectInput8::CreateDevice:
HRESULT CreateDevice( REFGUID rguid, // глобальный идентификатор (COM) LPDIRECTINPUTDEVICE * lplpDirectInputDevice, // указатель на устройство LPUNKNOWN pUnkOuter // COM );
rguid
Данный параметр относится к COM. Здесь необходимо запомнить два значения: GUID_SysMouse
- мышь, GUID_SysKeyboard
- клавиатура.
lplpDirectInputDevice
Адрес переменной, которая получит указатель на интерфейс IDirectInputDevice8.
pUnkOUter
Такой же параметр как и в функции DirectInput8Create. Передавайте NULL.
Теперь у нас есть переменная, которая представляет устройство. Тип устройства зависит от того, какое значение вы передали первому аргументу метода CreateDevice. В ближайшее время мы будем пользоваться клавиатурой. Соответсвенно первый параметр должен был быть таким: GUID_SysKeyboard.
3. Установка формата данных
Теперь нужно задать формат данных, который будет получать устройство. Для этого есть метод IDirectInputDevice8::SetDataFormat:
HRESULT SetDataFormat(LPCDIDATAFORMAT lpdf);
Единственным аргументом данного метода является адрес структуры, которая описывает формат данных. DirectInput предоставляет уже заполненные структуры LPCDIDATAFORMAT: для клавиатуры - c_dfDIKeyboard, для мышки - c_dfDIMouse.
4. Установка уровня взаимодействия с ОС.
Уровень взаимодействия с операционной системой задаётся через метод IDirectInputDevice8::SetCooperativeLevel:
HRESULT SetCooperativeLevel( HWND hwnd, DWORD dwFlags );
hWnd
Первый аргумент - описатель окна, у которого нужно забирать ввод.
dwFlags
Второй аргумент - набор флагов, определящий каким образом будет происходить взаимодействие с операционной системой. Нам нужно получать данные с устройства только когда окно активно. Этому условию отвечает значение: DISCL_FOREGROUND | DISCL_NONEXCLUSIVE.
5. Получение доступа к устройству ввода.
И последнее что нужно сделать прежде чем устройство будет способно получать ввод от пользователя во время программы - "приобрести" (acquire) устройство IDirectInputDevice8::Acquire. Этот метод позволяет получить доступ к устройству ввода.
С данным методом связан вот ещё какой момент. Когда пользователь переключается на другую программу, то доступ к устройству ввода теряется. Поэтому, когда пользователь возвращается в программу, необходимо снова вызвать данный метод.
При завершении программы, до уничтожения устройства методом Release, нужно вызвать метод IDirectInputDevice8::Unacquire, чтобы отменить доступ к устройству.
А теперь посмотрим как всё это работает (создаём устройство ввода с клавиатуры):
IDirectInput8* di; // объект DirectInput IDirectInputDevice8* didev; // устройство DirectInput DirectInput8Create(hInstance, // экземпляр приложения DIRECTINPUT_VERSION, // версия DirectInput IID_IDirectInput8, // глобальный идентификатор (COM) (void**)&di, // адрес указателя объекта DirectInput NULL); di->CreateDevice(GUID_SysKeyboard, // устройство ввода с клавиатуры &didev, // адрес указателя на устройство NULL); didev->SetDataFormat(&c_dfDIKeyboard); didev->SetCooperativeLevel(hWnd,DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); didev->Acquire();
Теперь можно начинать ввод. Как? Скоро узнаем...