СДЕЛАЙТЕ СВОИ УРОКИ ЕЩЁ ЭФФЕКТИВНЕЕ, А ЖИЗНЬ СВОБОДНЕЕ

Благодаря готовым учебным материалам для работы в классе и дистанционно

Скидки до 50 % на комплекты
только до

Готовые ключевые этапы урока всегда будут у вас под рукой

Организационный момент

Проверка знаний

Объяснение материала

Закрепление изученного

Итоги урока

Финальный проект

Категория: Информатика

Нажмите, чтобы узнать подробности

Просмотр содержимого документа
«Финальный проект»

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


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


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


Абстрактный класс Figure

Приведем код класса:


using System;

using System.Drawing; namespace Shapes

{

///

/// Figure - это абстрактный класс; прародитель семейства

/// классов геометрических фигур. Все фигуры имеют:

/// центр - center, масштаб - scale. статус

/// перетаскивания - dragged center - объект встроенного

/// класса (структуры) Point. Этот объект задает характерную

/// точку фигуры - чаще всего ее центр (тяжести)

/// scale задает масштаб фигуры, первоначально единичный.

/// drugged = true, когда фигура следует за курсором мыши.

/// над фигурами определены операции: параллельный

/// перенос - Move(a,b) масштабирование - Scale(s)

/// Показ фигуры - Show. Область захвата - Region_Capture

/// возвращает прямоугольник, характерный для фигуры,

/// перетаскивание фигуры возможно при установке курсора

/// мыши в области захвата.

///

abstract public class Figure

{

///

/// закрытые для клиентов атрибуты класса - center, scale

/// protected Point center;

protected double scale ; protected bool dragged; protected Color color;

//Доступ к свойствам

public Point center_figure

{

get{return(center);} get {center = value;}

}

public double scale_figure

{

get{return(scale);} get {scale = value;}

}

public bool dragged_figure

{

get{return(dragged);} get {dragged = value;}

}

public Color color_figure

{

get{return(color);} set {color = value;}

}

///

/// базовый конструктор фигур

///

/// координата X характерной точки

///фигуры

/// Координата Y характерной точки

///фигуры

public Figure(int x, int y)

{

center = new Point(x,y); scale = 1;

dragged = false;

color = Color.ForestGreen;

}

///

/// отложенный метод

/// Параллельный перенос фигуры на (a,b)

/// require : true;

/// ensure : для любой точки фигуры p(x,y):

/// x = old(x) +a; y = old(y) + b;

///

/// a - перемещение по горизонтали

///вправо

/// b - перемещение по вертикали

///вниз

/// Замечание: Для того, чтобы фигура при рисовании была

/// полностью видимой, координаты всех ее точек должны

/// быть в пределах области рисования. public void Move (int a,int b)

{

center.X +=a; center.Y += b;

}

///

/// изменяет масштаб фигуры

///

/// name="s"масштаб изменяется в s раз public void Scale(double s)

{

scale*=s;

}

///

/// рисование фигуры в окне, передающем объекты g и pen

///

/// графический объект, методы которого

/// рисуют фигуру

/// перо рисования public abstract void Show(Graphics g, Pen pen,

Brush brush);

public abstract System.Drawing.Rectangle Region_Capture();

}


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


Классы семейства геометрических фигур

Приведем теперь программные коды классов, являющихся потомками класса Figure.


Класс Ellipse


Вот программный код этого класса:


using System;

using System.Drawing; namespace Shapes

{

///

/// Класс Ellipse - потомок класса Figure.

///

public class Ellipse: Figure

{

int axisA,axisB;

Rectangle rect;

public Ellipse(int A, int B, int x, int y ): base(x,y)

{

axisA = A; axisB = B; rect =Init();

}

public override void Show(Graphics g, Pen pen, Brush brush)

{

rect = Init(); g.DrawEllipse(pen,rect); g.FillEllipse(brush, rect);

}

public override Rectangle Region_Capture()

{

rect = Init(); return rect;

}

Rectangle Init()

{

int a =Convert.ToInt32(axisA*scale); int b =Convert.ToInt32(axisB*scale); int leftupX = center.X - a;

int leftupY = center.Y - b;

return( new Rectangle(leftupX,leftupY,2*a,2*b));

}

}

}


Класс Circle

Этот класс является потомком класса Ellipse: using System;

using System.Drawing; namespace Shapes

{

///

/// Класс Circle - потомок класса Ellipse.

///

public class Circle: Ellipse

{

public Circle( int radius,int x, int y):base(radius,radius,x,y)

{

//Круг - это эллипс с равными полуосями (радиусом круга)

}

}

}


Здесь опять-таки проявляется мощь наследования. Потомок наследует все свойства и методы родителя. Ему остается только указать собственный конструктор объектов класса, да и в нем главное состоит в вызове конструктора родительского класса с передачей ему нужных аргументов.


Класс LittleCircle


Этот класс, задающие маленькие кружочки фиксированного радиуса, в свою очередь, является наследником класса Circle. Устроен он также чрезвычайно просто:


using System; namespace Shapes

{

///

/// Класс LittleCircle - потомок класса Circle.

///

public class LittleCircle:Circle

{

public LittleCircle(int x,int y): base(4,x,y)

{

// маленький круг радиуса 4

}

}

}


Класс Rect

Этот класс является еще одним прямым потомком класса Figure: using System;

using System.Drawing; namespace Shapes

{

///

/// Класс Rect - потомок класса Figure.

///

public class Rect:Figure

{

int sideA, sideB;

Rectangle rect;

public Rect(int sideA,int sideB, int x, int y): base(x,y)

{

this.sideA = sideA; this.sideB = sideB; rect =Init();

}

public override void Show(Graphics g, Pen pen, Brush brush)

{

rect = Init(); g.DrawRectangle(pen,rect); g.FillRectangle(brush,rect);

}

public override Rectangle Region_Capture()

{

rect = Init(); return rect;

}

Rectangle Init()

{

int a =Convert.ToInt32(sideA*scale); int b =Convert.ToInt32(sideB*scale); int leftupX = center.X - a/2;

int leftupY = center.Y - b/2;

return( new Rectangle(leftupX,leftupY,a,b));

}

}

}


Класс Square


Квадрат - это частный случай прямоугольника. Соответствующий класс является потомком класса Rect:


using System; namespace Shapes

{

///

/// Класс Square - потомок класса Rect.

///

public class Square:Rect

{

public Square(int side, int x, int y): base(side,side,x,y)

{

//квадрат - это прямоугольник с равными сторонами

}

}

}


Класс Person


Этот класс является прямым потомком класса Figure. Вместе с тем, класс является клиентом трех других классов семейства - Circle, Rect и LittleCircle, поскольку элементы фигуры, составляющие человечка, являются объектами этих классов%


namespace Shapes

{

///

/// Класс Person - потомок класса Figure,

/// клиент классов Circle, Rect, LittleCircle.

///

public class Person:Figure

{

int head_h;

Circle head;

Rect body;

LittleCircle nose;

public Person(int head_h, int x, int y): base(x,y)

{

//head_h - радиус головы, x,y - ее центр.

//остальные размеры исчисляются относительно

//размера головы. this.head_h = head_h;

head = new Circle(head_h,x,y); int body_x = x;

int body_y = y + 3*head_h;

int body_w =2*head_h; int body_h = 4*head_h;

body = new Rect(body_w, body_h, body_x,body_y); nose = new LittleCircle(x+head_h +2, y);

}

public override void Show(System.Drawing.Graphics g, System.Drawing.Pen pen, System.Drawing.Brush brush)

{

int h = Convert.ToInt32(head_h*scale);

//head

int top_x = center.X - h; int top_y = center.Y - h;

g.DrawEllipse(pen, top_x,top_y, 2*h,2*h); g.FillEllipse(brush, top_x,top_y, 2*h,2*h);

//body

top_y += 2*h;

g.DrawRectangle(pen, top_x,top_y, 2*h,4*h); g.FillRectangle(brush, top_x,top_y, 2*h,4*h);

//nose top_y -=h;

top_x += 2*h;

g.DrawEllipse(pen, top_x,top_y, 8,8);

g.FillEllipse(brush, top_x,top_y, 8,8);

}

public override System.Drawing.Rectangle Region_Capture()

{

int h = Convert.ToInt32(head_h*scale); int top_x = center.X - h;

int top_y = center.Y - h; return new

System.Drawing.Rectangle(top_x,top_y,2*h,2*h);

}

}

}


Список с курсором. Динамические структуры данных

Добавим в проект классы, задающие динамические структуры данных. Конечно, можно было бы воспользоваться стандартными... Но для обучения крайне полезно уметь создавать собственные классы, задающие такие структуры данных. Список с курсором - один из важнейших образцов подобных классов%:


using System; namespace Shapes

{

///

/// Класс TwoWayList(G) описывает двусвязный список с

/// курсором. Элементами списка являются объекты

/// TwoLinkable, хранящие, помимо указателей на двух

/// преемников, объекты типа G.Курсор будет определять /// текущий

(активный) элемент списка. Класс будет

/// определять симметричные операции по отношению к

/// курсору.

/// Конструкторы:

/// Конструктор без параметров будет создавать пустой

/// список

/// Запросы:

/// empty: require: true; возвращает true для

/// непустого списка item: require: not empty();

/// возвращает активный элемент типа G; count:

/// require: true; возвращает число элементов списка;

/// count in[0,n]

/// (count == 0) eqviv empty();

/// index: require: not empty(); возвращает индекс

/// активного элемента.

/// search_res: require: true; возвращает true,

/// если последний поиск был успешным.

/// Команды:

/// put_left(elem): require: true;

/// ensure: добавить новый элемент (elem) слева от курсора;

/// put_right(elem): require: true;

/// ensure: добавить новый элемент (elem) справа от

/// курсора;

/// remove: require: not empty();

/// ensure: удалить активный элемент;

/// особо обрабатывается удаление последнего и

/// единственного элементов

/// операции с курсором:

/// start: require: true;

/// ensure: сделать активным первый элемент;

/// finish: require: true;

/// ensure: сделать активным последний элемент;

/// go_prev: require: not (index = 1);

/// ensure: сделать активным предыдущий элемент;

/// go_next: require: not (index = count);

/// ensure: сделать активным последующий элемент;

/// go_i(i): require: (i in [1, count]);

/// ensure: сделать активным элемент с индексом i;

/// операции поиска:

/// search_prev(elem): require: not (index = 1);

/// ensure: сделать активным первый элемент elem

/// слева от курсора;

/// Успех или неуспех поиска сохранять в булевской

/// переменной search_res

/// search_next: require: not (index = count);

/// ensure: сделать активным первый элемент elem

/// справа от курсора;

/// успех или неуспех поиска сохранять в булевской

/// переменной search_res

///

public class TwoWayList

{

public TwoWayList()

{

first = cursor = last = null; count = index = 0;

search_res = false;

}//конструктор

///

/// first, cursor, last - ссылки на первый,

/// активный и последний элементы списка

/// Запросы count, index search_res также

/// реализуются атрибутами.

/// Запросы empty, item реализуются функциями

///

protected TwoLinkable first, cursor, last; protected int count, index;

protected bool search_res;

//доступ на чтение к закрытым свойствам; public int Count

{

get

{

return(count);

}

}

public int Index

{

get

{

return(index);

}

}

public bool Search_res

{

get

{

return(search_res);

}

}

///

/// require: true; возвращает true для непустого списка

///

/// public bool empty()

{

return(first == null);

}//empty

///

/// require: not empty(); возвращает активный

/// элемент типа G;

///

/// public Figure item()

{

return(cursor.Item);

}//item

///

/// require: true;

/// ensure: добавить новый элемент (elem) слева

/// от курсора;

///

/// Тип Figure играет роль

/// родового типа G

/// хранимого элемента elem public void put_left(Figure elem)

{

TwoLinkable newitem = new TwoLinkable(); newitem.Item = elem;

newitem.Next = cursor;

if (empty()) //список пуст

{

first = cursor = last = newitem; index =1; count = 1;

}

else

{

if (index == 1) first =newitem;

else

cursor.Prev.Next = newitem;

newitem.Prev = cursor.Prev; cursor.Prev = newitem; count++; index++;

}

}//put_right

///

/// require: true;

/// ensure: добавить новый элемент (elem) справа

/// от курсора;

///

/// Тип Figure играет роль

/// родового типа G

/// хранимого элемента elem public void put_right(Figure elem)

{

TwoLinkable newitem = new TwoLinkable(); newitem.Item = elem;

newitem.Prev = cursor;

if (empty()) //список пуст

{

first = cursor = last = newitem; index =1; count = 1;

}

else

{

if (index == count) last =newitem;

else

cursor.Next.Prev = newitem;


newitem.Next = cursor.Next; cursor.Next = newitem; count++;

}

}//put_right

public void remove()

{

if(count == 1)

{

first = last = cursor = null; index=0;

}

else if(index==1)

{

first = cursor.Next; cursor.Prev = null; cursor = cursor.Next;

}

else if(index == count)

{

last = cursor.Prev; cursor.Next = null; cursor = cursor.Prev; index--;

}

else

{

cursor.Prev.Next = cursor.Next; cursor.Next.Prev = cursor.Prev; cursor = cursor.Next;

}

count--;

}//remove

/// операции с курсором:

///

/// start: require: true;

/// ensure: сделать активным первый элемент;

/// public void start()

{

cursor = first; index = 1;

}//start

///

/// finish: require: true;

/// ensure: сделать активным последний элемент;

/// public void finish()

{

cursor = last; index = count;

}//finish

///

/// go_prev: require: not (index = 1);

/// ensure: сделать активным предыдущий элемент;

///

public void go_prev()

{

cursor = cursor.Prev; index--;

}// go_prev

///

/// go_next: require: not (index = count);

/// ensure: сделать активным последующий элемент;

///

public void go_next()

{

cursor = cursor.Next; index++;

}// go_next

///

/// go_i(i): require: (i in [1, count]);

/// ensure: сделать активным элемент с индексом i;

///

/// public void go_i(int i)

{

if(i index)

while (iindex)

{

cursor = cursor.Next; index++;

}

else if(i while (i

{

cursor = cursor.Prev; index--;

}

}// go_i

/// операции поиска:

///

/// search_prev(elem): require: not (index = 1);

/// ensure: сделать активным первый элемент elem

/// слева от курсора;

///

/// искомый элемент public virtual void search_prev(Figure elem)

{

bool found = false;

while (!found && (index !=1))

{

cursor = cursor.Prev; index--; found = (elem == item());

}

search_res = found;

}// search_prev

///

/// успех или неуспех поиска сохранять в булевской

/// переменной search_res

/// search_next: require: not (index = count);

/// ensure: сделать активным первый элемент elem

/// справа от курсора;

/// успех или неуспех поиска сохранять в булевской

/// переменной search_res

///

/// name="elem"

public virtual void search_next(Figure elem)

{

bool found = false;

while (!found && (index !=count))

{

cursor = cursor.Next; index++; found = (elem == item());

}

search_res = found;

}//search_next

}

}

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


Классы элементов списка


Рассмотрим классы, описывающие элементы списков - элементы с одним и с двумя указателями:


using System; namespace Shapes

{

///

/// Класс Linkable(T)задает элементы списка,включающие:

/// информационное поле типа T - item

/// ссылку на элемент типа Linkable - next

/// Функции:

/// конструктор new: - Linkable

/// запросы:

/// Get_Item: Linkable - T

/// Get_Next: Linkable - Linkable

/// процедуры:

/// Set_Item: Linkable*T - Linkable

/// Set_Next: Linkable*Linkable - Linkable

/// Роль типа T играет Figure

///

public class Linkable

{

public Linkable()

{

item =null; next = null;

}

///

/// закрытые атрибуты класса

/// Figure item; Linkable next;

///

/// процедуры свойства для доступа к полям класса

/// public Figure Item{ get{

return(item);

}

set{

item = value;

}

}

public Linkable Next{ get{

return(next);

}

set{

next = value;

}

}

}//class Linkable

///

/// Класс TwoLinkable задает элементы с двумя ссылками

///

public class TwoLinkable

{

public TwoLinkable()

{

prev = next = null;

}

///

/// закрытые атрибуты класса

/// TwoLinkable prev, next; Figure item;

///

/// процедуры свойства для доступа к полям класса

/// public Figure Item

{

get

{

return(item);

}

set

{

item = value;

}

}

public TwoLinkable Next

{

get

{

return(next);

}

set

{

next = value;

}

}

public TwoLinkable Prev

{

get

{

return(prev);

}

set

{

prev = value;

}

}

}//class TwoLinkable

}


Организация интерфейса

Создадим теперь интерфейс, позволяющий конечному пользователю работать с объектами наших классов. Как всегда, интерфейс создавался вручную в режиме проектирования. На форме я создал меню с большим числом команд и инструментальную панель с 18 кнопками, команды которых повторяли основную команду меню. Описывать процесс создания интерфейса не буду - он подробно рассмотрен в предыдущей главе. Поскольку вся работа по созданию интерфейса транслируется в программный код формы, то просто приведу этот достаточно длинный текст почти без всяких купюр:


using System;

using System.Drawing; using System.Collections;

using System.ComponentModel; using System.Windows.Forms; using System.Data;

using Shapes;


namespace Final

{

///

/// Эта форма обеспечивает интерфейс для создания,

/// рисования, показа, перемещения, сохранения в списке

/// и выполнения других операций над объектами семейства

/// геометрических фигур. Форма имеет меню и

/// инструментальные панели.

///

public class Form1 : System.Windows.Forms.Form

{

//fields

Graphics graphic;

Brush brush, clearBrush; Pen pen, clearPen;

Color color;

Figure current;

TwoWayList listFigure;

private System.Windows.Forms.MainMenu mainMenu1; private System.Windows.Forms.ImageList imageList1; private System.Windows.Forms.ToolBar toolBar1; private System.Windows.Forms.MenuItem menuItem1;

// аналогичные определения для других элементов меню private System.Windows.Forms.MenuItem menuItem35; private System.Windows.Forms.ToolBarButton

toolBarButton1;

// аналогичные определения для других командных кнопок

private System.Windows.Forms.ToolBarButton toolBarButton18;

private System.ComponentModel.IContainer components; public Form1()

{

InitializeComponent(); InitFields();

}

void InitFields()

{

graphic = CreateGraphics();

color = SystemColors.ControlText; brush = new SolidBrush(color);

clearBrush = new SolidBrush(SystemColors.Control); pen = new Pen(color);

clearPen = new Pen(SystemColors.Control); listFigure = new Figure_List();

current = new Person(20, 50, 50);

}

///

/// Clean up any resources being used.

///

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

#region Windows Form Designer generated code

///

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

///

private void InitializeComponent()

{

// Код, инициализирующий компоненты и построенный

// дизайнером, опущен

}

#endregion

///

/// Точка входа в приложение - процедура Main,

/// запускающая форму

/// [STAThread]

static void Main()

{

Application.Run(new Form1());

}

private void menuItem7_Click(object sender, System.EventArgs e)

{

createEllipse();

}

void createEllipse()

{

//clear old figure

if (current != null) current.Show(graphic, clearPen, clearBrush);

//create ellipse

current = new Ellipse(50, 30, 180,180);

}

private void menuItem8_Click(object sender, System.EventArgs e)

{

createCircle();

}

void createCircle()

{

//clear old figure

if (current != null) current.Show(graphic, clearPen, clearBrush);

//create circle

current = new Circle(30, 180,180);

}

private void menuItem9_Click(object sender, System.EventArgs e)

{

createLittleCircle();

}

void createLittleCircle()

{

//clear old figure

if (current != null) current.Show(graphic, clearPen, clearBrush);

//create littlecircle

current = new LittleCircle(180,180);

}

private void menuItem10_Click(object sender, System.EventArgs e)

{

createRectangle();

}

void createRectangle()

{

//clear old figure

if (current != null) current.Show(graphic, clearPen, clearBrush);

//create rectangle

current = new Rect(50, 30, 180,180);

}

private void menuItem11_Click(object sender, System.EventArgs e)

{

createSquare();

}

void createSquare()

{

//clear old figure

if (current != null) current.Show(graphic, clearPen, clearBrush);

//create square

current = new Square(30, 180,180);

}

private void menuItem12_Click(object sender, System.EventArgs e)

{

createPerson();

}

void createPerson()

{

//clear old figure

if (current != null) current.Show(graphic, clearPen, clearBrush);

//create person

current = new Person(20, 180,180);

}

private void menuItem13_Click(object sender, System.EventArgs e)

{

showCurrent();

}

void showCurrent()

{

//Show current current.Show(graphic, pen, brush);

}

private void menuItem14_Click(object sender, System.EventArgs e)

{

clearCurrent();

}

void clearCurrent()

{

//Clear current

current.Show(graphic, clearPen, clearBrush);

}

private void menuItem17_Click(object sender, System.EventArgs e)

{

incScale();

}

void incScale()

{

//Increase scale

current.Show(graphic, clearPen, clearBrush); current.Scale(1.5);

current.Show(graphic, pen, brush);

}

private void menuItem18_Click(object sender, System.EventArgs e)

{

decScale();

}

void decScale()

{

//Decrease scale

current.Show(graphic, clearPen, clearBrush);

current.Scale(2.0/3); current.Show(graphic, pen, brush);

}

private void menuItem19_Click(object sender, System.EventArgs e)

{

moveLeft();

}

void moveLeft()

{

//Move left

current.Show(graphic, clearPen, clearBrush); current.Move(-20,0);

current.Show(graphic, pen, brush);

}

private void menuItem20_Click(object sender, System.EventArgs e)

{

moveRight();

}

void moveRight()

{

//Move right

current.Show(graphic, clearPen, clearBrush); current.Move(20,0);

current.Show(graphic, pen, brush);

}

private void menuItem21_Click(object sender, System.EventArgs e)

{

moveTop();

}

void moveTop()

{

//Move top

current.Show(graphic, clearPen, clearBrush); current.Move(0,-20);

current.Show(graphic, pen, brush);

}

private void menuItem22_Click(object sender, System.EventArgs e)

{

moveDown();

}

void moveDown()

{

//Move down

current.Show(graphic, clearPen, clearBrush); current.Move(0, 20);

current.Show(graphic, pen, brush);

}

private void menuItem23_Click(object sender, System.EventArgs e)

{

//choose color

ColorDialog dialog = new ColorDialog();

if (dialog.ShowDialog() ==DialogResult.OK) color =dialog.Color;

pen = new Pen(color); brush = new SolidBrush(color);

}

private void menuItem24_Click(object sender, System.EventArgs e)

{

//Red color

color =Color.Red;

pen = new Pen(color); brush =

new SolidBrush(color);

}

private void menuItem25_Click(object sender, System.EventArgs e)

{

//Green color

color =Color.Green;

pen = new Pen(color); brush = new SolidBrush(color);

}

private void menuItem26_Click(object sender, System.EventArgs e)

{

//Blue color

color =Color.Blue;

pen = new Pen(color); brush = new SolidBrush(color);

}

private void menuItem27_Click(object sender, System.EventArgs e)

{

//Black color

color =Color.Black;

pen = new Pen(color); brush = new SolidBrush(color);

}

private void menuItem28_Click(object sender, System.EventArgs e)

{

//Gold color

color =Color.Gold;

pen = new Pen(color); brush = new SolidBrush(color);

}

private void menuItem29_Click(object sender, System.EventArgs e)

{

//put_left: добавление фигуры в список

listFigure.put_left(current);

}

private void menuItem30_Click(object sender, System.EventArgs e)

{

//put_right: добавление фигуры в список

listFigure.put_right(current);

}

private void menuItem31_Click(object sender, System.EventArgs e)

{

//remove: удаление фигуры из списка

if(!listFigure.empty()) listFigure.remove();

}

private void menuItem32_Click(object sender, System.EventArgs e)

{

goPrev();

}

void goPrev()

{

//go_prev: передвинуть курсор влево

if(!(listFigure.Index == 1))

{

listFigure.go_prev(); current = listFigure.item();

}

}

private void menuItem33_Click(object sender, System.EventArgs e)

{

goNext();

}

void goNext()

{

//go_next: передвинуть курсор вправо

if( !(listFigure.Index == listFigure.Count))

{

listFigure.go_next(); current = listFigure.item();

}

}

private void menuItem34_Click(object sender, System.EventArgs e)

{

//go_first listFigure.start(); if(!listFigure.empty())

current = listFigure.item();

}

private void menuItem35_Click(object sender, System.EventArgs e)

{

//go_last listFigure.finish(); if(!listFigure.empty())

current = listFigure.item();

}

private void menuItem15_Click(object sender, System.EventArgs e)

{

showList();

}

void showList()

{

//Show List listFigure.start();

while(listFigure.Index listFigure.Count)

{

current = listFigure.item(); current.Show(graphic,pen,brush); listFigure.go_next();

}

listFigure.finish();

}

private void menuItem16_Click(object sender, System.EventArgs e)

{

clearList();

}

void clearList()

{

//Clear List listFigure.start(); while(!listFigure.empty())

{

current = listFigure.item(); current.Show(graphic,clearPen,clearBrush); listFigure.remove();

}

}

private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)

{

if((current != null) && current.dragged_figure)

{

current.Show(graphic,clearPen,clearBrush); Point pt = new Point(e.X, e.Y); current.center_figure = pt; current.Show(graphic,pen,brush);

}

}

private void Form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)

{

current.dragged_figure = false;

}

private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)

{

Point mousePoint = new Point (e.X, e.Y); Rectangle figureRect = current.Region_Capture(); if ((current != null) &&

(figureRect.Contains(mousePoint))) current.dragged_figure = true;

}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)

{

//show current figure current.Show(graphic, pen, brush);

}

private void toolBar1_ButtonClick(object sender, System.Windows.Forms.ToolBarButtonClickEventArgs e)

{

int buttonNumber = toolBar1.Buttons.IndexOf(e.Button);

switch (buttonNumber)

{

case 0:

createEllipse(); break; case 1:

createCircle(); break; case 2:

createLittleCircle(); break; case 3:

createRectangle(); break; case 4:

createSquare(); break; case 5:

createPerson(); break; case 6:

showCurrent(); break; case 7:

clearCurrent(); break; case 8:

showList(); break; case 9:

clearList(); break; case 10:

incScale(); break; case 11:

decScale(); break; case 12:

moveLeft(); break; case 13:

moveRight(); break; case 14:

moveTop(); break; case 15:

moveDown(); break; case 16:

goNext(); break; case 17:

goPrev(); break;

}

}

}

}


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

Ограничусь кратким описанием главного меню:


  • команды пункта главного меню Create позволяют создавать геометрические фигуры разных классов;

  • команды пункта главного меню Show позволяют показать или стереть текущую фигуру или все фигуры, сохраняемые в списке;

  • две команды пункта Scale позволяют изменить масштаб фигуры (увеличить ее или уменьшить);

  • команды пункта Move позволяют перемещать текущую фигуру в четырех направлениях;

  • команды пункта Color позволяют либо задать цвет фигур в диалоговом окне, либо выбрать один из предопределенных цветов;

  • группа команд пункта List позволяет помещать текущую фигуру в список, перемещаться по списку и удалять из списка ту или иную фигуру;

  • командные кнопки инструментальной панели соответствуют наиболее важным командам меню;

  • реализована возможность перетаскивания фигур по экрану мышью.


В заключение взгляните, как выглядит форма в процессе работы с объектами:


Рис. 25.1. Финальный проект. Форма в процессе работы