|
||||||||||||||||||
|
Часть 7. Использоание класса DDCanvas, улучшение нашего изображения Использование класса DDCanvas.Для того, чтобы использопать этот класс, следует скопировать модуль DDCanvas.pas ц каталог Lib, который находится в каталоге Delphi 3.0, или и другой каталог, обозначенный в пути поиска библиотеки. Помните ли вы злополучное взаимное исключение Win 1 б, которое приостанаилипает многозадачную работу? Хорошо, я еще раз подчеркну необходимость освобождения DC. Класс TDDCanvas имеет и использует в своих целях метод Release. Всегда заворачивайте любой доступ к полотну в блок try..finally, например: try DDCanvas.TextOut( 0, 0, 'Hello Flipping World!' ) ; DDCanvas. Release ; Или, как я часто делаю, используйте конструкцию with для того, чтобы сэкономить время набора: with DDCanvas do try TextOuK 0, 0, 'Hello Withering World!' ) ; Release ; Итак, теперь вы можете добавить пару таких полотен в объявления формы, создавая их в FormShow, например: { создать два TDDCanvas для наших двух поверхностей } Освободите их в FormDestroy перед тем, как освободить поверхности: { освободить объекты TDDCanvas перед освобождением поверхностей } Теперь можно осуществлять вывод либо на основную поверхность, либо на фоновый буфер, просто применяя эти полотна. Таким образом, вы изменяете DrawSurfacesдля их использования, значительно упрощая код, что продемонстрировано Листинг 16 DrawSurfaces использует объекты TDDCanvas. procedure TFormI. DrawSurfaces ; ATopPos : integer ; // вначале выводить на основную поверхность. ATopPos := ( 480 - TextHeight( 'A' ) ) div 2 ; // убедиться, что мы сразу же освободили DC, // теперь работаем с фоновым буфером Text0ut( 630 - TextWidth( 'Back buffer' ), ATopPos, 'Back buffer' ) ; finally // убедиться, что DC освобожден end ; Заметьте блоки try...finally с вызовом Release. Помимо этого, теперь пы добрались до этапа, на котором уже можно рисовать на поверхностях DirectDraw, не используя скверные коды DirectDraw, а просто приятные методы полотна Delphi! Улучшение нашего изображенияТеперь, когда у вас прекрасно работает смена страниц, самое время научиться загружать растровое изображение на поверхность отображения. Процесс загрузки растрового изображения значительно упрощен по сравнению с тем, как это происходило в Windows 3.х, за счет введения функций Loadimage и CreateDIBSection а WIN32 API. В Windows 95 вы можете использовать Loadimage для загрузки растрового изображения либо с дискового файла, либо из ресурса. В окончательном приложении вы несомненно встроите свои изображения в ЕХЕ-файл в виде ресурсов. Однако, полезно иметь возможность загружать их из файла во время разработки. Первой из них, на которую следует обратить внимание, является DDReLoadBitmap. Вы можете смело использовать ее без понимания того, что она делает, но с целью обучения полезно немного заглянуть в этот код. Бывают моменты, когда вам может понадобиться самостоятельно написать специализированный код по обслуживанию растровых изображений. Это даст вам определенное понимание того, как это сделать. Листинг 17 представляет эту процедуру. Листинг 17 Сервисная процедура DDReLoadBitmap для загрузки изображений. procedure DDReLoadBitmap(Surface : IDirectDrawSurface ; const BitmapName : string ) ; begin // попытаться загрузить изображение как ресурс; если это не удается, то как файл IMAGE__BITMAP, 0, 0, LR_CREATEDIBSECTION ) ; 0, 0, LR_LOADFROMFILE or LR_CREATEDIBSECTION ) ; Raise Exception .CreateFmt( 'Unable to load bitmap Is', [ BitmapName ] ) ; DeleteObject ( Bitmap ) ; Вы указываете в DDReLoadBitmap поверхность DirectDraw и имя растрового изображения, которое вы хотите загрузить в поверхность. Процедура сначала попытается произвести загрузку из ресурса, предполагая, что BitmapName является именем ресурса. Если это не удается, она предполагает, что вы указали имя файла и попытается загрузить его из файла. На самом деле в этом случае при помощи Loadimage создается секция DIB. Это Hbitmap из Windows с форматом аппаратно независимого растрового изображения (DIB). Вы можете использовать DIB-секцию как обычный Hbitmap, например, выбрав ее для DC и вызвав стандартную функцию GDI BitBIt. DDReLoadBitmap вызывает другую сервисную программу - DDCopyBitmap, которая копирует изображение секции DIB на поверхность DirectDraw. Затем блок try...finally избавляется от секции DIB, поскольку она больше не нужна. В отличие от кода обеспечения растровых изображений Windows 3.х, эта процедура достаточно проста. Теперь, как по поводу DDCopyBitmap? Как показано в листинге 18, это не намного сложнее. Листинг 18 Сервисная процедура для копирования растрового изображения на поверхность. procedure DDCopyBitmap ( Surface : IDirectDrawSurface ; Bitmap : HBITMAP ; х, y. Width, Height : integer ) ; Raise Exception. Create ( 'Invalid parameters for DDCopyBitmap' ) ; // выбрать изображение для memoryDC, чтобы его использовать. try Select0bject( ImageDC, Bitmap ) ; try ImageDC, x, y. Width, Height, SRCCOPY ) ; finally Surface. ReleaseDC ( DC ) ; DeleteDC ( ImageDC ) ; После проверки некоторых параметров DDCopyBitmap вызывает Restore, чтобы обеспечить корректность память поверхности, Затем она обращается к обычной программе Windows для копирования растрового изображения с одного DC на другой. Исходное растровое изображение выбирается для первого DC, стандартная память DC обеспечивается вызовом CreateCompatibleDC. Передача нулевых параметров ширины и высоты в программу заставляет использовать фактическую ширину и высоту растрового изображения. Для того, чтобы получить эту информацию, программа использует функцию GetObject Затем заготавливается запись SurfaceDesc путем включения флажков DDSD_HEIGHT и DDSD_WIDTH. Это передает ся в GetSurfaceDesc, которое реагирует путем заполнения полей dwHeight и dwWidth дескриптора. Программа получает второй DC из поверхности, используя вызов GetDC и осуществляя простое StretchBIt Как обычно, блоки try..-Anally используются для обязательного освобождения DC. Все это довольно простые вещи. Это развеивает по ветру устаревшую истину о том, что код обработки растровых изображений для Windows тяжело писать. К счастью, теперь вы сможете прибегнуть к сочинению подобного кода без чувства опасения за будущее! Kод DrawSurface упрощается еще больше, потому что фоновый буфер теперь можно загружать где угодно, используя DDReLoaBitmap. Упрощенный DrawSurface представлен в листинге 19. Листинг 19 DrawSurface без кода отрисовки фоновой поверхности. procedure TFormI DrawSurfaces ; ATopPos : integer ; // вывод на основное полотно. ATopPos :^ ( 480 - TextHeight( 'A* ) ) div 2 ; finally // убедиться, что мы сразу же освободили DC, { загрузить изображение в фоновый буфер } А что по поводу палитр?Я знал, что об этом вы обязательно бы меня спросили! Хорошо, мы все еще вынуждены работать с палитрами. Настало время представить еще один СОМ-объект DirectDraw, На этот раз это lDirectDrawPalette. Этот маленький полезный объект обслужит большинство компонент палитры, нс утруждая этим нас с вами. Для того, чтобы использовать IDirectDraw, высоздаете его с IDirectDraw.CreatePalette, которая устанавливает указатель на массив вводимых данных палитры, который использовался для инициализации объекта палитры. Затем вы присоединяете ее к поверхности DrawSurface и она станет использоваться автоматически для всех последующих операций. Конечно же, прекрасно. Итак, как же получить эти значения цветов? Хорошо, я написал еще одну небольшую функцию для их загрузки из растрового изображения или создания цветов по умолчанию, и для создания и возврата объекта IDirectDrawPalette. Она Я добавил объект палитры к объявлению формы, загрузил его в FormShow и присоединил объект палитры к основной поверхности следующим образом: { загрузить палитку иэ растрового изображения и присоединить ее к основной поверхности ) Создав, вы должны освободить его из основной поверхности в FormDestroy: ( освободить DD-палитру } Проделав все изменения, вы можете теперь приступить к проверке. DDDemoS содержит все изменения, обозначенные до настоящего момента. Объединение всего вместеВ настоящий момент вы можете составить DirectDraw-приложсние со сменой страниц, а также загрузить растровое изображение и палитру. У вас имеется все необходимое для создания смены страниц и причем на полной скорости! Для того, чтобы было еще интересней, как насчет анимации? DirectDraw в одной из демонстрационных программ использует файл с именем ALL.BMP. Вы также скачать его вместе с примером DDDenno5. В ней содержится еще одно более интересное Перед очередной сменой страницы вы захотите отобразить фоновое изображение и затем текущий анимационный кадр с тором. Вы создаете три тора в разных позициях на экране, которые будут вращаться с разной скоростью. Ввиду того, что Существенно важно отметить, что по умолчанию DirectDraw создает исходное изображение в экранной памяти. Это означает, что когда вы используете изображение для обновления фонового буфера, любой производимый битовый перенос использует аппаратный перенос битов, если таковой имеется на графической карте. Практически все персональные компьютеры в настоящее время оснащены ускоренной графической картой, которую как раз и использует DirectDraw. Ввиду того, что это аппаратное обеспечение работает намного быстрее, чем процессор во время битового переноса, игры DirectDraw должны иметь большую эффективность по отношению к играм DOS, где процессор делает все. Битовый перенос (bit-blitting) - термин, используемый для описания переноса областей растровых изображений в, из или в пределах других растровых изображений. Термин иногда записывается более точно как bitblting, но он сложен для чтения, поэтому вы часто найдете его в расчлененным в виде двух слов bit-blitting. BitBIt - краткое описание термина BITmap Block Transfer (перенос блока растрового изображения). Итак, за работу. Создайте эту дополнительную поверхность и назовите ее Image (изображение). Добавьте ее в объявление формы. Это как раз и есть IDirectDrawSurface, поэтому нет необходимости представлять здесь эту тривиальную строку кода. Затем добавьте код в FormShow, который создает растровое изображение. Используйте DDLoadBitmap, это только одна строка! Вот она: Помните, что вам необходимо пополнить метод RestoreSurfaces и тогда вы получите новую неявную поверхность. Если восстановление основной памяти поверхности пройдет нормально, попытайтесь восстановить поверхностную память Image. Если оба типа восстановлений будут иметь место, вызовите DrawSurfaces, как показано в листинге 20. Листинг 20 Восстановление всех поверхностей. function TFormI. RestoreSurfaces : HResult ; |
|
Web дизайн: Бурлаков Михаил
Web программирование: Бурлаков Михаил