Инициализация DirectInput
Инициализация DirectInput и DirectDraw выполняется в функции OnCreate(). DirectInput инициализируется версией OnCreate() класса QwertyWin, а DirectDraw — версией из DirectDrawWin. Функция QwertyWin::OnCreate() приведена в листинге 6.2.
Листинг 6.2. Функция QwertyWin::OnCreate()
int QwertyWin::OnCreate(LPCREATESTRUCT lpCreateStruct) { HRESULT r=DirectInputCreate( AfxGetInstanceHandle(), DIRECTINPUT_VERSION, &dinput, 0 ); if (r!=DI_OK) { AfxMessageBox("DirectInputCreate() failed"); return -1; } r = dinput->CreateDevice( GUID_SysKeyboard, &keyboard, 0 ); if (r!=DI_OK) { AfxMessageBox("CreateDevice(keyboard) failed"); return -1; } r = keyboard->SetDataFormat( &c_dfDIKeyboard ); if (r!=DI_OK) { AfxMessageBox("keyboard->SetDataFormat() failed"); return -1; } r=keyboard->SetCooperativeLevel( GetSafeHwnd(), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); if (r!=DI_OK) { AfxMessageBox("keyboard->SetCooperativeLevel() failed"); return -1; } if (DirectDrawWin::OnCreate(lpCreateStruct)==-1) return -1; return 0; } |
Прежде всего обратите внимание — версия OnCreate() базового класса вызывается лишь в конце функции. Это сделано для того, чтобы при неудачной инициализации DirectInput программа выводила окно сообщения и прекращала работу без инициализации DirectDraw.
Сначала функция OnCreate() инициализирует указатель dinput с помощью функции DirectInputCreate(), которой необходимо передать четыре аргумента. Вызов этой функции выглядит так:
HRESULT r=DirectInputCreate( AfxGetInstanceHandle(), DIRECTINPUT_VERSION, &dinput, 0 ); |
Первый аргумент - логический номер экземпляра приложения, получаемый функцией AfxGetInstanceHandle(). Второй аргумент — номер версии DirectInput. В нашем случае используется константа DIRECTINPUT_VERSION, она определяется DirectInput в зависимости от версии SDK, использованной для компиляции приложения. Различные версии DirectInput более подробно рассматриваются в этой главе ниже. Третий аргумент DirectInputCreate() — адрес инициализируемого указателя, а четвертый — показатель агрегирования COM, который обычно равен нулю (агрегированием называется разновидность наследования, используемая в COM). Если инициализация DirectInput проходит успешно (то есть если DirectInputCreate() возвращает DI_OK), указатель dinput может использоваться для работы с DirectInput.
Затем мы создаем экземпляр интерфейса DirectInputDevice, который представляет клавиатуру. Я снова приведу соответствующую строку листинга 6.2:
r = dinput->CreateDevice( GUID_SysKeyboard, &keyboard, 0 ); |
Функция CreateDevice() интерфейса DirectInput применяется для инициализации устройств DirectInput. В нашем случае первым аргументом является стандартная константа GUID_SysKeyboard, показывающая, что мы собираемся работать с системной клавиатурой. Второй аргумент — адрес указателя keyboard, через который мы впоследствии будем обращаться к клавиатуре. Третий аргумент — показатель агрегирования COM, в нашем случае он должен быть равен нулю.
Следующий шаг — выбор формата данных устройства. Для клавиатуры он выполняется просто:
r = keyboard->SetDataFormat( &c_dfDIKeyboard ); |
Функции SetDataFormat() интерфейса DirectInputDevice передается единственный аргумент — константа стандартного формата c_dfDIKeyboard. Программа Qwerty работает лишь с одним устройством (клавиатурой), но, как мы убедимся в программе Smear, формат данных должен задаваться отдельно для каждого устройства, используемого программой.
Затем мы задаем уровень кооперации устройства с помощью функции SetCooperativeLevel() интерфейса DirectInputDevice. Соответствующий фрагмент листинга 6.2 выглядит так:
r=keyboard->SetCooperativeLevel( GetSafeHwnd(), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); |
Функция SetCooperativeLevel() получает два аргумента: логический номер окна и набор флагов, определяющих уровень кооперации. Функция GetSafeHwnd() определяет логический номер окна, а флаги DISCL_FOREGROUND и DISCL_NONEXCLUSIVE задают нужный уровень кооперации. Флаг активного режима DISCL_FOREGROUND присутствует потому, что на время активности другого приложения нам не потребуется ввод от клавиатуры, а флаг DISCL_NONEXCLUSIVE — потому, что DirectInput не позволяет установить монопольный доступ к клавиатуре.
До получения данных с клавиатуры остался всего один шаг: мы должны захватить устройство функцией Acquire(). Эта задача решается функцией OnActivate(), которую мы рассмотрим ниже.
Функция QwertyWin::OnCreate() завершается вызовом функции DirectDrawWin::OnCreate(), инициализирующей DirectDraw. Эта функция обсуждалась в главе 3.
Функция OnCreate() инициализирует DirectInput, а затем инициализирует мышь и клавиатуру функциями InitMouse() и InitKeyboard(). Она выглядит так:
int SmearWin::OnCreate(LPCREATESTRUCT lpCreateStruct) { HRESULT r=DirectInputCreate( AfxGetInstanceHandle(), DIRECTINPUT_VERSION, &dinput, 0 ); r if (r!=DI_OK) { AfxMessageBox("DirectInputCreate() failed"); return -1; } if (InitMouse()==FALSE) return -1; if (InitKeyboard()==FALSE) return -1; if (DirectDrawWin::OnCreate(lpCreateStruct) == -1) return -1; return 0; } |
DirectInput инициализируется функцией DirectInputCreate(). При успешном вызове в переменную dinput заносится указатель на созданный объект DirectInput. Остальные аргументы DirectInputCreate() рассматривались в программе Qwerty.
Затем мы вызываем функции, которые инициализируют мышь и клавиатуру. Они рассматриваются ниже. Функция OnCreate() завершается вызовом версии OnCreate() базового класса, инициализирующим DirectDraw.