Для поверхности, создаваемой в видеопамяти, надо использовать комбинацию флагов DDSCAPS_OFFSCREENPLAIN or DDSCAPSJ/IDEOMEMORY. и наоборот, флаг DDSCAPS_SYSTEMMEMORY указывает, что поверхность должна располагаться в системной памяти.
Метод GetAvailablevidMem главного объекта DirectDraw позволяет выяснить, сколько видеопамяти осталось в распоряжении приложения.
При нехватке видеопамяти операция создания поверхности завершится провалом, код соответствующей ошибки - DDERR_OUTOFVIDEOMEMORY. В этом случае необходимо поменять флаг и заново попытаться создать поверхность.
Теперь обсудим вопросы масштабирования растров. Вспомогательная функция копирования растра поддерживает масштабирование. Задайте размер вторичной поверхности больше, чем размер используемого растра, например, так:
ddsd.dwWidth := wrkBitmap.Width * 2;
Теперь при воспроизведении мы увидим картинку, растянутую вдоль экрана, но не всю, а только ее половину. Для того чтобы вывести ее целиком, надо изменить значение поля Right структуры dstRect:
SetRect (dstRect, 100, 100, 100 + 256 * 2, 356);
Попробуем перемещать картинку по экрану (проект каталога Ех08). Переменная ift хранит текущее значение смещения картинки, на это значение опираемся при заполнении полей структуры dstRect:
SetRect (dstRect, 1ft, 100, 1ft + 256, 356);
Форма дополнилась обработчиком нажатия клавиши: демонстрационные программы, использующие DirectDraw, традиционно должны завершать работу при нажатии клавиши или . Добавилась также обработка нажатий клавиш управления курсором:
case Key of
VK_ESCAPE, VK_F12 : begin // Традиция для DirectDraw
Close; Exit;
end;
VK_LEFT : begin // Клавиша "стрелка влево"
Dec (1ft, 1); // Уменьшаем 1ft
FormPaint (nil); // Перерисовываем экран end;
VK_RIGHT : begin // Клавиша "стрелка вправо"
Inc (1ft, 1); // Увеличиваем 1ft
FormPaint (nil); // Перерисовываем экран
end;
end;
Обратите внимание, что для перерисовки окна метод Refresh не годится, иначе сквозь экран будет проглядывать мелькнувшее окно приложения. Картинка движется с малым шагом с целю убедить вас, что если хоть один пиксел растра не помещается на первичную поверхность, не воспроизводится ничего.
Также наверняка вам бросится в глаза то, что картинка появляется медленно на экране, при ее воспроизведении вы можете увидеть мельтешение черных полос. Пока старайтесь не обращать на это внимания. В будущем мы устраним это - такого не должно быть в наших серьезных проектах.
Сейчас сделайте следующее. Запишите строку, задающую параметры области вывода так:
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-файлов. После загрузки приложения пользователь выбирает нужный файл с помощью стандартного диалога. Растр выводится на полный экран.
Читать дальше
Конец ознакомительного отрывка
Купить книгу