|
Direct Input. Мышь.
Содержание статьи:
Введение.
Direct Input – инициализация.
Direct Input - Мышь.
Вступление.
к началу статьи
Сегодня я с чистой душей сел за написание очередной статьи – сессия позади, всё что можно было сдать, сдано. Всё что можно было защитить, защищено. Одним словом лепота. Это нельзя передать словами, когда самый страшный из возможных экзаменов (госэкзамен) остается позади (и вбитые в голову никчемные знания то же). Переполняемый именно такими радостными чувствами я сегодня поведаю Вам о Dirct Input’е. Точнее той его части которая отвечает за обработку мыши. Вы спросите: «Зачем нам это? Ведь win api предлагает хорошие возможности по работе с мышью и клавиатурой?». Оказывается недостаточно хорошие. Ведь если как следует нагрузить рендеррер (до заметных тормозов), то появится эффект последействия – кнопку вы отпустили, а камера/перс/курсор продолжает двигаться. Можно конечно упрятать рендерринг в отдельный поток, но тогда придется сделать у него достаточно низкий приоритет, что бы очередь сообщений, через которую проходят все сообщения от устройств управления, обрабатывалась с должной скоростью. Естественно это приведет к критическому падению производительности.
К счастью DirectX предлагает нам удобный API для работы с устройствами ввода. Встречайте – Direct Input.
Direct Input – инициализация.
к началу статьи
Вспомните наши первые шаги в Direct3D – сначала мы создавали объект, затем девайс… Здесь все будет то же самое:
|
#include <windows.h>
#include <dinput.h>
#pragma comment ( lib , "dinput8.lib" )
#pragma comment ( lib , "dxguid.lib" )
class cDIObject{
public:
LPDIRECTINPUT8 Object;
cDIObject( void ){Object = NULL;}
~cDIObject(){}
LPDIRECTINPUT8 operator->(){return( Object );}
bool InitDirectInput( HINSTANCE );
void Release( void );
};
cDIObject DIObject;
bool cDIObject::InitDirectInput( HINSTANCE hInstance ){
//в этом классе мы создаем только объект
if( DirectInput8Create( hInstance , DIRECTINPUT_VERSION ,
IID_IDirectInput8 , ( void ** )&Object , NULL ) != DI_OK ){
MessageBox( 0 , "Не удалось инициализировать DirectInput." ,
"Ошибка" , 0 );
return( false );
}
return( true );
}
void cDIObject::Release( void ){
if( Object ){
Object->Release();
}
}
|
Здесь ничего сложного нет, поэтому сразу перейдем к классу мыши:
Direct Input - Мышь.
к началу статьи
|
#define DI_X 0
#define DI_Y 1
#define DI_Z 2
DIMOUSESTATE2 STD_DIMOUSEINPUT2;
class cMouse{
LPDIRECTINPUTDEVICE8 DIMouse;
public:
bool InitMouse( cDIObject & , HWND );
~cMouse(){}
void Release( void );
void GetMouseState( void );
bool GetButtonState( int );
int GetOffset( int );
};
|
cMouse Mouse;
Значение констант и глобальных объектов я поясню позже, а пока рассмотрим функцию инициализации:
|
bool cMouse::InitMouse( cDIObject &DIObject , HWND hWnd ){
//создание девайса
if( DIObject->CreateDevice( GUID_SysMouse , &DIMouse , NULL ) != DI_OK ){
MessageBox( 0 , "Ошибка создания девайса для мыши." , "Ошибка" , 0 );
return( false );
}
//установка формата вывода
//дело в том, что уже давно появились мышки
//с более чем 3 кнопками, для их поддержки
//создана структура DIDATAFORMAT
//и её глобальный объект c_dfDIMouse2
//если же хотите поддерживать только
//трехкнопочные мышки, то используйте
//объект c_dfDIMouse
if( DIMouse->SetDataFormat( &c_dfDIMouse2 ) != DI_OK ){
MessageBox( 0 , "Ошибка установки формата мыши." , "Ошибка" , 0 );
return( false );
}
//установка режима работы мыши
if( DIMouse->SetCooperativeLevel( hWnd , DISCL_BACKGROUND
| DISCL_NONEXCLUSIVE ) != DI_OK){
MessageBox( 0 , "Ошибка установки Cooperative Level'а для мыши." ,
"Ошибка" , 0 );
return( false );
}
//получаем доступ к мыше
if( DIMouse->Acquire() != DI_OK ){
MessageBox( 0 , "Ошибка получения доступа к мыши." , "Ошибка." , 0 );
return( false );
}
return( true );
}
|
Все самое сложное оказалось позади, теперь научимся считывать состояние мыши
|
//записываем состояние мыши в глобальный объект STD_DIMOUSEINPUT2
void cMouse::GetMouseState( void ){
if( !DIMouse ){
MessageBox( 0 , "Мышь не инициализирована." , "Ошибка" , 0 );
exit( 0 );
}
ZeroMemory( &STD_DIMOUSEINPUT2 , sizeof(STD_DIMOUSEINPUT2 ) );
if( DIMouse->GetDeviceState( sizeof( DIMOUSESTATE2 ), &STD_DIMOUSEINPUT2 ) != DI_OK ){
MessageBox( 0 , "Ошибка чтения состояния мыши." , "Ошибка" , 0 );
exit( 0 );
}
}
|
…читать состояния кнопок…
|
//состояние кнопок читается из глобального объекта DIMOUSESTATE2
bool cMouse::GetButtonState( int mb ){
if( !DIMouse ){
MessageBox( 0 , "Мышь не инициализирована." , "Ошибка" , 0 );
exit( 0 );
}
return( STD_DIMOUSEINPUT2.rgbButtons[ mb ] & 0x80 );
}
|
...и узнавать на сколько сдвинулся курсор мыши
|
//кстати после вызова GetDeviceState
//курсор возвращается в исходное положение
int cMouse::GetOffset( int _MODE ){
if( !DIMouse ){
MessageBox( 0 , "Мышь не инициализирована." , "Ошибка" , 0 );
exit( 0 );
}
switch( _MODE ){
case( DI_X ):return( STD_DIMOUSEINPUT2.lX );break;
case( DI_Y ):return( STD_DIMOUSEINPUT2.lY );break;
case( DI_Z ):return( STD_DIMOUSEINPUT2.lZ );break;
}
MessageBox( 0 , "cMouse::GetOffset(...) : кривое значение _MODE." , "Ошибка" , 0 );
return( 0 );
}
//освобождение ресурсов
void cMouse::Release( void ){
if( DIMouse )
DIMouse->Release();
}
|
Собственно вот и все! Для закрепления материала рассмотрим следующий пример:
|
//инициализация
if( !DIObject.InitDirectInput( hInstance ) ){
exit( 0 );
}
if( !Mouse.InitMouse( DIObject , hWnd ) ){
exit( 0 );
}
//использование
Mouse.GetMouseState();
Mouse.GetOffset( DI_Y );//смещение по оси y
Mouse.GetOffset( DI_Z );//на сколько провернулось колесико мыши
|
Теперь точно все. Урок был простой, но полезный и важный, поэтому необходимо его быстренько впитать, а результаты быстренько применить на практике.
к началу статьи
ЗЫ: способ связи прежний dodonov_a_a@inbox.ru
Смежные вопросы:
Урок 1.
Инициализация.
Вершинные буфферы и камера.
Урок
2. Проигрывание медиа-файлов.
Урок
3. Автоматизация загрузки и управления аудио и видео ресурсами.
Урок
4. Текстурирование. Текстурный менеджер.
Урок
5. Шрифты в Direct3D.
Урок
6. Элементы управления.
Урок
7. Вершинные шейдеры версии 1.0.
Урок
8. Система частиц.
Урок
9. Рендерринг в текстуру.
Исходные коды. |
|
|