LPDIRECTINPUT dinput;

 LPDIRECTINPUTDEVICE keyboard;

 LPDIRECTDRAWSURFACE coil[coil_frames];

 LPDIRECTDRAWSURFACE dm_surf;

 int dm_index;

 DWORD menubarfillcolor;

 HFONT largefont, smallfont;

};

Класс CursorWin объявляет три обработчика сообщений: OnCreate(), OnDestroy() и OnActivate(). Функция OnCreate() инициализирует DirectDraw, DirectInput и поток ввода. Функция OnDestroy() освобождает интерфейсы DirectX и завершает поток ввода. Функция OnActivate() обеспечивает захват мыши и клавиатуры на период активности приложения.

Следующие пять функций наследуются от класса DirectDrawWin:

• SelectDriver()

• SelectInitialDisplayMode()

• CreateCustomSurfaces()

• DrawScene()

• RestoreSurfaces()

Мы достаточно часто видели эти функции в других приложениях и знаем, что они делают, поэтому не будем рассматривать их. Исключением является функция DrawScene(), которая представляет некоторый интерес, потому что помимо создания нового кадра занимается синхронизацией основного потока с потоком ввода.

Затем объявляются функции InitMouse() и InitKeyboard(). Эти функции используются функцией OnCreate () и отвечают за инициализацию объектов DirectInput, предназначенных для работы с мышью и клавиатурой. Функция InitKeyboard () совпадает с одноименными функциями программ Qwerty и Smear из главы 6, поэтому она также не рассматривается. Однако функция InitMouse() помимо инициализации мыши запускает поток ввода. Вскоре мы рассмотрим эту функцию.

Функция UpdateDelaySurface() готовит к выводу поверхность меню задержки. Она выводит текст меню и выделяет текущую задержку.

Далее в классе CursorWin объявляются три функции потока мыши:

• MouseThread()

• UpdateCursorSimpleCase()

• UpdateCursorComplexCase()

Функция MouseThread() реализует поток ввода. Когда основной поток создает поток ввода, он передает указатель на статическую функцию MouseThread(). Созданный поток использует эту функцию в качестве точки входа и продолжает выполнять ее до возврата из функции или вызова функции AfxEndThread(). Функция MouseThread() обновляет изображение курсора с помощью функций UpdateCursorSimpleCase() и UpdateCursorComplexCase().

В оставшейся части класса CursorWin объявляются две группы переменных. Первая группа относится к работе с мышью. Все эти переменные объявлены статическими, чтобы статическая функция MouseThread() могла к ним обратиться (а также потому, что доступ к статическим переменным осуществляется чуть быстрее).

Обратите внимание: в число переменных мыши входят объекты классов CCriticalSection, CEvent и CWinThread, предназначенные для синхронизации двух потоков нашей программы.

Мы объявляем два указателя на объекты CEvent — один используется для оповещений DirectInput, а второй сигнализирует о завершении потока.

Вторая группа переменных не относится к работе с мышью. В нее входит массив указателей на интерфейсы DirectDrawSurface, через которые мы обращаемся к отдельным кадрам анимации спирали.

Инициализация приложения 

Наше знакомство с программой Cursor начинается с функции OnCreate(), которая отвечает за инициализацию DirectDraw, DirectInput и потока ввода. Функция OnCreate() приведена в листинге 7.2.

Листинг 7.2. Функция CursorWin::OnCreate()

int CursorWin::OnCreate(LPCREATESTRUCT lpCreateStruct) {

 HRESULT r=DirectInputCreate(AfxGetInstanceHandle(), DIRECTINPUT_VERSION, &dinput, 0);

 if (r!=DI_OK) {

  AfxMessageBox('DirectInputCreate() failed');

  return -1;

 }

 if (InitMouse()==FALSE)  return -1;

 if (InitKeyboard()==FALSE)  return -1;

 if (DirectDrawWin::OnCreate(lpCreateStruct) == -1) return -1;

 mousethread->ResumeThread();

 return 0;

}

Сначала OnCreate() инициализирует DirectInput функцией DirectInputCreate(). Затем мышь и клавиатура инициализируются функциями InitMouse() и InitKeyboard(), после чего вызывается функция DirectDrawWin::OnCreate(). Функция InitMouse(), которую мы рассмотрим чуть ниже, создает поток ввода, доступ к которому осуществляется через указатель mousepointer. Однако поток ввода создается в приостановленном состоянии, чтобы он не пытался преждевременно обращаться к первичной поверхности. Поток будет запущен лишь после инициализации DirectDraw. Приостановленный поток активизируется функцией CWinThread::ResumeThread().

Давайте рассмотрим функцию InitMouse(), чтобы получить общее представление об инициализации мыши и создании потока ввода. Функция InitMouse() приведена в листинге 7.3.

Листинг 7.3. Функция InitMouse()

BOOL CursorWin::InitMouse() {

 HRESULT r;

 r = dinput->CreateDevice(GUID_SysMouse, &mouse, 0);

 if (r!=DI_OK) {

  TRACE('CreateDevice(mouse) failed ');

  return FALSE;

 }

 r = mouse->SetDataFormat(&c_dfDIMouse);

 if (r!=DI_OK) {

  TRACE('mouse->SetDataFormat() failed ');

  return FALSE;

 }

 r = mouse->SetCooperativeLevel(GetSafeHwnd(),    DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);

 if (r!=DI_OK) {

  TRACE('mouse->SetCooperativeLevel() failed ');

  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) ');

  return FALSE;

 }

 mouse_event[mouse_event_index]=new CEvent;

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату