Графика для Windows библиотека программиста средствами DirectDraw
bda5893f

Получение данных от мыши



Хлопоты с инициализацией мыши и клавиатуры закончены, теперь можно получать от них данные. Функция DrawScene() (см. листинг 6.6) через указатели mouse и keyboard обращается к обоим устройствам и получает от них данные.
Листинг 6.6. Функция SmearWin::DrawScene()

void SmearWin::DrawScene() { static char key[256]; keyboard->GetDeviceState( sizeof(key), &key ); if ( key[DIK_ESCAPE] & 0x80 ) PostMessage( WM_CLOSE ); BOOL done=FALSE; while (!done) { DIDEVICEOBJECTDATA data; DWORD elements=1; HRESULT r=mouse->GetDeviceData( sizeof(data), &data, &elements, 0 ); if (r==DI_OK && elements==1) { switch(data.dwOfs) { case DIMOFS_X: x+=data.dwData; break; case DIMOFS_Y: y+=data.dwData; break; } } else if (elements==0) done=TRUE; } BltSurface( primsurf, sphere, x, y, TRUE ); }

Функция DrawScene() сначала проверяет состояние клавиатуры функцией GetDeviceState() интерфейса DirectInputDevice. Если была нажата клавиша Escape, она посылает сообщение WM_CLOSE, что приводит к завершению приложения. О функции GetDeviceState() и проверке состояния клавиш рассказано в программе Qwerty, поэтому сейчас мы займемся кодом, относящимся к мыши. DrawScene() в цикле извлекает элементы буфера мыши. Для получения данных, а также для проверки отсутствия элементов при пустом буфере используется функция GetDeviceData() интерфейса DirectInputDevice.
Каждый элемент буфера представлен структурой DIDEVICEOBJECTDATA. Эта структура используется независимо от типа устройства, поэтому ее поля были сделаны универсальными. DirectInput определяет структуру DIDEVICEOBJECTDATA следующим образом:

typedef struct { DWORD dwOfs; DWORD dwData; DWORD dwTimeStamp; DWORD dwSequence; } DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA;

Для мыши поле dwOfs определяет тип события. В DirectInput определены следующие константы, описывающие ввод от мыши:
  • DIMOFS_X
  • DIMOFS_Y
  • DIMOFS_Z
  • DIMOFS_BUTTON0
  • DIMOFS_BUTTON1
  • DIMOFS_BUTTON2
  • DIMOFS_BUTTON3
Программа Smear реагирует только на перемещение мыши по осям x и y, поэтому после вызова функции GetDeviceData() поле dwOfs сравнивается с константами DIMOFS_X и DIMOFS_Y.
Поле dwData определяет новые значения осевых координат и кнопок. Поскольку мы используем относительные значения, содержимое этого поля равно смещению по данной оси с момента получения последних данных. Следовательно, оно может быть и отрицательным. Поле dwData используется для обновления переменных x и y.
Поля dwTimeStamp и dwSequence содержат информацию о том, когда произошло данное событие. Поле dwTimeStamp определяет время в миллисекундах (о том, как интерпретируется эта величина, можно подробно узнать в описании функции Win32 GetTickCount()). Поле dwSequence определяет порядок наступления событий. События с меньшими номерами наступили раньше, однако несколько событий могут иметь одинаковые порядковые номера. Например, если мышь или рукоять джойстика смещается по диагонали, события для координат x и y будут иметь одинаковые номера.
Вернемся к функции DrawScene(). Цикл ввода извлекает элементы буфера до тех пор, пока буфер не опустеет. Этот цикл выглядит так:

while (!done) { DIDEVICEOBJECTDATA data; DWORD elements=1; HRESULT r=mouse->GetDeviceData( sizeof(data), &data, &elements, 0 ); if (r==DI_OK && elements==1) { switch(data.dwOfs) { case DIMOFS_X: x+=data.dwData; break; case DIMOFS_Y: y+=data.dwData; break; } } else if (elements==0) done=TRUE; }

Третий аргумент GetDeviceData() используется двояко. Значение, передаваемое функции, определяет количество элементов, извлекаемых из буфера. В нашем случае используется всего одна структура DIDEVICEOBJECTDATA, поэтому передается число 1. При возврате из функции это значение показывает количество полученных элементов.
Если вызов функции прошел успешно и значение elements осталось равным 1, значит, элемент буфера был прочитан, а поля dwOfs и dwData определяют тип события. Нулевое значение elements говорит о том, что буфер пуст и цикл завершается.
После извлечения всех элементов буфера остается лишь вывести поверхность в позиции, определяемой переменными x и y. Для этого используется функция BltSurface():

BltSurface( primsurf, sphere, x, y, TRUE );

Обратите внимание: поверхность изображения копируется непосредственно на первичную поверхность, как говорилось при обсуждении структуры программы Smear.


Содержание раздела