Графика для Windows средствами DirectDraw
Шрифт:
Далее объект отсечения присоединяется к первичной поверхности приложения функцией SetClipper интерфейса DirectDrawSurface. После такого присоединения можно осуществлять блиттинг на первичную поверхность с помощью функции Blt интерфейса DirectDrawSurface. Использовать функцию BltFast нельзя, потому что она не поддерживает отсечения.
Последнее, что происходит в функции CreateFlippingSurface, - создание поверхности вторичного буфера. В идеальном варианте нам удастся найти свободную видеопамять в объеме, достаточном для создания внеэкранной поверхности, которая по ширине и высоте совпадает с первичной поверхностью. Я называю такой вариант идеальным из-за преимущества
Функция CreateFlippingSurfaces пытается создать «идеальный» вторичный буфер, для чего используются флаг DDSCAPS_VIDEOMEMORY и функция CreateSurface. Если вызов заканчивается успешно, флаг videobacksurf получает значение TRUE, а функция завершает работу. В противном случае вторичный буфер не создается, а флагу videobacksurf присваивается значение FALSE.
В том варианте вторичный буфер создается приложением в системной памяти позднее, в обработчике OnSize. Функция OnSize вызывается при изменении размеров окна приложения. Создавая вторичный буфер по размерам клиентской области окна, мы экономим память. Функция OnSize выглядит так:
Инициализация приложения завершается вызовом функций StorePixelFormatData и CreateCustomSurfaces, происходящим в обработчике OnCreate. Обе функции ведут себя точно так же, как и в полноэкранном приложении.
Как и в полноэкранном варианте, для обновления экрана класс DirectDrawWin вызывает функцию DrawScene. Ее реализация для оконных приложений отличается от полноэкранного варианта по двум причинам. Во-первых, поскольку в оконном приложении не выполняется переключение страниц, содержимое вторичного буфера приходится копировать на первичную поверхность. Во-вторых, местонахождение выводимых данных на первичной поверхности должно определяться текущим положением и размерами окна. Помните — первичная поверхность в данном случае изображает весь экран, а не только клиентскую область окна. Оконный вариант DrawScene выглядит так:
Функция DrawScene
выполняет две блит-операции. Первая копирует содержимое поверхности surf1 на внеэкранную поверхность, которая используется в качестве вторичного буфера. Обратите внимание на применение функции BltSurface, рассмотренной нами выше. Автоматическое отсечение, выполняемое BltSurface, позволяет произвольно выбирать позицию на поверхности surf1.Вторая блит-операция копирует содержимое вторичного буфера на первичную поверхность. На этот раз используется функция Blt, поскольку к первичной поверхности присоединен объект отсечения. Структуры srect и drect типа RECT определяют области источника и приемника, участвующие в блиттинге. Заметьте, что при вычислении области приемника используются переменные offsetx и offsety, в которых хранятся координаты клиентской области окна. Если убрать эти смещения из структуры drect, программа всегда будет выводить изображение в левом верхнем углу экрана независимо от расположения окна.
В этой главе мы изучили почти весь код, сгенерированный AppWizard. Рассмотренное нами базовое приложение нетрудно изменить, поэтому попробуйте немного поэкспериментировать. Например, попытайтесь добавить в программу Bounce дополнительные поверхности или замените вызовы BltSurface на BltFast и посмотрите, что получится.
В оставшейся части книги речь в основном пойдет о том, какие изменения следует внести в базовый код, чтобы добиться конкретного результата. В главе 4 мы напишем программу, которая в полной мере использует возможности DirectDraw по переключению видеорежимов.
Глава 4. Видеорежимы и частота смены кадров
В главе 1 я упоминал функции EnumDisplayModes и SetDisplayMode интерфейса DirectDraw и говорил о том, что они применяются для обнаружения и активизации видеорежимов. Здесь эти функции будут применены на практике. Сначала мы познакомимся с общими принципами переключения видеорежимов, а затем рассмотрим две демонстрационных программы: Switch и SuperSwitch. Программа Switch выводит меню с обнаруженными видеорежимами и позволяет последовательно активизировать каждый из них. Программа SuperSwitch в дополнение к этому позволяет выбрать частоту смены кадров для каждого видеорежима.