- Машинная графика
- Рисуем? Где? Чем?
- Что позволяет рисовать система VB?
- Работа с отдельными точками
- Отрезки прямых и прямоугольники
- Окружности, эллипсы, дуги и сектора
- Очистка канвы графического объекта
- Что позволяют рисовать системы BCB и Delphi?
- Отрезки прямых и ломаные
- Стандартные прямоугольники
- Нестандартные многоугольники
- Кривые второго порядка
- Обмен с графическими файлами
- Вывод символьных и числовых данных на канве
- Отображение текстовой и числовой информации в VB
- Работа с текстами в BCB и Delphi
- Графические объекты в системе VB
- Графические объекты в системах BCB и Delphi
- Копирование растровых изображений
- Создание монотонно изменяющегося фона
- Формирование регулярных заливок замкнутых областей в BCB
- Формирование регулярных заливок замкнутых областей в Delphi
Стандартные прямоугольники
Опубликовано admin в Сб, 05/08/2010 - 20:45
Основной информацией для построения прямоугольников являются целочисленные координаты левого верхнего угла (x1,y1) и правого нижнего угла (x2,y2). В некоторых методах эти значения должны быть заданы как данные типа TRect, в других допускается явное перечисление всех четырех чисел. Любое нарушение в последовательности задания координат методами построения прямоугольников игнорируется, изображение они не строят, но и никаких сообщений не выдают. Если одна из угловых точек находится за пределами графического объекта, то изображение прямоугольника будет обрезано, и пропадут две его стороны.
С помощью метода FrameRect отображается граница прямоугольника, которая воспроизводится в соответствии с текущими параметрами пера:
TRect r=Rect(10,10,100,200); //BCB
.....................................
Form1->Canvas->FrameRect(r); //BCB
Form1->Canvas->FrameRect(Rect(5,15,50,50)); //BCB
var r:Trect; {Delphi}
.........................................
r:=Rect(10,10,100,200); {Delphi}
Form1.Canvas.FrameRect(r); {Delphi}
Form1.Canvas.FrameRect(Rect(5,15,50,50)); {Delphi}
Метод FillRect позволяет заполнить внутренность прямоугольника r в соответствии с текущими параметрами кисти:
имя_объекта->Canvas->FillRect(r); //BCB
имя_объекта.Canvas.FillRect(r); {Delphi}
Метод Rectangle совмещает в себе обе функции — и строит границу, и заливает внутренность прямоугольника. К этому методу можно обратиться либо с одним аргументом типа TRect, либо с четырьмя целочисленными значениями координатами:
имя_объекта->Canvas->Rectangle(x1,y1,x2,y2); //BCB
имя_объекта->Canvas->Rectangle(r); //BCB
имя_объекта.Canvas.Rectangle(x1,y1,x2,y2); {Delphi}
имя_объекта.Canvas.Rectangle(r); {Delphi}
Прямоугольник со скругленными углами строится с помощью метода RoundRect
имя_объекта->Canvas->RoundRect(x1,y1,x2,y2,w,h);//BCB
имя_объекта.Canvas.RoundRect(x1,y1,x2,y2,w,h); {Delphi}
Дополнительные аргументы определяют ширину (w) и высоту (h) эллипса, четвертушки дуг которого используются для сопряжения смежных сторон. При w=h в сопряжении участвуют соответствующие четверти окружности.
Специальный прямоугольник с пунктирной границей воспроизводится методом DrawFocusRect:
имя_объекта->Canvas->DrawFocusRect(r); //BCB
имя_объекта.Canvas.DrawFocusRect(r); {Delphi}
Название этого метода связано с отображением кнопок, которым передается фокус. Их заголовок обычно окаймляется пунктирным прямоугольником. Пунктирный прямоугольник, динамически отслеживающий перемещение мыши, очень часто используют для выделения прямоугольной области какого-либо изображения. Его обычно называют резиновым прямоугольником. Техника его построения базируется на использовании режима XOR при определении результирующего цвета пиксела. В момент нажатия правой клавиши мыши (событие OnMouseDown) фиксируются координаты одного из углов резинового прямоугольника, а затем отслеживаются координаты курсора во время перемещения мыши с зажатой клавишей (периодически возникающее событие OnMouseMove). Каждый раз в режиме XOR стирается предыдущее изображение пунктирного прямоугольника и строится новое. Процесс прекращается в момент отпускания клавиши мыши (событие OnMouseUp).
Приложение 8_08 (BCB).
Описанная технология реализована в следующем приложении:
int x0,y0,x1,y1;
bool Down=false;
//----------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//----------------------------------------------------------------
void __fastcall TForm1::Image1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
x0=X; StatusBar1->Panels->Items[1]->Text=X;
y0=Y; StatusBar1->Panels->Items[3]->Text=Y;
x1=X; y1=Y;
Down=true;
}
//----------------------------------------------------------------
void __fastcall TForm1::Image1MouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
Down=false;
StatusBar1->Panels->Items[9]->Text = X;
StatusBar1->Panels->Items[11]->Text= Y;
}
//----------------------------------------------------------------
void __fastcall TForm1::Image1MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
TRect r;
if(Down)
{
r.Left =(x0<x1)? x0 : x1;
r.Right =(x0<x1)? x1 : x0;
r.Top =(y0<y1)? y0 : y1;
r.Bottom=(y0<y1)? y1 : y0;
Image1->Canvas->DrawFocusRect(r);
r.Left =(x0<X)? x0 : X;
r.Right =(x0<X)? X : x0;
r.Top= (y0<Y)? y0 : Y;
r.Bottom=(y0<Y)? Y : y0;
Image1->Canvas->DrawFocusRect(r);
x1=X;
y1=Y;
StatusBar1->Panels->Items[5]->Text=X;
StatusBar1->Panels->Items[7]->Text=Y;
}
}
Глобальная переменная Down используется для фиксации состояния — мышь перемешается по канве Image1 с нажатой или не нажатой клавишей. В глобальных переменных (x0,y0) и (x1,y1) хранятся текущие значения левой верхней и правой нижней вершин резинового прямоугольника. При этом для правильного его воспроизведения в x0 всегда заносится минимум из (x0,x1), а в x1 — максимум из (x0,x1). Соответственно, в y0 заносится максимум из (y0,y1), а в y0 — минимум из (y0,y1). Если этого не делать, то прямоугольник будет рисоваться только при движении курсора мыши от начальной точки вниз и вправо.
Так как метод DrawFocusRect автоматически включает режим pmXor, то в программе пользователя дублировать такое переключение не обязательно. Повторное воспроизведение резинового прямоугольника по его прежним координатам уничтожает предшествующее изображение прямоугольника и восстанавливает поверхность канвы, перекрытую прежними границами.
Строка состояния StatusBar1 использована для отображения координат мыши во время действия того или иного события мыши — при нажатии кнопки, при движении с нажатой кнопкой и при ее отпускании. Результат работы приложения приведен на рис. 8.6.

