Пропустить навигацию.
Главная

Стандартные прямоугольники

Основной информацией для построения прямоугольников являются целочисленные координаты левого верхнего угла (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. Два стиля "резиновых" прямоугольников