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

ЖАНРЫ

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

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

Шрифт:

 static DWORD MouseThread(LPVOID);

 BOOL UpdateCursorSimpleCase(int curx, int cury, int oldcurx, int oldcury);

 BOOL UpdateCursorComplexCase(int curx, int cury, int oldcurx, int oldcury);

private:

 //------- Данные мыши -------

 static LPDIRECTINPUTDEVICE mouse;

 static CCriticalSection critsection;

 static CWinThread* mousethread;

 static CEvent* mouse_event[2];

 static int cursor_width;

 static int cursor_height;

 static LPDIRECTDRAWSURFACE cursor;

 static LPDIRECTDRAWSURFACE cursor_under;

 static LPDIRECTDRAWSURFACE cursor_union;

 static int curx, cury;

 static int oldcurx, oldcury;

 static CList<MouseClickData, MouseClickData> mouseclickqueue;

private:

 //------- Данные приложения -------

 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\n");

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