SNK Software
Web Studio Монополия Metaproducts Утилиты Игры
Монополию Web Studio Библиотека
Вебмастер Дельфи Работа на ПК Самоучитель
Для PHP Для Delphi
Веб-дизайн Программирование Компьютеры Девайсы Заметки
SNK Software Индустрия hardware Индустрия software
О студии Портфолио Сопровождение сайтов

Новые материалы

Девайсы:
Сравнительный обзор Nokia Lumia 920 и HTC 8X
Девайсы:
Обзор Nokia Lumia 820 – смартфона на WP8
Вебмастеру:
Настройка Apache, PHP и MySQL для Linux-VPS
Вебмастеру:
VPS на домашнем ПК: настройка сети в VM VirtualBox и Debian
Вебмастеру:
VPS на домашнем ПК: устанавливаем Linux Debian 6
Вебмастеру:
VPS на домашнем ПК: установка VM VirtualBox
Работа на компьютере:
Иные возможности текстового процессора Word
Работа на компьютере:
Вставка объектов
Работа на компьютере:
Таблицы в Word
Работа на компьютере:
Печать и сохранение документов
Работа на компьютере:
Сноски, колонтитулы, оглавление и указатели в Word

Черчение, рисование и печать

Среду Windows не зря называют графической - весь текст, рисунки и элементы управления выводятся в графическом виде. Соответственно весь вывод приложений Windows, в отличие от рассмотренных ранее консольных программ, является графическим по своей природе.

Графика в Windows

Когда приложению требуется вывести какую-либо информацию на экран дисплея, операционная система - Windows - предоставляет ей в свое распоряжение оконно-ориентированную графику. Это означает, что каждая форма (как, впрочем, и ряд других объектов) рассматривается как поверхность для рисования - холст (canvas).

Когда в форме производится построение рисунка, то выводимое изображение обрезается по ее краям, т.е. выводятся только те его части, которые помещаются на холст окна. Такой подход гарантирует, что вывод одного приложения не затронет клиентской области других приложений, на чем, собственно и основывается оконная система Windows.

За точку отсчета координат в окнах принимается левый верхний угол его клиентской области, ограниченной рамкой (т.е. как раз те габариты, что отражаются свойствами ClientHeight и ClientWidth). Для других элементов, имеющих холст для рисования, подобной рамки может и не быть - в таком случае рамками такого виртуального холста выступают границы объекта.

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

Хорошая новость состоит в том, что Delphi имеет целый ряд готовых к использованию компонент, заботиться о рисовании которых разработчику совершенно незачем, поскольку всю рутинную работу уже выполнили разработчики Delphi и VCL. Более того, в VCL есть множество "заготовок", на основании которых можно создавать собственные компоненты, опять-таки без непосредственного обращения к функциям графического вывода.

В то же время, рисование может быть полезным и при более простых ситуациях, например, когда требуется именно вывести какие-либо графические примитивы, или даже дать пользователю возможность что-нибудь начертить. Наконец, мы рассмотрим здесь вопрос рисования, чтобы еще раз проиллюстрировать работу классов и использование ООП, а заодно исследовать еще один фрагмент VCL.

Объект Canvas

Для многих элементов интерфейса в Windows-приложениях используется компоненты, основанные на классе TWinControl, являющегося прямым наследником уже рассмотренного нами класса TControl. Но множество других визуальных компонент происходят от другого его наследника - класса TGraphicControl, являющийся более простым и имеющим такое свойство, как Canvas, при помощи которого можно в буквальном смысле рисовать в Windows. Собственно говоря, свойство Canvas имеется не только у этого класса, но и у ряда других, в том числе и основанных на TWinControl. Впрочем, в любом случае это свойство будет представлено одним и тем же классом - TCanvas.