Рис. 8.6. Воспроизведение резинового прямоугольника
Приложение 8_09 (BCB).
Конечно, резиновый прямоугольник можно создать и другими средствами, меняя, например, стиль воспроизведения линий. Однако самый подходящий «точечный» стиль psDot смотрится гораздо хуже — точки больше смахивают на штрихи:
int x0,y0,x1,y1;
bool Down=false;
TRect r;
//--------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------
void __fastcall TForm1::FormActivate(TObject *Sender)
{
Image1->Canvas->Brush->Color=clWhite;
Image2->Canvas->Brush->Color=clWhite;
}
//---------------------------------------------------------------
void __fastcall TForm1::Image1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
x0=X; y0=Y;
x1=X; y1=Y;
Down=true;
}
//---------------------------------------------------------------
void __fastcall TForm1::Image1MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{ if(Down)
{ r.Left=(x0<x1)?x0:x1;
r.Right=(x0<x1)?x1:x0;
r.Top=(y0<y1)?y0:y1;
r.Bottom=(y0<y1)?y1:y0;
Image2->Canvas->MoveTo(r.Left,r.Top);
Image2->Canvas->LineTo(r.Right,r.Top);
Image2->Canvas->LineTo(r.Right,r.Bottom);
Image2->Canvas->LineTo(r.Left,r.Bottom);
Image2->Canvas->LineTo(r.Left,r.Top);
r.Left=(x0<X)?x0:X;
r.Right=(x0<X)?X:x0;
r.Top=(y0<Y)?y0:Y;
r.Bottom=(y0<Y)?Y:y0;
Image2->Canvas->MoveTo(r.Left,r.Top);
Image2->Canvas->LineTo(r.Right,r.Top);
Image2->Canvas->LineTo(r.Right,r.Bottom);
Image2->Canvas->LineTo(r.Left,r.Bottom);
Image2->Canvas->LineTo(r.Left,r.Top);
x1=X;
y1=Y;
}
}
//--------------------------------------------------------------
void __fastcall TForm1::Image1MouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
Down=false;
}
//---------------------------------------------------------------
void __fastcall TForm1::Image2MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
x0=X; y0=Y;
x1=X; y1=Y;
Down=true;
Image2->Canvas->Pen->Style=psDot;
Image2->Canvas->Pen->Mode=pmXor;
}
//---------------------------------------------------------------
void __fastcall TForm1::Image2MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
if(Down)
{ r.Left=(x0<x1)?x0:x1;
r.Right=(x0<x1)?x1:x0;
r.Top=(y0<y1)?y0:y1;
r.Bottom=(y0<y1)?y1:y0;
Image2->Canvas->MoveTo(r.Left,r.Top);
Image2->Canvas->LineTo(r.Right,r.Top);
Image2->Canvas->LineTo(r.Right,r.Bottom);
Image2->Canvas->LineTo(r.Left,r.Bottom);
Image2->Canvas->LineTo(r.Left,r.Top);
r1.Left=(x0<X)?x0:X;
r1.Right=(x0<X)?X:x0;
r1.Top=(y0<Y)?y0:Y;
r1.Bottom=(y0<Y)?Y:y0;
Image2->Canvas->MoveTo(r.Left,r.Top);
Image2->Canvas->LineTo(r.Right,r.Top);
Image2->Canvas->LineTo(r.Right,r.Bottom);
Image2->Canvas->LineTo(r.Left,r.Bottom);
Image2->Canvas->LineTo(r.Left,r.Top);
x1=X; y1=Y;
}
}
//---------------------------------------------------------------
void __fastcall TForm1::Image2MouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
Down=false;
}
В приведенном выше примере на форме находятся два объекта типа TImage. На левом объекте резиновый прямоугольник воспроизводится методом DrawFocusRect, а на правом — путем построения отрезков, состоящих из пунктирных линий. Результат работы такого приложения приведен на рис. 8.7.

Рис. 8.7. Два стиля "резиновых" прямоугольников
