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



> if (r!=DD_OK) {

>  TRACE("CreateClipper() failed\n");

>  return FALSE;

> }

> r=clipper->SetHWnd(0, GetSafeHwnd());

> if (r!=DD_OK) {

>  TRACE("SetHWnd() failed\n");

>  return FALSE;

> }

> r=primsurf->SetClipper(clipper);

> if (r!=DD_OK) {

>  TRACE("SetClipper() failed\n");

>  return FALSE;

> }

> ZeroMemory(&desc, sizeof(desc));

> desc.dwSize = sizeof(desc);

> desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;

> desc.dwWidth = displayrect.Width();

> desc.dwHeight = displayrect.Height();

> desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;

> r=ddraw2->CreateSurface(&desc, &backsurf, 0);

> if (r!=DD_OK) {

>  TRACE("failed to create 'backsurf' in video\n");

>  videobacksurf=FALSE;

> } else {

>  TRACE("Created backsurf in video\n");

>  videobacksurf=TRUE;

> }

> return TRUE;

>}

Сначала мы создаем первичную поверхность. В полноэкранном варианте код выглядит по-другому, потому что здесь создается обычная, несоставная первичная поверхность. В структуре DDSURFACEDESC мы описываем первичную поверхность, используя только флаг DDSCAPS_PRIMARYSURFACE. Затем описанная поверхность создается функцией CreateSurface() интерфейса DirectDraw.

Далее функция CreateClipper() интерфейса DirectDraw создает объект отсечения. CreateClipper() получает три аргумента, однако первый и последний из них чаще всего равны нулю. Второй аргумент представляет собой адрес указателя на интерфейс DirectDrawClipper. В нашем случае используется переменная класса DirectDrawWin с именем clipper.

Объект отсечения нужен для ограничения вывода в программе. Поскольку наше приложение работает в окне, которое находится на рабочем столе вместе с другими окнами, при обновлении изображения необходимо учитывать присутствие этих окон. Чтобы объект отсечения автоматически выполнял свою работу, его необходимо присоединить к окну функцией SetHWnd() интерфейса DirectDrawClipper. Функция SetHWnd() получает два аргумента — двойное слово (DWORD), которое зарезервировано для будущего использования и пока должно быть равно нулю, и логический номер окна приложения.

Далее объект отсечения присоединяется к первичной поверхности приложения функцией SetClipper() интерфейса DirectDrawSurface. После такого присоединения можно осуществлять блиттинг на первичную поверхность с помощью функции Blt() интерфейса DirectDrawSurface. Использовать функцию BltFast() нельзя, потому что она не поддерживает отсечения.

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