Краснов Михаил
Шрифт:
end else Result := hRet;
end;
Теперь мы можем узнать смысл первых трех аргументов метода Bit поверхности. Первый из них - указатель на структуру типа TRECT, задающую местоположение и размер области, в которую происходит копирование. Второй параметр - поверхность источника. Третий аргумент - указатель на структуру типа TRECT, задающую местоположение и размер области, из которой происходит копирование.
Флагом задаем константу DDBLT_WAIT, не комбинацию значений. Дополнительные параметры пока не указываем, поэтому последний аргумент метода устанавливаем в nil.
Пример простой, но очень важный. Осмыслим изученное. Естественным для DirectDraw способом воспроизведения является блиттинг. На вспомогательных поверхностях размещаем нужные нам образы, а в определенный момент времени копируем требуемые области с одной поверхности на другую, в простейшем случае - со вспомогательных поверхностей на первичную, связанную с экраном.
Вторичных поверхностей создают столько, сколько требуется приложению. Разработчик сам решает, что и где ему располагать, но здесь надо учесть небольшую тонкость: если видеокарта имеет малый размер памяти, то вторичную поверхность не получится создать размером больше первичной. Может быть, это происходит только с конкретными картами, но я действительно встречался с такой ситуацией.
Поверхностей вы можете создавать сколько угодно, но чем их меньше, тем быстрее будет осуществляться блиттинг. Поэтому лучше не плодить множество поверхностей, а, в идеальном случае, располагать все образы на одной большой поверхности.
В общем случае операция копирования блоков из системной памяти в видеопамять осуществляется медленнее, чем из видеопамяти в видеопамять. Поэтому образы, выводимые наиболее часто, старайтесь размешать в видеопамяти, а при ее нехватке те из образов, которые редко будут появляться, например заставки или меню, следует размещать в системной памяти.
Поддержка AGP если и стирает разницу в скоростях обмена, то незначительно. Если бы скорости работы с видеопамятью и системной памятью сосовпадали или были близки друг к другу, не было бы нужды производителям карт выпускать модели, различающиеся размером видеопамяти, а пользователям оставалось лишь наращивать размер системной памяти.
Для поверхности, создаваемой в видеопамяти, надо использовать комбинацию флагов 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, традиционно должны завершать работу при нажатии клавиши <Esc> или <F12>. Добавилась также обработка нажатий клавиш управления курсором:
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 не годится, иначе сквозь экран будет проглядывать мелькнувшее окно приложения. Картинка движется с малым шагом с целю убедить вас, что если хоть один пиксел растра не помещается на первичную поверхность, не воспроизводится ничего.