Чтение онлайн

на главную - закладки

Жанры

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

Трухильо Стэн

Шрифт:

 HRESULT r;

 DDSURFACEDESC desc;

 desc.dwSize = sizeof(desc);

 desc.dwFlags = DDSD_CAPS;

 desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

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

 if (r!=DD_OK) {

TRACE("FAILED to create 'primsurf'\n");

return FALSE;

 }

 r=ddraw2->CreateClipper(0, &clipper, 0);

 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, - создание поверхности вторичного буфера. В идеальном варианте нам удастся найти свободную видеопамять в объеме, достаточном для создания внеэкранной поверхности, которая по ширине и высоте совпадает с первичной поверхностью. Я называю такой вариант идеальным из-за преимущества по скорости, характерного для блит-операций в пределах видеопамяти. Кроме того, поскольку вторичный буфер по размерам совпадает с первичной поверхностью, он подойдет для окна любого размера.

Функция 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 выглядит так:

Поделиться:
Популярные книги

Дворянская кровь

Седой Василий
1. Дворянская кровь
Фантастика:
попаданцы
альтернативная история
7.00
рейтинг книги
Дворянская кровь

Газлайтер. Том 16

Володин Григорий Григорьевич
16. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 16

Барон диктует правила

Ренгач Евгений
4. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон диктует правила

Стрелок

Астахов Евгений Евгеньевич
5. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Стрелок

Шатун. Лесной гамбит

Трофимов Ерофей
2. Шатун
Фантастика:
боевая фантастика
7.43
рейтинг книги
Шатун. Лесной гамбит

Проклятый Лекарь V

Скабер Артемий
5. Каратель
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Проклятый Лекарь V

На границе империй. Том 3

INDIGO
3. Фортуна дама переменчивая
Фантастика:
космическая фантастика
5.63
рейтинг книги
На границе империй. Том 3

Новый Рал

Северный Лис
1. Рал!
Фантастика:
фэнтези
попаданцы
5.70
рейтинг книги
Новый Рал

Его наследник

Безрукова Елена
1. Наследники Сильных
Любовные романы:
современные любовные романы
эро литература
5.87
рейтинг книги
Его наследник

Венецианский купец

Распопов Дмитрий Викторович
1. Венецианский купец
Фантастика:
фэнтези
героическая фантастика
альтернативная история
7.31
рейтинг книги
Венецианский купец

Мастер темных Арканов

Карелин Сергей Витальевич
1. Мастер темных арканов
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Мастер темных Арканов

Всплеск в тишине

Распопов Дмитрий Викторович
5. Венецианский купец
Фантастика:
попаданцы
альтернативная история
5.33
рейтинг книги
Всплеск в тишине

Начальник милиции

Дамиров Рафаэль
1. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции

Возвышение Меркурия. Книга 2

Кронос Александр
2. Меркурий
Фантастика:
фэнтези
5.00
рейтинг книги
Возвышение Меркурия. Книга 2