Графика для Windows средствами DirectDraw
Шрифт:
И последнее замечание о Visual C++. Поскольку этот продукт выпускается в трех вариантах (Learning, Professional и Enterprise), иногда читателям не удается скомпилировать проект. Для написания и тестирования программ этой книги я пользовался вариантом Professional, так что при работе с другими вариантами могут возникнуть проблемы. Впрочем, в основном это проблемы мелкие и легко излечимые. Если у вас возникнут трудности и вы решите обратиться ко мне, пожалуйста, укажите версию и вариант Visual C++.
Советы и рекомендации
В этом разделе рассматривается несколько не связанных друг с другом, но полезных тем.
В DirectDraw есть одна ошибка, связанная с переключением режимов, которую никак не может исправить Microsoft (или тот, кто для них пишет видеодрайверы). Впервые я столкнулся с ней во время работы над предыдущей книгой. Я надеялся, что к моменту написания этой книги ошибку уже исправят, но она так и осталась.
Проблемы возникают при активизации видеорежимов, которые отличаются по глубине пикселей от текущего активного режима Windows. Например, если Windows работает в 8-битном видеорежиме, а ваше приложение DirectDraw попытается активизировать 16-битный видеорежим, ничего не получится, даже когда новый режим вполне допустим. Если попытаться установить 8-битный видеорежим при 16-битном режиме Windows, результат будет тем же. В таких случаях DirectX выдает отладочное сообщение следующего вида:
К счастью, это происходит только при первой попытке изменения видеорежима. Если эта попытка удалась, после этого можно установить любой видеорежим. Следовательно, у нас появляется обходной путь: если текущий видеорежим отличается по глубине пикселей от желаемого, переключение следует производить в два этапа; сначала перейдите к видеорежиму, который совпадает по глубине пикселей с текущим, а затем — к видеорежиму, нужному вам.
Такой обходной маневр нетрудно реализовать с помощью класса DirectDrawWin, представленного в этой книге. В функции SelectInitialDisplayMode (которая вызывается до переключения видеорежима) следует проверить глубину пикселей текущего режима. Если она отличается от требуемой, выполните «фиктивное» переключение. Программа может выглядеть так:
Мы проверяем глубину пикселей текущего видеорежима Windows функцией DirectDrawWin::GetDisplayDepth. Нас интересует режим с 16-битными пикселями, поэтому при использовании другой глубины мы активизируем режим 640×480 с текущей глубиной, вызывая функцию SetDisplayMode интерфейса DirectDraw. Затем можно переходить к поиску нужного режима в традиционном цикле.
Другой выход — просто воспользоваться
той глубиной пикселей, которая в данный момент установлена в Windows. Этот вариант не подойдет в тех случаях, когда работа программы зависит от определенных параметров видеорежима, но неплохо работает, если приложение поддерживает видеорежимы с различными глубинами пикселей. В частности, он встречается в программе Switch (см. главу 4), разработанной специально для поддержки любого режима. Функция SelectInitialDisplayMode в программе Switch выглядит так:Эта функция ищет режим 640×480 с текущей глубиной пикселей. Такой режим наверняка найдется, потому что 640×480 — «общий знаменатель» для всех видеорежимов и нам известно, что нужная глубина пикселей уже установлена в Windows.
Следует заметить, что такое поведение характерно лишь для некоторых конфигураций. Иногда нужную глубину пикселей можно установить сразу, без глупых обходных маневров (например, я еще не видел, чтобы эта ошибка проявлялась на компьютерах с Windows NT). Но чтобы расширить круг рабочих конфигураций вашего приложения, пожалуй, стоит помнить об этой ошибке.
Как вы уже знаете, библиотека 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-частями библиотеки.