Стэн Трухильо - Графика для Windows средствами DirectDraw
- Название:Графика для Windows средствами DirectDraw
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стэн Трухильо - Графика для Windows средствами DirectDraw краткое содержание
Графика для Windows средствами DirectDraw - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:

Рис. 7.1. Программа Cursor
Перед тем как погружаться в программный код, я должен признаться, что работа над программой Cursor сопровождалась внутренней борьбой. Мне очень хотелось разбить код на несколько мелких функций, скрыть некоторые технические подробности и упорядочить структуру программы. Однако я справился с искушением — читатель наверняка захочет видеть программу прямо перед собой, вместо того чтобы искать нужный фрагмент по всему коду. В результате программа получилась менее структурированной по сравнению с другими.
Как создать собственный курсор
Программа Cursor может работать с курсором любого размера. В версии программы на CD-ROM использован небольшой курсор (12×20 пикселей), но вы можете легко изменить этот стандартный размер. Для этого достаточно заменить cursor_08.bmpи/или cursor_24.bmpфайлами с более крупными изображениями курсоров.
По умолчанию приложение работает в 8-битном видеорежиме и соответственно с 8-битным курсором. Многое зависит от вашего графического редактора, но, скорее всего, вы избавитесь от проблем с палитрой, если воспользуетесь файлом cursor_08.bmpс CD-ROM как шаблоном для создания нестандартного курсора. С курсором формата True Color дело обстоит проще, но, чтобы воспользоваться им, придется слегка подправить функцию SelectInitialDisplayMode(), чтобы активизировать беспалитровый видеорежим вместо палитрового.
Программа Cursor, как и все остальные программы этой книги, построена на базе структурных классов DirectDrawWinи DirectDrawApp. Эти классы остались неизменными, а вся специфика приложения реализуется классом CursorWin. На практике функциональность курсора мыши, вероятно, следовало бы встроить в структурный класс. И все же для наглядности я объединил код для работы с курсором со специфическим кодом приложения. Класс CursorWin приведен в листинге 7.1.
Листинг 7.1. Класс CursorWin
class CursorWin : public DirectDrawWin {
public:
CursorWin();
protected:
//{{AFX_MSG(CursorWin)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
int SelectDriver();
int SelectInitialDisplayMode();
BOOL CreateCustomSurfaces();
void DrawScene();
void RestoreSurfaces();
private:
BOOL InitMouse();
BOOL InitKeyboard();
BOOL UpdateDelaySurface();
private:
//------- Функции потока ввода ------
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 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");
Интервал:
Закладка: