- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
О чём не пишут в книгах по Delphi - А. Григорьев
Шрифт:
Интервал:
Закладка:
1.2.7. Пример GDIDraw
Программа GDIDraw демонстрирует некоторые возможности GDI, которые не поддерживаются классом TCanvas. Выбраны только те возможности, которые поддерживаются не только в Windows NT/2000/XP, но и в 9x/ME. Окно программы показано на рис. 1.11.
В своей работе программа использует рисунок из стандартных картинок Delphi, предполагая, что эти картинки установлены в папку "С:Program FilesCommon FilesBorland SharedImages". Если у вас эти картинки установлены в другую папку, или по каким-то причинам вы хотите выбрать другой рисунок, измените обработчик события OnCreate формы так, чтобы он загружал рисунок из нужного вам файла. Загруженный рисунок сохраняется в поле FBitmap формы.
Рис. 1.11. Окно программы GDIDraw
Основная работа выполняется в обработчике события OnPaint формы. Мы здесь будем разбирать этот обработчик не целиком, а по частям в соответствии с тем, что каждая часть рисует. Начнем с надписи Delphi Kingdom в левом верхнем углу окна (листинг 1.34).
Листинг 1.34. Вывод надписи Delphi Kingdomvar
R: TRect;
...
// Формируем регион, использующийся для отсечения.
// Формируем его только при первом вызове метода, а при
// дальнейших используем созданный ранее. Поле FRgn
// содержит дескриптор этого региона
if FRgn = 0 then
begin
Canvas.Font.Name := 'Times New Roman';
Canvas.Font.Style := [fsBold];
Canvas.Font.Height := 69;
// Начинаем рисование траектории. Все вызовы
// графических функций, находящиеся между BeginPath
// и EndPath, не будут приводить к выводу на экран.
// Вместо этого информация о том, что рисуется, будет
// сохраняться а специальном объекте GDI - траектории.
BeginPath(Canvas.Handle);
R := Rect(10, 10, 10 + FBitmap.Width, 10 + FBitmap.Height);
// Если не установить с помощью SetBkMode прозрачный
// фон, в траекторию попадут не только контуры букв,
// но и контуры содержащих их прямоугольных знакомест.
SetBkMode(Canvas.Handle, TRANSPARENT);
// Выводим текст "Delphi Kingdom", выравнивая его по
// центру по вертикали и горизонтали.
DrawText(Canvas.Handle, 'Delphi'#13#10'Kingdom', -1, R,
DT_CENTER or DT_VCENTER);
EndPath(Canvas.Handle);
// Превращаем траекторию в регион. В результате вызова
// этой функции получится регион, контуры которого
// совпадают с контурами надписи "Delphi Kingdom",
// сделанной в указанных координатах выбранным шрифтом.
FRgn := PathToRegion(Canvas.Handle);
end;
// Устанавливаем регион отсечения. Все, что не будет
// попадать в выбранный регион, при выводе будет
// игнорироваться.
SelectClipRgn(Canvas.Handle, FRgn);
// Выводим изображение. Все, что не попадает в область
// региона, отсекается. Таким образом, получаем надпись
// "Delphi Kingdom", подсвеченную выбранным изображением.
Canvas.Draw(10, 10, FBitmap);
// Отменяем отсечение по региону
SelectClipRgn(Canvas.Handle, 0);
Если присмотреться к надписи, видно, что внутренняя часть контуров букв содержит тот самый рисунок, который был загружен в обработчик OnCreate (как будто мы нарисовали этот рисунок через трафарет, имеющий форму надписи). По сути, так оно и есть, только называется это не трафарет, а регион отсечения. Регион — это специальный объект, который хранит область произвольной формы. Способы применения регионов различны (см. разд. 1.3.3), и один из них — это использование региона для отсечения графического вывода. Если установить регион отсечения для контекста устройства, то, что бы мы ни выводили потом в данный контекст, все, что лежит за пределами региона отсечения, игнорируется.
Соответственно, чтобы сделать такую надпись, нужно создать регион, совпадающий по форме с этой надписью. В GDI есть целый ряд функций для создания регионов различной формы, но вот для создания региона в форме букв функции нет. Зато GDI поддерживает другие объекты — траектории. Строго говоря, это не совсем объекты, траектория не имеет дескриптора (по крайней мере, API не предоставляет этот дескриптор программам), и в каждом контексте устройства может быть только одна траектория. Создание траектории начинается с вызова функции BeginPath, заканчивается вызовом функции EndPath. Графические функции, вызванные между BeginPath и EndPath, не выводят ничего в контекст устройства, а то, что должно быть выведено, вместо этого запоминается в траектории (которая представляет собой совокупность замкнутых кривых). С траекторией можно выполнить много полезных операций (см., например, разд. 1.3.4). В нашем случае между вызовами BeginPath и EndPath мы вызываем DrawText. формируя таким образом траекторию, состоящую из контуров букв. Затем с помощью функции PathToRegion мы создаем регион, границы которого совпадают с контурами траектории, т.е., в данном случае, регион, совпадающий по форме с надписью.
ПримечаниеНа самом деле не все графические функции, вызванные между BeginPath и EndPath, добавляют контуры к траектории. Это зависит от версии операционной системы. Подробнее этот вопрос обсуждается в разд. 1.3.4.
В ходе работы программы регион не меняется, так что нет нужды создавать его каждый раз при обработке события OnPaint. Он создается только один раз, и его дескриптор сохраняется в поле FRgn формы для дальнейшего использования.
Все, что осталось сделать, — это установить регион отсечения с помощью функции SelectClipRgn, отобразить рисунок и убрать регион отсечения, чтобы не мешал в дальнейшем.
Теперь рассмотрим, как рисуются звезды в правом верхнем углу окна (листинг 1.35).
Листинг 1.35. Рисование звездvar
I: Integer;
Star: array[0..4] of TPoint;
...
// Следующая группа команд рисует две звезды справа от
// надписи. Эти звезды демонстрируют использование двух
// режимов заливки: WINDING и ALTERNATE. Для простых
// фигур эти режимы дают одинаковые результаты, разница
// возникает только при закрашивании сложных фигур,
// имеющих самопересечения.
Canvas.Pen.Style := psSolid;
Canvas.Pen.Width := 1;
Canvas.Pen.Color := clRed;
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := clRed;
// Вычисляем координаты вершин звезды. Они помещаются
// в массив Star в следующем порядке (если первой
// считать верхнюю вершину и нумеровать остальные по
// часовой стрелке от нее): 1-3-5-2-4
for I := 0 to 4 do
begin
Star[I].X := Round(380 + 90 * Sin(0.8 * I * Pi));
Star[I].Y := Round(100 - 90 * Cos(0.8 * I * Pi));
end;
// Устанавливаем режим заливки WINDING. При
// использовании этого режима закрашивается все
// содержимое многоугольника независимо от того,
// как именно он нарисован.
SetPolyFillMode(Canvas.Handle, WINDING);
Canvas.Polygon(Star);
// Сдвигаем координаты звезды, чтобы нарисовать ее
// правее с другим режимом заливки.
for I := 0 to 4 do Inc(Star([I].X, 200);
// Устанавливаем режим заливки ALTERNATE. При
// использовании этого режима заполняются горизонтальные
// линии, лежащие между нечетной и четной сторонами
// многоугольника. В результате пятиугольник в центре
// звезды оказывается незаполненным.
SetPolyFillMode(Canvas.Handle, ALTERNATE);
Canvas.Polygon(Star);
Самое интересное здесь то, что обе звезды рисуются практически одинаково, меняется только режим заливки. Сначала с помощью простейшей тригонометрии вычисляются координаты вершин звезды, помещаются в массив Star и эта звезда рисуется с режимом заливки WINDING. При этом закрашиваются все точки, для которых выполняется условие, что луч, выпущенный из этой точки, пересекает контур многоугольника нечетное число раз, т.е. всю внутренность контура. Затем координаты вершин звезды смещаются вправо, и такая же звезда рисуется точно так же, но уже с режимом заливки ALTERNATE. В этом режиме закрашиваются только те точки, которые оказались между четной и нечетной сторонами многоугольника, и пятиугольник внутри звезды остается незакрашенным. Обратите внимание, что звезду мы здесь рисуем с помощью класса TCanvas, и только режимы заливки переключаем API-функциями.
Следующий шаг — это рисование черной прямоугольной рамки на фоне пересекающихся зеленых линий. Линии рисуются до рамки для того, чтобы показать, что центр рамки действительно остается прозрачным, а не заливается цветом фона. Сама рамка рисуется вызовом одной функции PolyPolygon, позволяющей за один раз нарисовать фигуру, ограниченную несколькими замкнутыми многоугольными контурами (листинг 1.36).