Объект Canvas инкапсулирует в себе взаимодействие с Windows GDI (Graphic Device Interface - интерфейс графического устройства). GDI обрабатывает весь графический вывод, предназначенный для экрана монитора, а так же для принтеров и иных печатающих устройств. Но поскольку взаимодействие с GDI, как, впрочем, и с другими подсистемами Windows API напрямую - дело хлопотное и чреватое ошибками, то в Delphi и был предусмотрен класс TCanvas, предоставляющий сравнительно простой и удобный доступ к GDI.

Сам по себе холст (Canvas) представляет собой поверхность, на которую можно выводить текст и иные графические изображения - линии, прямоугольники, эллипсы и т.д. Но при ближайшем рассмотрении можно увидеть, что этот холст представляет собой плоскость, состоящую из отдельных точек - пикселей. Пиксель - это базовый элемент графического ввода, представляющий собой отдельную точку. Фактически, при рисовании на холсте вы просто закрашиваете его отдельные точки тем или иным цветом. Но, разумеется, работая с холстом посредством методов, предоставляемых классом TCanvas, можно без лишних хлопот выводить не только точки, но и текст, линии, прямоугольники, многоугольники, окружности, и даже готовые изображения. Рассмотрим основные свойства и методы объекта Canvas, обратившись к таблице 9.1.

Таблица 9.1. Свойства и методы TCanvas
Свойство (метод)Тип значений или параметрыОписание
PixelsМатрица TColorПредоставляет доступ к любому пикселю холста, чтобы узнать или изменить его цвет
PenTPenСвойства пера для черчения линий
BrushTBrushСвойства кисти для заполнения внутренних областей фигур
FontTFontСвойства шрифта для вывода текста
MoveToX, Y: IntegerУстанавливает текущую позицию пера
LineToX, Y: IntegerПроводит линию от текущей позиции к указанной
TextOutX, Y: Integer; const Text: stringВыводит заданный текст, начиная с указанных координат
RectangleX1, Y1, X2, Y2: Integer или Rect: TRectРисует прямоугольник указанных размеров. Цвет рамки определяется текущим значением свойства Pen, а цвет заливки – свойством Brush
EllipseX1, Y1, X2, Y2: Integer или Rect: TRectРисует эллипс, вписанных в прямоугольник указанных размеров. Цвет рамки определяется текущим значением свойства Pen, а цвет заливки – свойством Brush
PolygonPoints: array of TPointРисует многоугольник по указанным вершинам
PolyLinePoints: array of TPointРисует ломаную линию, соединяющую указанные точки
DrawX, Y: Integer; Graphic: TGraphicВыводит графическое изображение, начиная от указанных координат (левого верхнего угла)

Рассмотрим некоторые свойства более подробно. Начнем с Pixels. Это свойство, представляющее собой двумерный массив, содержит информацию о цвете каждой точки поверхности, описывая, таким образом, всю поверхность холста. Изменяя цвет той или иной точки, мы можем выводить изображения. Например, если нам надо изменить цвет точки в левом верхнем углу, мы можем написать такое выражение:

Canvas.Pixels[1,1]:=clRed;

Здесь мы обратились к 1-му элементу 1-го ряда массива, которой как раз и соответствует левому верхнему углу холста, и назначили ему значение clRed, т.е. установили красный цвет.

Поскольку с использованием различных методов объекта Canvas можно выводить не только точки, но и различные фигуры, а так же текст, то остальные свойства как раз позволяют настроить параметры вывода этих фигур и текста. Так, для текста используется свойство Font, являющееся, в свою очередь, классом TFont и имеющим такие свойства, как Color (цвет), Name (гарнитура шрифта), Size (размер) и Style (стиль). Последнее свойство имеет 4 флага, позволяющих сделать шрифт полужирным, наклонным, подчеркнутым или зачеркнутым:

Canvas.Font.Color:=clBlue; //шрифт будет синего цвета Canvas.Font.Name:='Arial'; //выбрана гарнитура Arial Canvas.Font.Size:=12; //установлен размер шрифта в 12pt Canvas.Font.Style:=[fsBold,fsItalic]; //шрифт будет полужирным наклонным

