Краснов Михаил
Шрифт:
Также наверняка вам бросится в глаза то, что картинка появляется медленно на экране, при ее воспроизведении вы можете увидеть мельтешение черных полос. Пока старайтесь не обращать на это внимания. В будущем мы устраним это - такого не должно быть в наших серьезных проектах.
Сейчас сделайте следующее. Запишите строку, задающую параметры области вывода так:
SetRect (dstRect, 1ft, 100, 1ft + 512, 356);
Картинка выводится растянутой, из чего делаем важный вывод: метод Bit поверхности поддерживает операцию масштабирования. Удобное для нас свойство, им можно пользоваться, чтобы задавать в качестве фона растровое изображение любого размера. Для этого измените ту же строку вот так:
SetRect (dstRect, 0, 0, ClientWidth, ClientHeight);
Теперь код, заполняющий первичную поверхность черным цветом, можно просто удалить. Он не нужен, его выполнение только отнимает драгоценное время.
Плохо в получающемся примере то, что размер растра используется в нем дважды: при задании размеров первичной поверхности и при задании области вывода. Здесь нас ждет хорошая новость: во втором случае можно ничего не указывать, по умолчанию будет использоваться вся поверхность, и строку блиттинга можно записать так:
hRet := FDDSPrimary.Blt (SdstRect, FDDSImage, nil, DDBLT_WAIT, nil);
To есть третий параметр равен nil. Обязательно проверьте это, все должно работать как следует.
С точки зрения оптимизации лучше явно задавать размер копируемой поверхности.
Протестируйте работу программы при переключении и восстановлении и, если картинка пейзажа теряется, скорректируйте код функции RestoreAli.
Я воспользуюсь случаем, чтобы посвятить вас в еще одну важную тему: в любой момент времени мы можем получить информацию обо всех свойствах поверхности, в том числе и о ее размерах. Для этого предназначен метод поверхности GetSurfaceDesc.
Иллюстрацией служит проект каталога Ех09. Код обработчика onPaint формы дополнился локальной переменной ddsd2 типа TDDSurfaceDesc2, перед блиттингом с ней производятся обычные действия (обнуление всех полей и задание размера), используется она с целью хранения информации о параметрах поверхности, для получения которых и вызывается изучаемый метод:
//В ddsd2 занести данные о поверхности
FDDSImage.GetSurfaceDesc (ddsd2);
// Размеры srcRect устанавливаются равными размерам поверхности
SetRect (srcRect, 0, 0, ddsd2.dwWidth, ddsd2.dwHeight);
Сейчас в качестве упражнения рекомендую выполнить следующее задание: создайте простейшую программу просмотра bmp-файлов. После загрузки приложения пользователь выбирает нужный файл с помощью стандартного диалога. Растр выводится на полный экран.
Еще один простой пример по поводу блиттинга - проект каталога Ех10. Здесь экран раскрашивается подобно радуге (рис. 2.2).
Используется растр размером 1024x1, т. е. высотой в один пиксел. Не забывайте, что карты с небольшой видеопамятью не способны создать вторичную поверхность больше первичной. Некоторые читатели не смогут насладиться всей красотой этого примера, но ничего не потеряют, поскольку следующий проект выводит все тот же растр, и должен работать на всех картах.
В проекте каталога Ex11 я напоминаю о другом способе масштабирования растров, обычном для Delphi. При создании вторичной поверхности растровое изображение все также загружается в объект wrkBitmap. Затем создается вспомогательный объект wrkBitmapl, его ширина - 640 пикселов, высота - 1 пиксел. После чего "масштабируется" прежний растр и выводится на канве wrkBitmapi с помощью метода StretchDraw:
wrkBitmapi.Canvas.StretchDraw (Rect (0, 0, wrkBitmapi.Width,
wrkBitmapi.Height), wrkBitmap);
Размеры вторичной поверхности теперь должны опираться на размеры именно второго растра.
Такой способ масштабирования более эффективен. Задайте высоту растра равной 60 пикселам, и радуга должна заполнить экран гораздо быстрее, чем в двух предыдущих способах, поскольку меньше тратится времени при окончательном растяжении вторичной поверхности.
Упражнение: сделав wrkBitmapl глобальной переменной, добейтесь уверенного восстановления изображения.
Аналогичный прием со вспомогательным объектом класса TBitmap используется в очередном примере (проекте каталога Ех12), в котором образ загружается из jpg-файла, а при выводе картинка заключается в рамку (рис. 2.3).
В списке uses добавлены модули extctris и jpeg для использования динамически создаваемого объекта image класса Timage, в который будет загружаться jpg-файл :
Image := Timage.Create (nil); // Создаем объект