- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Графика DirectX в Delphi - Михаил Краснов
Шрифт:
Интервал:
Закладка:
Начинающих программистов может смущать кажущаяся запутанность с цифрами в типах переменных, скажем, тип TDDSurfaceDesc2 заканчивается не на 7. Одни типы, например интерфейсы, менялись с каждой версией, другие же вспомогательные типы модифицировались реже, поэтому их цифры "отстают" от нумерации используемых интерфейсов.
Еще один вопрос, который надо разрешить, тоже связан с версией DirectX. Многое из того, что мы применяем, присутствует и в более ранних версиях, и для массы примеров вполне можно использовать интерфейсы не седьмой, а, например, пятой версии. Легко поддаться такому соблазну, ведь тогда круг потенциальных пользователей вашей программы существенно расширяется. Я не смогу придерживаться этого, и вам советую делать подобное лишь в случае крайней необходимости. Ведь наверняка со временем разношерстность кода приведет к полному беспорядку в ваших проектах. Согласно спецификации СОМ-интерфейс не может меняться после его определения. Новый интерфейс должен поддерживать как старые, так и новые возможности. Но интерфейсы со старшими номерами версий не обязательно должны быть образованы от соответствующих интерфейсов с меньшими номерами.
Еще одна потенциальная проблема связана со вспомогательными структурами. Мы уже начали с ними знакомиться. Доступ к этим структурам, используемым в методах интерфейсов, осуществляется в программе непосредственно, а не через интерфейс (мы сами заполняем поля записи). Структуры с каждой новой версией могут обрастать новыми полями, следовательно, размер их меняется.
Именно по этой причине каждая функция должна обязательно получать и размер передаваемой структуры.
Более старая версия DirectX не сможет обработать новые поля знакомой ей структуры, она просто ничего не знает о появившихся в ней новых полях. Разработчики попытались снять часть возникших проблем, вводя новые типы структур, те самые двойки в имени их появились из-за запрета на применение одноименных методов разных интерфейсов. Но самым лучшим решением для нас будет использование текущей версии DirectX.
Двигаемся дальше. Попробуем порисовать что-нибудь в привычном для нас антураже. Переходим к проекту каталога Ех02, отличающемуся от предыдущего тем, что здесь добавился обработчик события onPaint формы:
procedure TfrmDD.FormPaint(Sender: TObject);
var
// Вспомогательный дескриптор, идентификатор устройства вывода GDI
DC : HDC;
wrkCanvas : TCanvas; // Вспомогательный объект, рабочая канва begin
// Получение дескриптора, необходимого для функций GDI
if FDDSPrimary.GetDC(DC) = DD_OK then begin
wrkCanvas := TCanvas.Create; // Создаем вспомогательную канву
wrkCanvas.Handle := DC; // Задаем идентификатор канвы = DC
// Рисуем на канве кружок
wrkCanvas.Ellipse (Left + 50, Top + 50, Left + 100, Top + 100);
wrkCanvas.Free; // Освобождение памяти, удаление канвы
FDDSPrimary.ReleaseDC (DC); // Освобождение контекста устройства
end;
end;
Пример учебный, не ожидайте от него ничего выдающегося. Впереди нас ждут еще более впечатляющие программы. При запуске проекта ничего особенного не происходит, на поверхности окна рисуется кружок. Причем вы можете даже обнаружить, что появляется он на экране медленнее, чем нарисованный обычным способом.
Канва Delphi является оболочкой системных функций вывода GDI, ее свойство Handle в точности соответствует типу нос, ссылке на устройство вывода. В этой величине нуждаются все функции GDI для идентификации устройства, окна или блока памяти, в который осуществляется вывод.
Как видно из кода, метод поверхности Getoc позволяет в нужную переменную поместить значение такого идентификатора. Установив значение Handle канвы в найденное значение, мы добьемся того, что вывод на канве физически будет осуществляться на необходимое нам устройство. Все это нам знакомо по предыдущей главе.
Первичная поверхность в нашей программе является канвой рабочего стола, так мы сами задали ее свойства. Поэтому канва связана с областью всего экрана, и прямоугольник, ограничивающий кружок, мы задаем в координатах рабочего стола, а не в координатах окна приложения. Затем мы освобождаем память и контекст вывода. Это действие является предельно важным. Если его не выполнить, то приложение просто закроет доступ к рабочему столу для всех остальных приложений и для операционной системы. Страшная ситуация!
Поработайте с проектом. При перемещении окна все работает так, как мы того ожидаем, но вот если размеры окна сделать слишком маленькими, то кружок может выходить за его пределы. Это объяснимо. Мы знаем, что круг рисуется на поверхности всего экрана. Если же окно приложения перекрыть другим окном или минимизировать, а затем распахнуть, то кружок уже не появляется.
Мы подходим к очень важным вопросам, специфичным именно для DirectDraw. Ситуацию, когда приложение временно убирается с экрана, а затем восстанавливается, необходимо в приложениях фиксировать.
Посмотрите проект каталога Ех03, в котором отслеживается ошибка, возникающая при такой ситуации, и пользователю выдается осмысленное сообщение (рис. 2.1).
Код ошибки - DDERR_SURFACELOST. Как сообщается в его расшифровке, в таком случае необходимо использовать метод Restore поверхности.
Пример делает прозрачным причины потери поверхности. Первичную поверхность мы связали с рабочим столом, и, конечно, после того, как окно "ушло" с экрана, оно освободило память поверхности для других приложений. Теперь ему надо заново вернуть свои исключительные права на область памяти. Такая же ситуация возникает при изменении параметров рабочего стола по ходу работы приложения.
Также многие из функций DirectDraw могут вернуть код ошибки DDERR_WASSTILLDRAWING, означающий, что аппаратное обеспечение занято и запрос необходимо повторять до тех пор, пока не добьемся успеха или не получим иного сообщения об ошибке.
Взгляните на проект каталога Ех04, здесь решены все эти проблемы, и первое, что изменилось, - это код, связанный с перерисовкой окна. Теперь код собственно воспроизведения заключен внутрь цикла, из которого мы выходим либо в случае успешного воспроизведения, либо если поверхность восстановить не удается, либо код ошибки отличен от DDERR_WASSTILLDRAWING:
while True do begin возможно, // Код придется повторять неоднократно
hRet := FDDSPrimary.GetDC(DC); // Заново получаем дескриптор
if Succeeded (hRet) then begin
wrkCanvas := TCanvas.Create;
wrkCanvas.Handle := DC; wrkCanvas.Ellipse (Left + 50, Top + 50, Left + 100, Top + 100);
wrkCanvas.Free; FDDSPrimary.ReleaseDC (DC); Break;
end;
// Поверхность потеряна, надо восстановить if hRet = DDERR_SURFACELOST then begin
hRet := FDDSPrimary._Restore;
// Если не удалось восстановить, дальше продолжать нельзя
if hRet <> DD_OK then Break; end;
// Ошибка отлична от DDERR_WASSTILLDRAWING, следовательно непоправима if hRet <> DDERR_WASSTILLDRAWING then Break;
end;
Чтобы кружок не рисовался за пределами окна приложения, можно просто не разрешать уменьшать высоту окна. Таким образом, появился обработчик
события OnCanResize:
procedure TfrmDD.FormCanResize(Sender: TObject; var NewWidth,
NewHeight: Integer; var Resize: Boolean); begin
if NewHeight < 110 // Высота окна не должна быть меньше 110
then Resize := False
else Resize := True;
end;
Что еще надо сделать, так это при обработке события OnResize окна вызывать тот же код, что и при событии OnPaint.
Для обработки тех ситуаций, когда восстановить поверхность не удается, в проект добавлен компонент класса TAppLicationEvents, на события OnActivate и onRestore которого вызывается такой же код, как и при создании окна. То есть при восстановлении минимизированного окна и каждой активизации окна приложения заново создаем первичную поверхность.
Хорошенько поработайте с проектом: протестируйте его работу в самых различных ситуациях, минимизируйте и восстанавливайте окно, активизируйте самыми различными способами, поменяйте установки экрана по ходу работы этого приложения. Кружок должен появляться всегда, когда мы его ожидаем. При деактивизации окно может вести себя непривычно для обычных приложений, можете записать Application.Minimize в обработчике события OnDeactivate единственного компонента проекта. Восстанавливается окно тоже особым образом, распахиваясь на весь экран.
Такое использование полноэкранной первичной поверхности, как в этом примере, когда воспроизведение осуществляется только функциями GDI в пределах окна приложения, редко применяется в практических задачах.
В примере есть небольшое упрощение. Так как при восстановлении окна приложения и его активизации (пользователь переходит на него с помощью комбинации клавиш <Alt>+<Tab>) поверхность создается заново, то она никогда не будет потеряна. Такой прием можно использовать только для простейших приложений, поскольку весьма неэкономно тратить время подготовки работы при каждой активизации приложения.
Блиттинг
Блиттингом называется копирование графических изображений в память видеоустройств, и DirectDraw представляет собой просто механизм блиттинга.