Что касается таких свойств холста, как Pen и Brush, то для них предусмотрено изменение цвета и стиля линии (для Pen) или заполнения (для Brush). Кроме того, для пера можно определить ширину линии и режим наложения цвета. Соответственно, мы имеем следующие свойства:

Следует учитывать, что изменить стиль линии возможно только в том случае, если ее толщина установлена в 1 пиксель (что, впрочем, является значением по умолчанию). При любом другом значении толщины линия всегда будет сплошной - psSolid.

Черчение фигур

Чтобы лучше представить себе использование объекта Canvas, попробуем использовать его свойства и методы для рисования фигур. Для начала попробуем вывести простую линию на поверхность формы, для чего создадим новое приложение, щелкнем по автоматически созданной форме (Form1), после чего перейдем в окно инспектора объекта и на закладке Events дважды щелкнем по строке напротив надписи OnClick. В ответ на это Delphi создаст обработчик события FormClick в редакторе кода:

procedure TForm1.FormClick(Sender: TObject); begin end;

Теперь остается поместить в него код, рисующий линию. Поскольку у формы уже имеется свойство Canvas, то будет достаточно просто обратиться к его методам MoveTo и LineTo. Пусть линия начнется в точке со смещением в 10 пикселей от левого верхнего угла по вертикали и горизонтали, и продлится до точки в 200 пикселей по горизонтали. В результате код получится следующим:

procedure TForm1.FormClick(Sender: TObject); begin Form1.Canvas.MoveTo(10,10); Form1.Canvas.LineTo(200,10); end;

Теперь остается запустить приложение и щелкнуть по любому мету на форме. Результатом будет вывод тонкой горизонтальной линии. Добавив к коду процедуры вызов метода Ellipse, мы получим построение эллипса, а Rectangle - прямоугольника:

Form1.Canvas.Ellipse(30,30,150,150); Form1.Canvas.Rectangle(230,30,350,150);

Здесь в обоих случаях мы построили правильные фигуры, т.е. окружность и квадрат. Но поскольку для класса TCanvas не определены методы, строящие именно эти фигуры, то мы использовали методы для построения эллипса и прямоугольника, рассматривая окружность и квадрат как частные случаи этих типов фигур. В то же время, при необходимости можно было бы создать собственные методы, добавив их к классу TCanvas. Сделать это, на самом деле, несложно: достаточно определить новый класс, являющийся наследником TCanvas, и определить для него 2 новых метода. Назовем такой класс TMyCanvas, а методы - Circle и Square:

TMyCanvas = class(TCanvas) procedure Circle(Rad, X, Y: integer); procedure Square(Size, X, Y: integer); end;

Определение этого класса следует поместить в части interface, непосредственно после определения класса TForm1, которое уже размещено в модуле самой Delphi. В части же implementation мы определим сами эти функции:

procedure TMyCanvas.Circle(Rad, X, Y: integer); begin end; procedure TMyCanvas.Square(Size, X, Y: integer); begin end;

Теперь остается написать код, выполняющий построение фигур. Для начала примем, тот факт, что для метода Circle параметр Rad означает радиус окружности, а параметры X и Y - ее центр. Таким образом, мы можем использовать унаследованный метод Ellipse, подставив нужные параметры в его вызов:

Ellipse(X-Rad, Y-Rad, X+Rad, Y+Rad);

Что касается метода Square, то его параметр Size будет означать размер стороны квадрата, а X и Y - координаты верхнего левого угла. Таким образом, можно использовать метод Rectangle, указав для него соответствующие параметры:

Rectangle(X, Y, X+Size, Y+Size);

