Инициализация мыши
Функция InitMouse() (см. листинг 6.5) готовит мышь к работе.
Листинг 6.5. Функция InitMouse()
BOOL SmearWin::InitMouse() { HRESULT r; r = dinput->CreateDevice( GUID_SysMouse, &mouse, 0 ); if (r!=DI_OK) { TRACE("CreateDevice(mouse) failed\n"); return FALSE; } r = mouse->SetDataFormat( &c_dfDIMouse ); if (r!=DI_OK) { TRACE("mouse->SetDataFormat() failed\n"); return FALSE; } r = mouse->SetCooperativeLevel( GetSafeHwnd(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND ); if (r!=DI_OK) { TRACE("mouse->SetCooperativeLevel() failed\n"); return FALSE; } DIPROPDWORD property; property.diph.dwSize=sizeof(DIPROPDWORD); property.diph.dwHeaderSize=sizeof(DIPROPHEADER); property.diph.dwObj=0; property.diph.dwHow=DIPH_DEVICE; property.dwData=64; r = mouse->SetProperty( DIPROP_BUFFERSIZE, &property.diph ); if (r!=DI_OK) { TRACE("mouse->SetProperty() failed (buffersize)\n"); return FALSE; } return TRUE; } |
Функция InitMouse() включает в себя четыре этапа:
- Создание объекта DirectInputDevice, представляющего мышь.
- Определение формата данных, получаемых от мыши.
- Установку уровня кооперации для мыши.
- Инициализацию буфера данных устройства.
r = dinput->CreateDevice( GUID_SysMouse, &mouse, 0 );
|
DirectInput предоставляет константу GUID_SysMouse, поэтому для получения нужного GUID можно обойтись без составления списка системных устройств. Если приложение должно поддерживать аппаратные конфигурации, в которых используется более одной мыши, придется вызывать функцию EnumDevices().
Если вызов функции CreateDevice() прошел успешно, переменной mouse присваивается указатель на созданный объект DirectInputDevice. Третий аргумент должен быть равен нулю, если только вы не пользуетесь агрегированием COM.
На втором этапе функция SetDataFormat() интерфейса DirectInputDevice сообщает DirectInput формат ожидаемых данных:
r = mouse->SetDataFormat( &c_dfDIMouse ); |
В DirectInput предусмотрен формат c_dfDIMouse для стандартных данных мыши, поэтому эта задача оказывается простой. DirectInput также содержит форматы данных для клавиатур и джойстиков, так что в большинстве приложений вам не придется определять нестандартные форматы.
На третьем этапе определяется уровень кооперации для мыши:
r = mouse->SetCooperativeLevel( GetSafeHwnd(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND ); |
Как и в программе Qwerty, при вызове этой функции используются флаги совместного (DISCL_NONEXCLUSIVE) и активного (DISCL_FOREGROUND) режимов доступа. Первый означает, что во время работы нашей программы другое приложение может получить монопольный доступ к мыши, а второй — что, находясь в фоновом режиме, наше приложение не получает ввод от мыши.
Остается лишь задать размер буфера данных функцией SetProperty() интерфейса DirectInputDevice. Размер буфера определяет количество событий, сохраняемых в очереди DirectInput. Если буфер слишком мал, возникает риск потери данных из-за его переполнения. Я снова привожу соответствующий фрагмент листинга 6.5:
DIPROPDWORD property; property.diph.dwSize=sizeof(DIPROPDWORD); property.diph.dwHeaderSize=sizeof(DIPROPHEADER); property.diph.dwObj=0; property.diph.dwHow=DIPH_DEVICE; property.dwData=64; r = mouse->SetProperty( DIPROP_BUFFERSIZE, &property.diph ); |
Функция SetProperty() получает два аргумента: величину, которая определяет задаваемое свойство, и адрес структуры DIPROPDWORD. Среди прочего эта структура содержит значение свойства.
В нашем случае константа DIPROP_BUFFERSIZE говорит о том, что SetProperty() задает размер буфера. Поле dwSize структуры property равно 64; это значит, что мы заказываем буфер данных из 64 элементов. Размер буфера выбирается достаточно произвольно. Он должен быть достаточно большим, чтобы избежать переполнения, и достаточно малым, чтобы не тратить память напрасно.
Подготовка мыши закончена; осталось лишь захватить ее перед получением данных. Перед тем как захватывать мышь, мы кратко рассмотрим процесс инициализации клавиатуры.