Определение состояния клавиш
Теперь по указателю на интерфейс клавиатуры можно определить состояние отдельных клавиш. В нашей программе это происходит в функции DrawScene(), перед обновлением экрана. Функция DrawScene() приведена в листинге 6.3.
Листинг 6.3. Функция QwertyWin::DrawScene()
void QwertyWin::DrawScene() { static char key[256]; keyboard->GetDeviceState( sizeof(key), &key ); //---------- Клавиши QWERTY -------- if ( key[DIK_Q] & 0x80 ) BltSurface( backsurf, q_dn, 213, 70 ); else BltSurface( backsurf, q_up, 213, 70 ); if ( key[DIK_W] & 0x80 ) BltSurface( backsurf, w_dn, 251, 70 ); else BltSurface( backsurf, w_up, 251, 70 ); if ( key[DIK_E] & 0x80 ) BltSurface( backsurf, e_dn, 298, 70 ); else BltSurface( backsurf, e_up, 298, 70 ); if ( key[DIK_R] & 0x80 ) BltSurface( backsurf, r_dn, 328, 70 ); else BltSurface( backsurf, r_up, 328, 70 ); if ( key[DIK_T] & 0x80 ) BltSurface( backsurf, t_dn, 361, 70 ); else BltSurface( backsurf, t_up, 361, 70 ); if ( key[DIK_Y] & 0x80 ) BltSurface( backsurf, y_dn, 393, 70 ); else BltSurface( backsurf, y_up, 393, 70 ); //---------------- LEFT CONTROL --------------- if ( key[DIK_LCONTROL] & 0x80 ) BltSurface( backsurf, lctrl_dn, 50, 180 ); else BltSurface( backsurf, lctrl_up, 49, 180 ); //---------------- RIGHT CONTROL --------------- if ( key[DIK_RCONTROL] & 0x80 ) BltSurface( backsurf, rctrl_dn, 490, 180 ); else BltSurface( backsurf, rctrl_up, 490, 180 ); //---------------- LEFT ALT --------------- if ( key[DIK_LMENU] & 0x80 ) BltSurface( backsurf, lalt_dn, 100, 260 ); else BltSurface( backsurf, lalt_up, 100, 260 ); //---------------- RIGHT ALT --------------- if ( key[DIK_RMENU] & 0x80 ) BltSurface( backsurf, ralt_dn, 440, 260 ); else BltSurface( backsurf, ralt_up, 440, 260 ); //---------------- SPACE ----------------- if ( key[DIK_SPACE] & 0x80 ) BltSurface( backsurf, space_dn, 170, 340 ); else BltSurface( backsurf, space_up, 170, 340 ); //---------- ESCAPE ------------- if ( key[DIK_ESCAPE] & 0x80 ) { BltSurface( backsurf, esc_dn, 0, 0 ); esc_pressed=TRUE; } else { BltSurface( backsurf, esc_up, 0, 0 ); if (esc_pressed) PostMessage( WM_CLOSE ); } primsurf->Flip( 0, DDFLIP_WAIT ); } |
Состояние устройства определяется функцией GetDeviceState() интерфейса DirectInputDevice. Тип и размер второго аргумента GetDeviceState() зависят от типа устройства, а также от формата данных, заданного функцией SetDataFormat(). Для клавиатуры функция должна получать массив из 256 байт, где каждый байт соответствует одной клавише. В DirectInput предусмотрен набор клавиатурных констант, которые используются как индексы массива и позволяют ссылаться на нужные клавиши. DirectInput обозначает нажатие клавиши установкой старшего бита того байта, который представляет данную клавишу. Объявление массива и вызов функции GetDeviceState() находятся в верхней части листинга 6.3, я снова привожу их:
static char key[256]; keyboard->GetDeviceState( sizeof(key), &key ); |
Адрес массива клавиш передается во втором аргументе GetDeviceState(). Первый аргумент определяет размер данных в байтах.
Все готово к проверке элементов массива. Сначала мы проверяем, была ли нажата клавиша Q:
if ( key[DIK_Q] & 0x80 ) BltSurface( backsurf, q_dn, 213, 70 ); else BltSurface( backsurf, q_up, 213, 70 ); |
Константа DIK_Q определяет индекс клавиши Q в массиве. Мы проверяем значение старшего бита; если бит установлен, значит, клавиша Q нажата, и мы копируем поверхность, изображающую клавишу Q в нажатом состоянии (q_dn), функцией BltSurface(). Если клавиша не нажата, копируется поверхность q_up.
Обратите внимание: каждой клавише соответствует отдельный элемент массива, даже для функционально одинаковых клавиш. Например, две клавиши Alt обрабатываются по отдельности. Кроме того, DirectInput не отличает прописных букв от строчных. Чтобы учесть регистр буквы, придется дополнительно проверить состояние обеих клавиш Shift.
Оставшаяся часть функции состоит из аналогичных проверок состояния других клавиш. После того как все клавиши будут проверены, функция Flip() интерфейса DirectDrawSurface выводит новое изображение на экран.