Теперь, когда методы определены и новый класс готов, следует разобраться с тем, как его использовать. Прежде всего, нам понадобится определить переменную - экземпляр класса. Кроме того, нам понадобится создать ее, использовав конструктор Create. Ну и, наконец, используя свойство Handle (указатель), мы должны связать наш объект с холстом формы. Все это можно разместить во все том же методе обработки щелчка мышкой.

procedure TForm1.FormClick(Sender: TObject); var MC: TMyCanvas; begin MC:=TMyCanvas.Create; // используем конструктор родительского класса MC.Handle:=Canvas.Handle; // назначаем холст окна областью вывода MC.Circle(50,200,100); // рисуем окружность диаметром 50 пикселей MC.Square(50,100,100); // рисуем квадрат со сторонами 50 пикселей MC.Free; end;

Разумеется, все методы, доставшиеся классу TMyCanvas в наследство от TCanvas, так же можно использовать, включая те же Create и Free, чем мы и воспользовались. Применительно к остальным свойствам и методам можно делать то же самое, например, установить толщину и цвет линии, вывести линию при помощи MoveTo и т.д.:

MC.Pen.Width:=3; MC.Pen.Color:=clRed; MC.MoveTo(10,10); MC.LineTo(200,10); MC.Brush.Style:=bsHorizontal;

Таким образом, можно оформить вывод фигур, при помощи заполнения, штриховкой, а линию сделать толще и изменить ее цвет (рис. 9.1).

Вывод графики на холст окна в Delphi
Рис. 9.1. Вывод графики на холст окна

Законченный код программы можно найти в каталоге Demo\Part2\Canvas. В нем же приведен еще один вариант использования метода Circle - для создания кольца из окружностей.

Вывод на печать

Вывод текста и графики возможен не только на дисплей, но и на принтер. Для этого так же используется свойство Canvas, но только не формы, а специального объекта Printer. Чтобы задействовать этот объект, необходимо подключить к программе модуль printers, указав его в списке используемых модулей, т.е. в uses. При этом не требуется ни создавать экземпляр класса TPrinter, ни заботиться о его удалении - достаточно просто использовать переменную Printer, которая создается для программы автоматически, если указан модуль Printers.

Помимо свойства Canvas, объект Printer имеет ряд иных свойств и методов, необходимых для осуществления печати. Среди методов этого объекта следует отметить, прежде всего, BeginDoc и EndDoc. Эти методы используются, соответственно, для начала и окончания процесса печати. Отметим так же метод NewPage, используемый для обозначения начала новой страницы, а так же метод Abort, прерывающий процесс печати. Что касается свойств, то они приведены в таблице 9.2.

Таблица 9.2. Свойства класса TPrinter
СвойствоТипОписание
AbortedBooleanУказывает, остановлена или нет печать пользователем
CanvasTCanvasПредставляет холст листа
CopiesIntegerОпределяет число копий для печати
OrientationTPrinterOrientationОпределяет формат расположения бумаги – портретный (poPortrait), или ландшафтный (poLandscape)
PageHeightIntegerУказывает на высоту страницы в пикселях
PageNumberIntegerУказывает на текущую печатаемую страницу
PageWidthIntegerУказывает на ширину страницы в пикселях
PrintingBooleanУказывает, выполняется или нет печать в данный момент
TitleStringОпределяет текст, идентифицирующий задание печати в менеджере принтеров Windows

Прежде, чем что-либо выводить не печать, необходимо проделать подготовительную работу. Это вызвано рядом причин, в частности, тем, что принтер не может печатать под обрез - следовательно, надо определить поля. Кроме того, у разных принтеров различное выходное разрешение, которое зависит как от модели, так и от настроек качества печати. В случае вывода текста так же следует определиться с количеством строк, помещающихся на странице. Тем не менее, в простейшем случае для вывода на печать бывает достаточно просто открыть документ для печати при помощи метода BeginDoc и назначить свойству Canvas принтера необходимое содержимое:

Printer.BeginDoc; Printer.Canvas.TextOut(150, 150, 'Текст для печати'); Printer.EndDoc;

