Стэн Трухильо - Графика для Windows средствами DirectDraw
- Название:Графика для Windows средствами DirectDraw
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стэн Трухильо - Графика для Windows средствами DirectDraw краткое содержание
Графика для Windows средствами DirectDraw - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
}
Функция ClearSurface()получает три аргумента: указатель на заполняемую поверхность; величину, присваиваемую каждому пикселю; и необязательную структуру RECT, которая определяет заполняемую область поверхности.
После проверки указателя мы подготавливаем экземпляр структуры DDBLTFX. Полю dwFillColorприсваивается величина, используемая для заполнения, а сама операция осуществляется функцией Blt()интерфейса DirectDrawSurface. Флаг DDBLT_COLORFILLсообщает Blt()о том, что вместо блиттинга выполняется цветовое заполнение.
Получившаяся функция удобна, но ей не хватает универсальности. Дело в том, что величина, применяемая для заполнения поверхности, может иметь различный смысл. Например, для палитровых поверхностей она представляет собой индекс в палитре. Без предварительной проверки палитры невозможно предсказать, какой цвет будет использоваться для заполнения. Аналогичные проблемы возникают и для беспалитровых поверхностей, поскольку конкретное значение пикселя зависит от глубины и формата пикселей. Форматы пикселей особенно часто различаются в режимах High Color, поэтому заполнение поверхности конкретным цветом превращается в нетривиальную задачу.
Вторая версия ClearSurface()получает в качестве аргументов RGB-составляющие и рассчитывает по ним конкретную величину, присваиваемую пикселям поверхности. В таком варианте функция становится более универсальной, но и работает медленнее; быстродействие особенно сильно снижается для палитровых поверхностей, потому что нужный цвет приходится искать в палитре. Код этой функции будет рассмотрен в главе 5.
Нам остается рассмотреть лишь функцию GetSurfaceDimensions(), которая получает указатель на поверхность и возвращает ее ширину и высоту. Код этой функции выглядит так:
BOOL DirectDrawWin::GetSurfaceDimensions(LPDIRECTDRAWSURFACE surf, DWORD& w, DWORD& h) {
if (surf==0) return FALSE;
DDSURFACEDESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.dwSize=sizeof(desc);
desc.dwFlags=DDSD_WIDTH | DDSD_HEIGHT;
if (surf->GetSurfaceDesc(&desc)!=DD_OK) return FALSE;
w=desc.dwWidth;
h=desc.dwHeight;
return TRUE;
}
После проверки указателя мы подготавливаем экземпляр структуры DDSURFACEDESC. Нас интересуют ширина и высота поверхности, поэтому в поле dwFlagsзаносятся флаги DDSD_WIDTHи DDSD_HEIGHT.
Затем мы вызываем функцию GetSurfaceDesc()интерфейса DirectDrawSurfaceи передаем ей указатель на структуру с описанием поверхности. Функция GetSurfaceDesc()сохраняет размеры поверхности в полях dwWidthи dwHeight. Они присваиваются переданным по ссылке переменным wи hтипа DWORD, после чего функция завершается.
Все рассмотренные функции встречаются в демонстрационных программах этой книги, однако вы вовсе не обязаны пользоваться ими. Впрочем, независимо от этого вам будет полезно познакомиться с их реализацией.
Графический вывод
Приложение Bounce прошло стадию инициализации, и теперь все готово к графическому выводу. Однако сначала мы посмотрим, как в классах DirectDrawWinи DirectDrawAppорганизуется обновление кадров.
Класс CWinApp, базовый для DirectDrawApp, содержит виртуальную функцию OnIdle(), которая вызывается при отсутствии необработанных сообщений. Поскольку эта функция автоматически вызывается во время пассивной работы приложения, она хорошо подходит для обновления изображения на экране. Функция DirectDrawApp::OnIdle()выглядит так:
BOOL DirectDrawApp::OnIdle(LONG) {
if (ddwin->PreDrawScene()) ddwin->DrawScene();
return TRUE;
}
Функция OnIdle()вызывает функцию DirectDrawWin::PreDrawScene()и в зависимости от полученного результата вызывает функцию DrawScene(). Функция OnIdle()всегда возвращает TRUE, потому что при возврате FALSE MFCперестает ее вызывать. Функция PreDrawScene()реализована так:
BOOL DirectDrawWin::PreDrawScene() {
if (window_active && primsurf->IsLost()) {
HRESULT r;
r=primsurf->Restore();
if (r!=DD_OK) TRACE("can't restore primsurf\n");
r=backsurf->Restore();
if (r!=DD_OK) TRACE("can't restore backsurf\n");
RestoreSurfaces();
}
return window_active;
}
Функция PreDrawScene()выполняет сразу две задачи. Во-первых, она следит за тем, чтобы для неактивного приложения не выполнялись попытки обновить изображение на экране. Во-вторых, она восстанавливает поверхности приложения в случае их потери.
Потеря поверхностей происходит из-за того, что DirectDraw выделяет занятую видеопамять для других целей. Потерянную поверхность можно легко восстановить, но лишь после того, как приложение станет активным, поэтому перед тем, как восстанавливать поверхности, функция PreDrawScene()ждет установки флага window_active(состояние флага window_activeзависит от сообщений WM_ACTIVATEAPP, обрабатываемых функцией DirectDrawWin::OnActivateApp). После восстановления первичной поверхности и вторичного буфера вызывается функция RestoreSurfaces(). Она является чисто виртуальной функцией, которая должна быть реализована в производных классах. Сейчас мы рассмотрим ее возможную реализацию.
Так как функция OnIdle()вызывает DrawScene()лишь после проверки результата PreDrawScene(), DrawScene()будет вызвана лишь в том случае, если приложение активно, а первичная и вторичная поверхности не были потеряны.
Классы, производные от DirectDrawWin, реализуют функцию DrawScene(), в которой происходит обновление экрана. Версия DrawScene()из класса BounceWinвыглядит так:
void BounceWin::DrawScene() {
CRect limitrect=GetDisplayRect();
x+=xinc;
y+=yinc;
if (x<-160 || x>limitrect.right-160) {
xinc=-xinc;
x+=xinc;
}
if (y<-100 || y>limitrect.bottom-120) {
yinc=-yinc;
y+=yinc;
}
ClearSurface(backsurf, 0);
BltSurface(backsurf, surf1, x, y);
primsurf->Flip(0, DDFLIP_WAIT);
}
Сначала функция GetDisplayRect()получает объект CRect, хранящий ширину и высоту текущего видеорежима. Эти размеры будут использоваться для ограничения перемещений растрового изображения в соответствии с видеорежимом. Далее вычисляются значения переменных xи yкласса BounceWin, определяющих местонахождение растра на экране.
Затем мы вызываем функцию ClearSurface()и передаем ей два аргумента: указатель backsurfи 0. Это приводит к тому, что вторичный буфер заполняется черным цветом. Хотя я упоминал о том, что использование ClearSurface()иногда осложняется различными форматами пикселей, заполнение поверхностей черным работает надежно. Для палитровых поверхностей 0 означает черный цвет, потому что по умолчанию он стоит в палитре на первом месте; для беспалитровых поверхностей 0 всегда соответствует черному цвету.
Читать дальшеИнтервал:
Закладка: