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

ЖАНРЫ

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

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

Шрифт:
Варианты Visual C++ 

И последнее замечание о Visual C++. Поскольку этот продукт выпускается в трех вариантах (Learning, Professional и Enterprise), иногда читателям не удается скомпилировать проект. Для написания и тестирования программ этой книги я пользовался вариантом Professional, так что при работе с другими вариантами могут возникнуть проблемы. Впрочем, в основном это проблемы мелкие и легко излечимые. Если у вас возникнут трудности и вы решите обратиться ко мне, пожалуйста, укажите версию и вариант Visual C++.

Советы и рекомендации 

В этом разделе рассматривается несколько не связанных друг с другом, но полезных тем.

Сначала мы поговорим об одной ошибке DirectDraw, а затем узнаем кое-что о файлах DirectX. Напоследок я скажу пару слов о видеокартах на базе чипов 3Dfx. 

Ошибка переключения режимов DirectDraw 

В DirectDraw есть одна ошибка, связанная с переключением режимов, которую никак не может исправить Microsoft (или тот, кто для них пишет видеодрайверы). Впервые я столкнулся с ней во время работы над предыдущей книгой. Я надеялся, что к моменту написания этой книги ошибку уже исправят, но она так и осталась.

Проблемы возникают при активизации видеорежимов, которые отличаются по глубине пикселей от текущего активного режима Windows. Например, если Windows работает в 8-битном видеорежиме, а ваше приложение DirectDraw попытается активизировать 16-битный видеорежим, ничего не получится, даже когда новый режим вполне допустим. Если попытаться установить 8-битный видеорежим при 16-битном режиме Windows, результат будет тем же. В таких случаях DirectX выдает отладочное сообщение следующего вида:

DDHEL: ChangeDisplaySettings LIED!!!

DDHEL: Wanted 640x480x16 got 1024x768x8

DDHEL: ChangeDisplaySettings FAILED: returned -1

К счастью, это происходит только при первой попытке изменения видеорежима. Если эта попытка удалась, после этого можно установить любой видеорежим. Следовательно, у нас появляется обходной путь: если текущий видеорежим отличается по глубине пикселей от желаемого, переключение следует производить в два этапа; сначала перейдите к видеорежиму, который совпадает по глубине пикселей с текущим, а затем — к видеорежиму, нужному вам.

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

int SampleWin::SelectInitialDisplayMode {

 DWORD curdepth=GetDisplayDepth;

 int i, nummodes=GetNumDisplayModes;

 DWORD w,h,d;

 if (curdepth!=16) ddraw2->SetDisplayMode(640, 480, curdepth, 0, 0 );

 // Искать режим 640x480x16 после смены видеорежима

 for (i=0;i>nummodes;i++) {

GetDisplayModeDimensions(i, w, h, d);

if (w==640 && h==480 && d==16) return i;

 }

 return -1;

}

Мы проверяем глубину пикселей текущего видеорежима Windows функцией DirectDrawWin::GetDisplayDepth. Нас интересует режим с 16-битными пикселями, поэтому при использовании другой глубины мы активизируем режим 640×480 с текущей глубиной, вызывая функцию SetDisplayMode интерфейса DirectDraw. Затем можно переходить к поиску нужного режима в традиционном цикле.

Другой выход — просто воспользоваться

той глубиной пикселей, которая в данный момент установлена в Windows. Этот вариант не подойдет в тех случаях, когда работа программы зависит от определенных параметров видеорежима, но неплохо работает, если приложение поддерживает видеорежимы с различными глубинами пикселей. В частности, он встречается в программе Switch (см. главу 4), разработанной специально для поддержки любого режима. Функция SelectInitialDisplayMode в программе Switch выглядит так:

int SwitchWin::SelectInitialDisplayMode {

 DWORD curdepth=GetDisplayDepth;

 int i, nummodes=GetNumDisplayModes;

 DWORD w,h,d;

 // Искать режим 640x480 с текущей глубиной пикселей

 for (i=0;i<nummodes;i++) {

GetDisplayModeDimensions(i, w, h, d);

if (w==640 && h==480 && d==curdepth) return i;

 }

 return 0;

}

Эта функция ищет режим 640×480 с текущей глубиной пикселей. Такой режим наверняка найдется, потому что 640×480 — «общий знаменатель» для всех видеорежимов и нам известно, что нужная глубина пикселей уже установлена в Windows.

Следует заметить, что такое поведение характерно лишь для некоторых конфигураций. Иногда нужную глубину пикселей можно установить сразу, без глупых обходных маневров (например, я еще не видел, чтобы эта ошибка проявлялась на компьютерах с Windows NT). Но чтобы расширить круг рабочих конфигураций вашего приложения, пожалуй, стоит помнить об этой ошибке.

Символическая константа INITGUID (устаревшая) 

Как вы уже знаете, библиотека DirectX построена на базе спецификации COM, а для однозначной и систематизированной идентификации интерфейсов в COM применяются GUID. Один из заголовочных файлов COM содержит код, в котором инициализируются все конструкции, относящиеся к GUID. Такой метод инициализации COM требует, чтобы символическая константа INITGUID была определена в одном и только одном кодовом модуле, до включения заголовочных файлов COM (для DirectX заголовочные файлы COM включаются косвенно, из заголовочных файлов DirectX). Следовательно, в некоторых программах можно встретить константу INITGUID. Этот метод вызывает немало хлопот, особенно при работе с прекомпилированными заголовками, потому что он не позволяет включить заголовочные файлы DirectX в состав прекомпилированного заголовка.

Вы не встретите INITGUID в программах на CD-ROM, потому что, начиная с DirectX 3, появилось более удачное решение — вместо того, чтобы определять INITGUID, достаточно подключить к проекту файл DXGUID.LIB. На случай, если вы не знали…

Эмуляция версий 

Одна из широко разрекламированных возможностей COM — управление версиями. COM-объекты устроены так, что доступ к ним может осуществляться только через строго определенные интерфейсы. В соответствии с правилами COM, интерфейс не может изменяться после его определения. Вместо этого приходится вводить новый интерфейс, который поддерживает как старые, так и новые возможности. При этом новые программы могут без опасений пользоваться новыми возможностями, а старые — работать со старыми интерфейсами, которые заведомо не изменятся. Эта схема неплохо работает и помогает обеспечить совместимость приложений DirectX со старыми и новыми runtime-частями библиотеки.

Поделиться с друзьями: