Чтение онлайн

ЖАНРЫ

Графика для Windows средствами DirectDraw

Трухильо Стэн

Шрифт:

Оставшаяся часть определения класса состоит из указателей на интерфейсы DirectDrawSurface. Для каждой клавиши, поддерживаемой приложением, создаются две поверхности (для нажатого и отпущенного состояния).

Инициализация 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.

Захват клавиатуры

Итак, мы инициализировали DirectInput и подготовили клавиатуру к работе; теперь необходимо захватить ее. Для этой цели используется функция OnActivate, потому что клавиатуру приходится захватывать при каждой активизации нашего приложения. Функция OnActivate выглядит так:

void QwertyWin::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) {

 DirectDrawWin::OnActivate(nState, pWndOther, bMinimized);

 if (nState!=WA_INACTIVE && keyboard) {

TRACE("keyboard->Acquire\n");

keyboard->Acquire;

 }

}

После вызова версии OnActivate базового класса мы проверяем, происходит ли активизация приложения (функция OnActivate вызывается и в случае деактивизации, когда активным становится другое приложение). Если проверка дает положительный результат, мы вызываем функцию Acquire интерфейса DirectInputDevice.

Перед вызовом Acquire можно проверить, не была ли клавиатура захвачена ранее, но в этом нет необходимости. DirectInput игнорирует лишние вызовы функции Acquire.

Определение состояния клавиш

Теперь по указателю на интерфейс клавиатуры можно определить состояние отдельных клавиш. В нашей программе это происходит в функции DrawScene, перед обновлением экрана. Функция DrawScene приведена в листинге 6.3.

Поделиться с друзьями: