Рейтинговые книги
Читем онлайн Графика для Windows средствами DirectDraw - Стэн Трухильо

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 17 18 19 20 21 22 23 24 25 ... 66

}

Инициализация приложения завершается вызовом функций 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) {

  xinc=-xinc;

  x+=xinc;

 }

 if (y<-100 || y>height-100) {

  yinc=-yinc;

  y+=yinc;

 }

 BltSurface(backsurf, surf1, x, y);

 int offsetx=client.left;

 int offsety=client.top;

 RECT srect;

 srect.left=0;

 srect.top=0;

 srect.right=client.Width();

 srect.bottom=client.Height();

 RECT drect;

 drect.left=offsetx;

 drect.top=offsety;

 drect.right=offsetx+client.Width();

 drect.bottom=offsety+client.Height();

 primsurf->Blt(&drect, backsurf, &srect, DDBLT_WAIT, 0);

}

Функция 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 в дополнение к этому позволяет выбрать частоту смены кадров для каждого видеорежима.

Перед тем как переходить к программированию, мне хотелось бы сказать, что в этой главе нет ничего сложного. Управление видеорежимами — одна из простейших возможностей DirectDraw, да и с частотой смены кадров разобраться не так уж тяжело. Следовательно, я вовсе не собираюсь поразить вас сообщением о том, что в DirectDraw можно переключать видеорежимы. Вместо этого мы рассмотрим проблемы, связанные с переключением режимов, а заодно рассеем некоторые распространенные заблуждения. Материал этой главы поможет вам писать приложения с простым и надежным переключением видеорежимов.

Кроме того, эта глава преследует и другую цель. В программах Switch и SuperSwitch используются некоторые средства DirectDraw, которые, скорее всего, вам пригодятся (или уже пригодились), — например, цветовые ключи и вывод текста на поверхности. Хотя у нас нет времени для подробного изучения этих тем, мы кратко рассмотрим их в этой главе, чтобы в дальнейшем никакие объяснения уже не понадобились.

Переключение видеорежимов

Для безопасного вызова функции SetDisplayMode() интерфейса DirectDraw стоит заранее убедиться в том, что нужный вам режим поддерживается. Как мы узнали из главы 3, класс DirectDrawWin с помощью функции EnumDisplayModes() интерфейса DirectDraw строит список всех доступных видеорежимов. Пользуясь функциями доступа, мы можем применить информацию из этого массива для надежного вызова SetDisplayMode().

Тем не менее переключение видеорежимов не сводится к простому вызову функции SetDisplayMode(). По этой причине в класс DirectDrawWin была включена функция ActivateDisplayMode(), которая выполняет все необходимые действия для гладкого перехода от одного режима к другому. Вскоре мы рассмотрим ActivateDisplayMode() и все, что она делает, но сначала давайте обратимся к самой функции SetDisplayMode().

Функция SetDisplayMode()

Существуют две версии функции SetDisplayMode(). Первая из них принадлежит интерфейсу DirectDraw и вызывается с тремя аргументами. Вторая версия принадлежит интерфейсу DirectDraw2 и вызывается с пятью аргументами. Прототип первой функции выглядит так:

HRESULT SetDisplayMode(DWORD width, DWORD height, DWORD depth);

СОВЕТ

Для любознательных читателей

Заглянув в заголовочный файл DirectDraw (ddraw.h), вы не найдете в нем этого прототипа. Это объясняется тем, что все функции DirectDraw описываются на IDL (языке определения интерфейсов) спецификации COM. На IDL функция SetDisplayMode() выглядит так:

STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD, DWORD) PURE;

Для наших целей IDL не нужен. Все, что нам необходимо знать, — имя функции, тип возвращаемого значения, а также количество и типы аргументов. Все эти сведения более четко описываются традиционными прототипами функций, которые и приводятся в книге и справочных файлах DirectX. 

Функция SetDisplayMode(), как и большинство функций DirectX API, возвращает значение типа HRESULT — 32-разрядную величину с описанием результата вызова функции. Ее значение DD_OK показывает, что вызов оказался успешным.

Версия SetDisplayMode() из интерфейса DirectDraw получает три аргумента типа DWORD. Эти аргументы определяют разрешение экрана и глубину пикселей нужного видеорежима, поэтому стандартный видеорежим VGA 640×480×8 активизируется так:

ddraw1->SetDisplayMode(640, 480, 8);

Выглядит довольно просто, поэтому давайте перейдем к версии SetDisplayMode() из интерфейса DirectDraw2. Ее традиционный прототип выглядит так:

HRESULT SetDisplayMode(DWORD width, DWORD height, DWORD depth,  DWORD refreshrate, DWORD flags);

В этой версии появляются два дополнительных аргумента: частота смены кадров и двойное слово, которое может быть использовано в будущих версиях DirectDraw, а пока должно быть равно нулю. В расширенной версии SetDisplayMode() стандартный видеорежим VGA 640×480×8 можно активизировать так:

ddraw1->SetDisplayMode(640, 480, 8, 0, 0);

В данном случае вместо частоты смены кадров передается 0; это означает, что должна быть использована частота, принятая по умолчанию. Кроме того, можно указать конкретное значение частоты (60 Гц в следующем примере):

ddraw1->SetDisplayMode(640, 480, 8, 60, 0);

Однако не следует думать, что вы можете задать любую частоту (или другие параметры видеорежима). Перед тем как вызывать SetDisplayMode(), необходимо сначала определить параметры и частоты допустимых видеорежимов.

Обнаружение видеорежимов и частот смены кадров

В главе 3 говорилось о том, как функция EnumDisplayModes() интерфейса DirectDraw перечисляет все поддерживаемые видеорежимы. Через косвенно вызываемую функцию она сообщает вашему приложению о каждом видеорежиме, поддерживаемом установленными видеоустройствами. Прототип функции EnumDisplayModes() выглядит так:

1 ... 17 18 19 20 21 22 23 24 25 ... 66
На этой странице вы можете бесплатно читать книгу Графика для Windows средствами DirectDraw - Стэн Трухильо бесплатно.
Похожие на Графика для Windows средствами DirectDraw - Стэн Трухильо книги

Оставить комментарий