Шаг 42.
Графические инструменты в Delphi. Дополнительные возможности API-функций

    На этом шаге мы рассмотрим некоторые API-функции, применяемые при работе с графикой.

    Класс TCanvas инкапсулирует лишь наиболее популярные приемы работы с чертежными инструментами. В этом разделе перечисляются некоторые функции Windows, которые не инкапсулирует класс TCanvas и которые способны значительно разнообразить текстовый вывод (именно он наиболее обеднен узкими рамками TCanvas).

    Перечислим некоторые функции API.
Таблица 1. Некоторые функции API
Функция Описание
function CreateFont (Font: TLogFont): hFont; Создает новый шрифт на основе данных в параметре Font. Назначение полей структуры TLogFont смотрите после таблицы.
function DrawText (DC: hDC; pText: PChar; var Rect: TRect; Format: UINT): Integer; В прямоугольнике Rect выводит многострочный текст, на который указывает pText. Параметр Format используется для форматирования (смотри таблицу 2).
function ExtTextOut (DC: hDC; X, Y: Integer; Options: Integer; Rect: TRect; pText: PChar; Count: Integer; PX: PInteger): Bool; Выводит текст с нестандартными межсимвольными расстояниями:
  • X, Y - верхняя левая точка текста;
  • Options - параметр, управляющий выводом;
  • Rect - ограничивающий прямоугольник;
  • pText - указатель на строку вывода;
  • Count - количество выводимых символов;
  • PX - указатель на массив целочисленных значений, определяющих межсимвольные расстояния: 1-й параметр - расстояние от 1-го до 2-го символа; 2-й параметр - расстояние от 2-го до 3-го символа и т. д. Если какой-то параметр равен 0, используется умалчиваемое межсимвольное расстояние.
function GetBkColor (DC: hDC): TColor; Возвращает цвет фона.
function GetBkMode (DC: hDC): Integer; Возвращает режим прорисовки фона: Opaque - фон прорисовывается заново при выводе текста; Transparent - фон не прорисовывается.
function GetTextAlign (DC: hDC): Integer; Возвращает выравнивание текста.
function GetTextCharacterExtra (DC: hDC): Integer; Возвращает межсимвольное расстояние.
function SetBkColor (DC: hDC; Color: TColor): TColor; Устанавливает новый цвет фона и возвращает старый, если обращение успешно.
function SetBkMode (DC: hDC; Mode: Integer): Integer; Устанавливает новый режим прорисовки фона и возвращает старый, если операция успешна.
function SetTextAlign (DC: hDC; Flags: Integer): Integer; Устанавливает новое выравнивание текста и возвращает старое, если вызов успешен.
function SetTextCharacterExtra (DC: hDC; CharExtra: Integer): Integer; Устанавливает новое межсимвольное расстояние и возвращает старое, если вызов успешен.

    Отдельные поля структуры TLogFont для функции CreateFontIndirect имеют следующий смысл:

    Приведем пример использования некоторых рассмотренных конструкций. Пусть, например, нужно создать приложение, при выполнении которого на экране появляется следующее изображение:


