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



Функция CreateFlippingSurfaces() пытается создать «идеальный» вторичный буфер, для чего используются флаг DDSCAPS_VIDEOMEMORY и функция CreateSurface(). Если вызов заканчивается успешно, флаг videobacksurf получает значение TRUE, а функция завершает работу. В противном случае вторичный буфер не создается, а флагу videobacksurf присваивается значение FALSE.

В том варианте вторичный буфер создается приложением в системной памяти позднее, в обработчике OnSize(). Функция OnSize() вызывается при изменении размеров окна приложения. Создавая вторичный буфер по размерам клиентской области окна, мы экономим память. Функция OnSize() выглядит так:

>void DirectDrawWin::OnSize(UINT nType, int cx, int cy) {

> CWnd::OnSize(nType, cx, cy);

> CFrameWnd::GetClientRect(&clientrect);

> CFrameWnd::ClientToScreen(&clientrect);

> if (videobacksurf) return;

> DDSURFACEDESC desc;

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

> desc.dwSize = sizeof(desc);

> desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;

> desc.dwWidth = clientrect.Width();

> desc.dwHeight = clientrect.Height();

> desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;

> if (backsurf) backsurf->Release(), backsurf=0;

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

> if (r!=DD_OK)  {

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

>  return;

> } else TRACE("backsurf w=%d h=%d\n", clientrect.Width(), clientrect.Height());

>}

Инициализация приложения завершается вызовом функций StorePixelFormatData() и CreateCustomSurfaces(), происходящим в обработчике OnCreate(). Обе функции ведут себя точно так же, как и в полноэкранном приложении.

Графический вывод

Как и в полноэкранном варианте, для обновления экрана класс DirectDrawWin вызывает функцию DrawScene(). Ее реализация для оконных приложений отличается от полноэкранного варианта по двум причинам. Во-первых, поскольку в оконном приложении не выполняется переключение страниц, содержимое вторичного буфера приходится копировать на первичную поверхность. Во-вторых, местонахождение выводимых данных на первичной поверхности должно определяться текущим положением и размерами окна. Помните — первичная поверхность в данном случае изображает весь экран, а не только клиентскую область окна. Оконный вариант DrawScene() выглядит так:

>void BounceWin::DrawScene() {

> ClearSurface(backsurf, 0);

> CRect client=GetClientRect();

> int width=client.Width();

> int height=client.Height();

> x+=xinc;

> y+=yinc;

> if (x<-160 || x>width-160) {