Так как функция OnIdle() вызывает DrawScene() лишь после проверки результата PreDrawScene(), DrawScene() будет вызвана лишь в том случае, если приложение активно, а первичная и вторичная поверхности не были потеряны.

Функция 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 всегда соответствует черному цвету.

Функция DrawScene() использует функцию DirectDrawWin::BltSurface() для копирования поверхности surf1 на поверхность backsurf. Два последних аргумента BltSurface() определяют точку поверхности- приемника, куда должно быть скопировано содержимое источника. Для выполнения этой операции можно было бы воспользоваться функцией Blt () или BltFast() интерфейса DirectDrawSurface, но мы не делаем этого из-за возможного отсечения. Обратите внимание - код, определяющий положение растра, позволяет источнику выйти за пределы приемника, в результате чего может потребоваться отсечение. Мы не можем воспользоваться функцией Blt(), потому что тогда потребовалось бы присоединить к приемнику объект DirectDrawClipper, чего мы не делаем. Функция BltFast() тоже не подходит, потому что она вообще не поддерживает отсечения. Функция BltSurface() автоматически выполняет отсечение, а функции Blt() и BltFast() вызываются внутри нее.

Но перед тем, как переходить к функции BltSurface(), мы закончим рассмотрение функции DrawScene(). Она завершается вызовом функции Flip(). При этом происходит переключение страниц, и подготовленный нами кадр отображается на экране. Функция Flip() получает два аргумента: указатель на поверхность и переменную типа DWORD, предназначенную для установки флагов. Указатель на поверхность необходим лишь в нестандартных ситуациях, когда в переключении поверхностей участвует несколько вторичных буферов. Второй аргумент обычно содержит флаг DDFLIP_WAIT, показывающий, что возврат из функции должен происходить только после того, как переключение страниц завершится.

Функция BltSurface()

Функция BltSurface() класса DirectDrawWin оказывается более гибкой и удобной по сравнению с функциями DirectDrawSurface::Blt() и BltFast(). Мы уже видели, как BltSurface() используется внутри функции BounceWin::DrawScene(), а сейчас рассмотрим саму функцию.

Функция BltSurface() требует передачи четырех аргументов, а пятый аргумент необязателен. Первые два аргумента представляют собой указатели на поверхности — источник и приемник. Следующие два аргумента — координаты x и y, определяющие положение копируемой области на приемнике. По умолчанию блиттинг выполняется без цветовых ключей, однако их можно активизировать с помощью необязательного пятого параметра. Код функции BltSurface() приведен в листинге 3.3.

Листинг 3.3. Функция BltSurface()

BOOL DirectDrawWin::BltSurface(LPDIRECTDRAWSURFACE destsurf, LPDIRECTDRAWSURFACE srcsurf, int x, int y, BOOL srccolorkey) {

 if (destsurf==0 || srcsurf==0) return FALSE;

 BOOL use_fastblt=TRUE;

 DDSURFACEDESC destsurfdesc;

 ZeroMemory(&destsurfdesc, sizeof(destsurfdesc));

 destsurfdesc.dwSize = sizeof(destsurfdesc);

 destsurf->GetSurfaceDesc(&destsurfdesc);

 CRect destrect;

 destrect.left=0;

 destrect.top=0;

 destrect.right=destsurfdesc.dwWidth;

 destrect.bottom=destsurfdesc.dwHeight;

 DDSURFACEDESC srcsurfdesc;

 ZeroMemory(&srcsurfdesc, sizeof(srcsurfdesc));

 srcsurfdesc.dwSize = sizeof(srcsurfdesc);

 srcsurf->GetSurfaceDesc(&srcsurfdesc);

 CRect srcrect;

 srcrect.left=0;

 srcrect.top=0;

 srcrect.right=srcsurfdesc.dwWidth;

 srcrect.bottom=srcsurfdesc.dwHeight;

 // Проверить, нужно ли что-нибудь делать...

 if (x+srcrect.left>=destrect.right) return FALSE;

 if (y+srcrect.top>=destrect.bottom) return FALSE;

 if (x+srcrect.right<=destrect.left) return FALSE;

 if (y+srcrect.bottom<=destrect.top) return FALSE;

 // При необходимости выполнить отсечение

 // для прямоугольной области источника

 if (x+srcrect.right>destrect.right) srcrect.right-=x+srcrect.right-destrect.right;

 if (y+srcrect.bottom>destrect.bottom) srcrect.bottom-=y+srcrect.bottom-destrect.bottom;

 CRect dr;

 if (x<0) {

  srcrect.left=-x;

  x=0;

  dr.left=x;

  dr.top=y;

  dr.right=x+srcrect.Width();

  dr.bottom=y+srcrect.Height();

  use_fastblt=FALSE;

 }

 if (y<0) {

  srcrect.top=-y;

  y=0;

  dr.left=x;

  dr.top=y;

  dr.right=x+srcrect.Width();

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

0

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

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