Рис.1. Внешний вид приложения

    Вот как реализован этот пример:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormPaint(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormPaint(Sender: TObject);
var
   X: Integer;
   LF: TLogFont;
   Fnt: HFont;
const
   Text = 'Лучшая в мире система программирования';
begin
   // Определяем параметры нового шрифта.
   FillChar(LF, SizeOf(LF), 0);
   with LF do
     begin
       lfHeight := 20;
       lfWeight := fw_Normal;
       lfUnderline := 1;
       lfEscapement := 450;
       StrPCopy(lfFaceName, 'Courier New Cyr');
     end;
    with Form1.Canvas do
      begin
       // Создаем шрифт.
       Fnt := CreateFontIndirect(LF);
       // Присваиваем его дескриптор шрифту канвы.
       Font.Handle := Fnt;
       // Выводим текст под углом  +45 градусов.
       TextOut(0, 300, Text);
       X:= TextWidth(Text) ;
       DeleteObject(Fnt); // Удаляем ненужный шрифт.
       // Изменяем параметры шрифта.
       with LF do
         begin
           lfHeight := 90;
           lfEscapement := -900;
           lfWeight := fw_Heavy;
           StrPCopy(LF.lfFaceName, 'Arial Cyr');
         end;
       Fnt:=CreateFontIndirect(LF); // Создаем новый шрифт.
       Font.Handle := Fnt;
       Font.Color := clRed;
       // Выводим снаклоном -90 градусов.
       TextOut(X-10, 10, 'Delphi 6');
       DeleteObject(Fnt); // Удаляем ненужный шрифт.
end;

end;

end.

    Текст этого примера можно взять здесь.

    Параметр Format функции DrawText может содержать один или несколько флагов, перечисленных в таблице 2.
Таблица 2. Возможные значения параметра Format функции DrawText
Параметр Описание
dtBottom Текст прижимается к нижней части области Rect.
dtCalcRect Разрешает динамически изменять размеры области Rect.
dtCenter Текст центрируется по горизонтали.
dtEditControl Функция дублирует свойства отображения многострочного тестового редактора. В частности, таким же способом вычисляется средняя ширина символа и не показывается частично видимая последняя строка.
dtExpandTabs Символы табуляции заменяются пробелами.
dtExternalLeading В высоту строки включается высота межстрочного интервала.
dtLeft Текст прижимается к левой части области Rect.
dtNoClip Текст не отсекается границами Rect.
dtNoPrefix Символы & не заменяются подчеркиванием.
dtRight Текст прижимается к правой части области Rect.
dtSingleLine Весь текст выводится единственной строкой, символы перехода на новую строку игнорируются.
dtTabsStop Символы табуляции не заменяются пробелами.
dtTop Текст прижимается к верхней части области Rect.
dtVCenter Текст центрируется по вертикали.
dtWordBreak Разрешает переход на новую строку при достижении правой границы Rect; разрыв строки - на границе слова; символы перевода строки также переводят вывод на следующую строку.

    Если установлен флаг dtCalcRect, функция изменяет высоту и ширину прямоугольника так, чтобы вывести весь текст, но сам текст не выводится. Если в тексте несколько строк, ширина вывода не меняется. Функция возвращает истинную высоту прямоугольника вывода.

    Параметр Options функции ExtTextOut может быть комбинацией следующих значений:

    При выводе текста стандартными методами TCanvas всегда заново прорисовывается фон символов (цвет фона возвращает функция GetBkColor). Если цвет фона символов отличается от фона канвы, вывод сопровождается неприятными побочными эффектами. Конечно, с помощью функции SetBkColor можно установить цвет формы совпадающим с цветом канвы, однако это не всегда возможно. Ясно, что установить переменный цвет функцией SetBkColor невозможно. Более того, заглавные надписи программ Setup.exe также традиционно выводятся утолщенным наклонным шрифтом Times New Roman белыми буквами с черной тенью. Реализовать такой эффект достаточно просто: нужно вообще отказаться от прорисовки фона, установив с помощью функции SetBkMode режим Transparent, и вывести надпись дважды: первый раз черным цветом, а второй - белым, сместив вторую надпись немного влево и вверх относительно первой:


Рис.2. Внешний вид приложения

    Следующий листинг иллюстрирует сказанное:

procedure TForm1.FormPaint(Sender: TObject);
var
  Y: Integer;
  Blue: Byte;
const
   Text = 'Фон для программы Setup.exe';
begin
   with Form1.Canvas do
   begin
     for Y := 0 to Form1.Height-1 do
     begin
       //Уменьшаем интенсивность цвета с ростом ординаты Y.
       Blue := Round($FF*(Form1.Height-Y)/Form1.Height);
       Pen.Color := RGB(0, 0, Blue); // Формируем цвет.
       MoveTo(0, Y); // Чертим линию.
       LineTo(Form1.Width-1, Y) ;
     end;
     Font.Size := 32;
     Font.Style := [fsBold, fsItalic, fsUnderline];
     Font.Name := 'Times New Roman';
     // Это обращение накладывает текст на фон.
     SetBkMode(Handle, Transparent);
     // Сначала выводим тень надписи.
     Font.Color := clBlack;
     TextOut(40, 30, Text);
     // Теперь саму надпись.
     Font.Color := clWhite;
     TextOut(36, 26, Text);
     end;
end;

    Текст этого примера можно взять здесь.


    Примечание. Любая заливка фона, в том числе его прорисовка, реализуется с помощью кисти. Поэтому отказаться от прорисовки фона текста можно, если установить стиль кисти bsClear. Вместо SetBkMode (Handle, Transparent); можно использовать Brush.Style:=bsClear;.

    На следующем шаге мы рассмотрим такое понятие, как области.




Предыдущий шаг Содержание Следующий шаг