У канвы имеется свойство Pen — перо. Это объект, в свою очередь имеющий ряд свойств. Одно из них уже известное вам свойство Color — цвет, которым наносится рисунок. Второе свойство — Width (ширина линии). Ширина задается в пикселях. По умолчанию ширина равна 1.
Свойство Style определяет вид линии. Это свойство может принимать следующие значения:
psSolid
Сплошная линия
psDash
Штриховая линия
psDot
Пунктирная линия
psDashDot
Штрих-пунктирная линия
psDashDotDot
Линия, чередующая штрих и два пунктира
psClear
Отсутствие линии
psInsideFrame
Сплошная линия, но при Width > 1 допускающая цвета, отличные от палитры Windows
Все стили со штрихами и пунктирами доступны только при Width = 1. В противном случае линии этих стилей рисуются как сплошные.
Стиль psInsideFrame — единственный, который допускает произвольные цвета. Цвет линии при остальных стилях округляется до ближайшего из палитры Windows.
У канвы имеется свойство PenPos. Это свойство определяет в координатах канвы текущую позицию пера. Перемещение пера без прорисовки линии, т.е. изменение PenPos, производится методом канвы MoveTo(X,Y). Здесь (X,Y) — координаты точки, в которую перемещается перо. Эта текущая точка становится исходной, от которой методом LineTo(X,Y) можно провести линию в точку с координатами (X,Y). При этом текущая точка перемещается в конечную точку линии и новый вызов LineTo будет проводить точку из этой новой текущей точки.
Давайте попробуем нарисовать пером график синуса из предыдущего примера. Откройте прежний проект, добавьте на него еще один компонент Image и разместите компоненты так, как показано выше на рис. 5.8. Размеры обоих компонентов Image должны быть абсолютно одинаковы, так как на этом для экономии размера кода и вашего труда основана программа, которую мы напишем. Сделать размеры компонентов абсолютно одинаковыми легко, выделив их оба и воспользовавшись командой всплывающего меню Size.
Затем в уже написанном вами обработчике щелчка на кнопке добавьте перед началом цикла оператор
Image2->Canvas->MoveTo(0,Image2->Height / 2);
который переводит перо в начало координат второго графика — на левый край канвы в середину ее высоты. А в конце цикла добавьте оператор
Image2->Canvas->LineTo(PX, PY) ;
который рисует на втором графике линию, соединяющую соседние точки. Иначе говоря, теперь ваш код должен иметь вид:
#define Pi 3.14159
float X,Y; // координаты функции
int PX,PY; // координаты пикселей
Image2->Canvas->MoveTo(0,Image2->Height / 2);
for (PX = 0; PX <= Imagel->Width; PX++)
{
//X — координата, соответствующая пикселю с координатой PX
X = PX * 4 * Pi / Imagel->Width;
Y = sin(X);
//PY — координата пикселя, соответствующая координате Y
PY = Imagel->Height — (Y+l) * Imagel->Height / 2;
//Устанавливается черный цвет выбранного пикселя
Imagel->Canvas->Pixels[PX][PY] = clBlack;
//Проводится линия на второй графике
Image2->Canvas->LineTo(PX,PY);
}
Для экономии кода мы воспользовались тем, что оба графика у нас абсолютно одинакового размера и, следовательно, пересчет координат достаточно провести для одного из них, а потом воспользоваться этими координатами для рисования обоих графиков.
Откомпилируйте приложение и выполните его. Легко видеть, что качество двух одинаковых графиков сильно различается. В левом на крутых участках сплошной линии нет — она распадается на отдельные точки — пиксели. А правый график весь сплошной. Это показывает, что при прочих равных условиях рисовать лучше не по пикселям, а пером.
Отметим еще одно ценное свойство компонента Image и его канвы. Вы можете задавать координаты пикселей, выходящие за пределы размеров канвы, и ничего страшного при этом не случится. Это позволяет не заботиться о том, какая часть рисунка попадает в рамку Image, а какая нет. Вы можете легко проверить это, увеличив, например, вдвое размах вашей синусоиды. Для этого достаточно изменить оператор, задающий значение Y, на следующий:
Y = 2 * sin(X);
Изобразилась только та часть рисунка, которая помещается в рамку канвы. Это позволяет легко осуществлять приложения, в которых пользователю предоставляется возможность увеличивать и просматривать в деталях какие-то фрагменты графиков.
Перо может рисовать не только прямые линии, но и фигуры. Ниже перечислены некоторые из методов канвы, использующие перо для рисования фигур:
Arc
Рисует дугу окружности или эллипса
Chord
Рисует замкнутую фигуру, ограниченную дугой окружности или эллипса и хордой
Ellipse
Рисует окружность или эллипс
Pie
Рисует сектор окружности или эллипса
Polygon
Рисует замкнутую фигуру с кусочно- линейной границей
Polyline
Рисует кусочно-линейную кривую
Rectangle
Рисует прямоугольник
RoundRect
Рисует прямоугольник со скругленными углами
Ниже приведен текст процедуры, которая рисовала фигуры.
Этот текст поможет вам понять методы, осуществляющие рисование фигур.
lmagel->Canvas->Font->Style < fsBold;
Imagel->Canvas->Arc(10,10, 90, 90,90,50,10,50);
Imagel->Canvas->TextOut(40,60,»Arc») ;
Imagel->Canvas->Chord(110,10,190,90,190, 50,110, 50);
Imagel->Canvas->TextOut(135, 60, «Chord» );
Imagel->Canvas->Ellipse(210, 10,290, 50);
Imagel->Canvas->TextOut(230,60,»Ellipse»);
Imagel->Canvas->Pie(310,10,390,90,390,30,310,30);
Imagel->Canvas->TextOut(340,60,»Pie»);
TPoint points[5];
points[0] = Point (30,150);
points[1] = Point (40,130);
points[2] = Point (50,140);
points [3] = Point (60,130);
points[4] = Point (70,150);
Imagel->Canvas->Polygon(points,4);
Imagel->Canvas->TextOut(30,170,»Polygon»);
points[0].x += 100;
points[1].x += 100;
points[2].x += 100;
points[3].x += 100;
points[4].x += 100;
Imagel->Canvas->Polyline(points,4);
Imagel->Canvas->TextOut(130,170,»Polyline»);
Imagel->Canvas->Rectangle(230,120, 280, 160);
Imagel->Canvas->TextOut(230,170,»Rectangle»);
Imagel->Canvas->RoundRect(330,120, 380, 160,20,20);
Imagel->Canvas->TextOut(325,170,»RoundRect»);
Проглядите этот текст. Подобный пример вы можете увидеть на прилагаемом к книге диске. Там вы можете не только просмотреть текст, но и поменять параметры методов, чтобы лучше понять, как они работают.
Для вывода текста на канву в приведенном примере использован метод TextOut, синтаксис которого:
void _fastcall TextOut(int X, int Y, const System::AnsiString Text);
Имеется еще несколько методов вывода текста, которые применяются реже. Все методы вывода текста используют свойство канвы Font — шрифт, с которым вы уже знакомы. В частности, в приведенном примере с помощью этого свойства установлен жирный шрифт надписей.