Однако если текст окажется слишком длинным, то он не перенесется на следующую строку, а просто не будет напечатан. Поэтому для вывода достаточно большого по объему текста, все-таки придется заниматься расчетами и готовить строки к выводу.

В то же время, если надо вывести только текст, причем его оформление не принципиально, то можно воспользоваться стандартной процедурой writeln, указав для нее вывод на принтер. Делается это при помощи процедуры AssignPrn:

var F: TextFile; ... AssignPrn(F); Rewrite(F); writeln(F,'Текст для печати.'); CloseFile(F);

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

Чтобы посмотреть, как работают оба этих метода, можно обратиться к примеру, находящемуся в каталоге Demo\Part2\Print.

Но вернемся к графическому выводу на принтер. Как уже было отмечено, для начала следует определиться с областью, доступной для печати и с ее размерами в пикселях. Для удобства бывает полезным определить переменные, отвечающие за размер полей с каждой из сторон документа. В случае вывода строк текса так же необходима переменная, определяющая положение ввода текущей строки. Что касается предмета для вывода, то попробуем нарисовать рамку для всей страницы, проходящую по ее полям, а так же текст разного размера и начертания, и какую-либо еще геометрическую фигуру. Все это мы можем разместить в функции, которую назовем PrintAny (см. листинг 9.1).

Листинг 9.1. Печать текста и графики

procedure PrintAny; var LMargin, RMargin, TMargin, BMargin: integer; fH, HPos: integer; begin with Printer, Printer.Canvas do begin LMargin:=PageWidth div 10; // поле слева 10% от ширины страницы RMargin:=PageWidth div 20; // поле справа 5% от ширины страницы TMargin:=PageHeight div 20; // поле сверху 5% от высоты страницы BMargin:=PageHeight div 10; // поле снизу 10% от высоты страницы Title:='Пробная печать'; // заголовок печати BeginDoc; Pen.Width:=3; Rectangle(LMargin,TMargin,PageWidth-RMargin,PageHeight-BMargin); // рамка Font.Name:='Arial'; Font.Style:=[fsBold,fsUnderline]; Font.Size:=24; fH:=abs(Font.Height); // получаем высоту шрифта HPos:=TMargin+fH; // вычисляем отступ сверху для вывода текста TextOut(LMargin,Hpos,' Заголовок '); Font.Style:=[]; Font.Size:=10; fH:=abs(Font.Height); HPos:=HPos+TMargin+fh; // вновь вычисляем отступ для дальнейшего вывода TextOut(LMargin,Hpos,' Текст абзаца.'); Ellipse(LMargin*2,Hpos+LMargin,LMargin*4,Hpos+LMargin*3); // рисуем круг EndDoc; end; // конец width end; // конец процедуры PrintAny

Здесь сначала были определены поля, затем по этим полям был начерчен прямоугольник, образующий рамку страницы, после чего крупным полужирным и подчеркнутым шрифтом выведено слово "Заголовок", а под ним, уже обычным и более мелким текстом - фраза "Текст абзаца". После этого был выведен круг радиусом, равным ширине левого поля. Таким образом, на один документ были введены как собственно графические объекты, так и текстовые строки, которые, впрочем, в данном случае рассматриваются тоже как графические объекты.

Пример работы этой функции можно посмотреть в программе AnyPrint, которая расположена в каталоге Demo\Part2\Print2.

Избранное

SNK GSCP
SNK GSCP - новая библиотека для PHP 5!
Web Studio
Web Studio и Visual Workshop
Библиотека:
Стандарты на web-технологии
Монополия
Монополия Android
Загрузки:
скачать программы
Продукция:
программы и книги
Техподдержка / Связаться с нами
Copyright © 1999-2020 SNK. Все права защищены.
При использовании материалов с сайта ссылка на источник обязательна.
Рейтинг@Mail.ru