Модификация приложения WindowsForms: функциональность векторного редактора — КиберПедия 

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

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

Модификация приложения WindowsForms: функциональность векторного редактора

2017-11-17 320
Модификация приложения WindowsForms: функциональность векторного редактора 0.00 из 5.00 0 оценок
Заказать работу

 

Для начала определим все необходимые для работы приложения класса внутри самого приложения.

 

Первый класс с именем файла DrawObject.cs станет основным классом для рисования любых объектов. На его основе будут созданы классы для рисования конкретных объектов типа линий или прямоугольников. Класс будет содержать все возможные функции, события и свойства, необходимы для работы с графическим объектом. А именно этот класс будет определять функция рисования объекта (Draw), выделения, перемещения, изменения размеров и определения количества ключевых точек. Что такое ключевая точка? Для линии это точки на концах линии, которые «подсвечиваются» небольшими прямоугольниками. Если выделить линию и навести мышь на такую точку, курсор будет изменён (зависит от типа точки и объекта рисования). Нажатие на ключевую точку обеспечивает операцию изменения размеров объекта либо перемещения (зависит от объекта рисования). Любой объект во время выделения мышью подсвечивается ключевыми точками. Например, нарисованный и выделенный прямоугольник имеет 8 ключевых точек:

 

Код файла DrawObject.cs:[искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 2 (Файлы классов Draw...) ].

 

Класс GraphicsProperties напрямую связан с дочерней формой LWP15Properties. Обработаем форму LWP15Properties и проинициализируем все необходимые свойства и события.

 

Откроем код формы (выделим LWP15Properies.cs ->нажмём правую кнопку мыши -> Перейти к коду (F7)). Найдём:

 

public LWP15Properties()

{

InitializeComponent();

}

 

Добавимпосле:

 

privateGraphicsProperties properties;

privateconststring undefined = "Незадано";

privateconstint maxWidth = 10;

 

publicGraphicsProperties Properties

{

get { return properties; }

set { properties = value; }

}

 

В самое начало формы добавим код:

 

using System.Globalization;

 

Найдём:

 

namespace LWP15Draw

{

public partialclassLWP15Properties: Form

{

 

Изменимна:

 

namespace LWP15Draw

{

partialclassLWP15Properties: Form

{

 

Проинициализируем первое событие формы LWP15Properties: Load со следующим кодом:

 

privatevoid LWP15Properties_Load(object sender, EventArgs e)

{

InitControls();

SetColor();

SetPenWidth();

}

 

Вспомогательные функции добавим сразу после предыдущего фрагмента кода:

 

privatevoid InitControls()

{

for (int i = 1; i <= maxWidth; i++)

{

CB_PenWidth.Items.Add(i.ToString(CultureInfo.InvariantCulture));

}

}

 

privatevoid SetColor()

{

if (properties.Color.HasValue) L_Color.BackColor = properties.Color.Value;

else L_Color.Text = undefined;

}

 

privatevoid SetPenWidth()

{

 

if (properties.PenWidth.HasValue)

{

int penWidth = properties.PenWidth.Value;

if (penWidth < 1) penWidth = 1;

if (penWidth > maxWidth) penWidth = maxWidth;

label2.Text = penWidth.ToString(CultureInfo.InvariantCulture);

CB_PenWidth.SelectedIndex = penWidth - 1;

}

else { label2.Text = undefined; }

}

 

privatevoid ReadValues()

{

if (CB_PenWidth.Text!= undefined) { properties.PenWidth = CB_PenWidth.SelectedIndex + 1; }

if (L_Color.Text.Length == 0) { properties.Color = L_Color.BackColor; }

}

 

Событие SelectedIndexChanged для ComboBox этойформы:

 

privatevoid CB_PenWidth_SelectedIndexChanged(object sender, EventArgs e)

{

int width = CB_PenWidth.SelectedIndex + 1;

L_PenWidth.Text = width.ToString(CultureInfo.InvariantCulture);

}

 

Событие Click нажатиякнопки B_SelectColor:

 

privatevoid B_SelectColor_Click(object sender, EventArgs e)

{

ColorDialog dlg = newColorDialog();

dlg.Color = L_Color.BackColor;

 

if (dlg.ShowDialog(this) == DialogResult.OK)

{

L_Color.BackColor = dlg.Color;

L_Color.Text = "";

}

}

 

Событие Click нажатиякнопки B_OK:

 

privatevoid B_OK_Click(object sender, EventArgs e)

{

ReadValues();

this.DialogResult = DialogResult.OK;

}

 

Форма готова. Если возникнут ошибки, перепроверяем имена элементов управления.

 

Следующим классом станет класс, отвечающий за работу со списком графических объектов документа. Данный класс будет реализовывать массив всех графических объектов, нарисованных в документе.

 

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

 

Каждый новый объект помещается вначале Z-порядка (списка расположения «под курсором»). Таким образом, нарисовав в одном и том же месте несколько объектов и нажав инструментов «Выделение» на этом же месте «по умолчанию» будет выделен последний нарисованный объект. Если изменить положение объекта в Z-списке, отправив объект «назад» («Переместить назад»), наверху окажется предыдущий нарисованный объект. Сам же объект, который мы отправили «назад», будет расположен в конце Z-порядка и будет выделен, если удалить из области все другие объекты.

 

Файл для класса назовём GraphicsList.cs, код файла будет таким:[искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 3 (Файлы классов Graphics...) ].

 

Игнорируем возникшие ошибки (3 штуки, исправим позже добавлением других классов).

 

Также добавим вспомогательный класс для передачи параметров: GraphicsProperties (файл GraphicsProperties.cs)со следующим кодом: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 3 (Файлы классов Graphics...) ].

 

Добавляем новый класс, являющийся базовым для команд типа «Отменить» и «Вернуть» («Undo» и «Redo»). Имя файла класса будет Command.cs, код файла вставляем следующий:[искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 4 (Файлы классов Command...) ].

 

Следующий класс (CommandChangeState.cs) станет основным классом для поддержки команд перемещений, изменения размеров и изменения параметров объекта рисования для операций «Отменить» и «Вернуть». Код файла будет следующим:[искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 4 (Файлы классов Command...) ].

 

Класс CommandAdd (CommandAdd.cs), отвечающий за команду добавления объекта для операций «Отменить» и «Вернуть»: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 4 (Файлы классов Command...) ].

 

Непосредственно реализация команд «Отменить» и «Вернуть» будет выполнена следующим классом UndoManager (файл UndoManager.cs) с кодом:[искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 5 (Прочие файлы) ].

 

Класс CommandDelete (CommandDelete.cs), отвечающий за команду удаления выделенного объекта для операций «Отменить» и «Вернуть»: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 4 (Файлы классов Command...) ].

 

Класс CommandDeleteAll (CommandDeleteAll.cs), отвечающий за команду удаления всех объектов для операций «Отменить» и «Вернуть»: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 4 (Файлы классов Command...) ].

 

Теперь перейдём к классам, поддерживающим рисование графических объектов. Первый и самый примитивный графический объект это линия. Класс на основе DrawObject: DrawLine (DrawLine.cs) реализует всё необходимое для поддержки рисования объекта линии, выделения нарисованного объекта, изменения положения и перемещения объекта линии. Линия рисуется через два три события (нажатие левой кнопки мыши, перемещения и отжатия левой кнопки мыши). Объект имеет де ключевые точки (точка начала и точка конца линии). Сериализуется в файл путём указания следующих параметров: точка начала и точка конца линии, а также строки записей для сохранения в файле: Start и End. Перемещение линии обеспечивается созданием для линии небольшой линейной области (толщина в 7 пикселей от центра линии). Нажатие левой кнопки мыши в этой области приведёт к выделению объекта и активации возможности перемещение, изменения. Изменение размеров линии осуществляется в ключевых точках.

 

Код файла для реализации класса:[искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 2 (Файлы классов Draw...) ].

 

Объект получает параметры из инструмента «Линия» следующим обрахом:

 

privatePoint startPoint;

privatePoint endPoint;

 

public DrawLine(int x1, int y1, int x2, int y2): base()

{

startPoint.X = x1;

startPoint.Y = y1;

endPoint.X = x2;

endPoint.Y = y2;

Initialize();

}

 

Рисует линию так:

 

///<summary>

/// Главная функция рисования линии на форме

///</summary>

publicoverridevoid Draw(Graphics g)

{

g.SmoothingMode = SmoothingMode.AntiAlias;

Pen pen = newPen(Color, PenWidth);

g.DrawLine(pen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);

pen.Dispose();

}

 

Прямоугольник. Класс на основе DrawObject: DrawRectangle (DrawRectangle.cs) реализует всё необходимое для поддержки рисования объекта прямоугольника, выделения нарисованного объекта, изменения положения и перемещения объекта прямоугольника. Объект имеет воесь ключевых точек (угловые точки, точки в центре линий). Сериализуется в файл путём указания следующих параметров: область прямоугольника, а также строки записей для сохранения в файле: Rect. Прямоугольник является цельным объектом, область для перемещения которого ограничена стронами прямоугольника. Для перемещения, как и в случае с линией нужно выделить объект (в любом месте прямоугольника) и зажать левую кнопку мыши.

 

Код файла для реализации класса:[искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 2 (Файлы классов Draw...) ].

 

Нормализация нужна для правильного определения направления рисования (первое нажатие в левом уголу, движение мыши в правый нижний угол и прочее) и получение положительных значений координат для прямоугольника.

 

Эллипс. Класс на основе DrawRectangle: DrawEllipse (DrawEllipse.cs) реализует всё необходимое для поддержки рисования объекта эллипса, выделения нарисованного объекта, изменения положения и перемещения объекта эллипса. Объект имеет воесь ключевых точек (угловые точки, точки в центре линий). Сериализуется в файл путём указания следующих параметров: область прямоугольника, а также строки записей для сохранения в файле: Rect. Прямоугольник является цельным объектом, область для перемещения которого ограничена стронами прямоугольника. Для перемещения, как и в случае с линией нужно выделить объект (в любом месте прямоугольника) и зажать левую кнопку мыши.

 

Код файла для реализации класса:[искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 2 (Файлы классов Draw...) ].

 

Объект получает следующие параметры из инструмента «Эллипс»:

 

public DrawEllipse(int x, int y, int width, int height): base()

{

Rectangle = newRectangle(x, y, width, height);

Initialize();

}

 

Рисование эллипса реализовано так:

 

///<summary>

/// Главная функция рисования эллипса на форме

///</summary>

///<param name="g"></param>

publicoverridevoid Draw(Graphics g)

{

Pen pen = newPen(Color, PenWidth);

g.DrawEllipse(pen, DrawRectangle.GetNormalizedRectangle(Rectangle));

pen.Dispose();

}

 

Карандаш: последний объект рисования. Класс на основе DrawLine: DrawPolygon (DrawPolygon.cs) реализует всё необходимое для поддержки рисования объекта непрерывной линии с малым расстоянием между точками, выделения нарисованного объекта, изменения положения и перемещения объекта карандаша. Объект имеет столько ключевых точек, сколько нарисовано «кусков» + 1 точка). Сериализуется в файл путём указания следующих параметров: точка и длина (для одного участка), а также строки записей для сохранения в файле: Point и Length. Карандаш не является цельным объектом (даже в случае замыкания линий). Для перемещения, как и в случае с линией нужно выделить объект (в любом месте нарисоанной ломаной) и зажать левую кнопку мыши. Путь для выделения создаётся также как и в случае с линией, но для каждого участка. Параметр расстояния (до ближайшей точки) регулируется так (будущий файл ToolPolygon.cs):

 

privateconstint minDistance = 15*15; // Дистанция между ключевыми точками

 

Кусок кода событиея перемещения мыши во время рисования:

 

Point point = newPoint(e.X, e.Y);

int distance = (e.X - lastX)*(e.X - lastX) + (e.Y - lastY)*(e.Y - lastY);

 

if (distance < minDistance)

{

// Если расстояние между последними двумя точками меньше минимального -

// перемещаем последнюю точку

newPolygon.MoveHandleTo(point, newPolygon.HandleCount);

}

else

{

// Добавляем новую точку

newPolygon.AddPoint(point);

lastX = e.X;

lastY = e.Y;

}

 

Код файла для реализации класса:[искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 2 (Файлы классов Draw...) ].

 

Последние 7 классов относятся к классам реализации инструмента рисования, и именно они инициализируются до вызова класса рисования объекта. Экземпляр класса инструмента передаёт в экземпляр класса рисования все параметры. Первый класс из цепочки является абстрактным базовым классом для реализации работы инструментов. Реализует три простых события действия с мышью (нажатие, перемещение и снятие нажатия). Имя: Tool.cs (класс Tool). Код файла с классом: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 6 (Файлы классов Tool...) ].

 

ToolObject.cs (класс ToolObject). Это базовый класс для реализации остальных объектов инструментов.Реализует свойства курсора для инструмента, а также функцию добавления нового объекта в список объектов документа:

 

///<summary>

/// Добавление нового объекта в область рисования.

/// Функция вызывается когда пользователь нажимает ЛКМ на области рисования,

/// и один из полученных ToolObject-инструментов активен.

///</summary>

///<param name="drawArea"></param>

///<param name="o"></param>

protectedvoid AddNewObject(DrawArea drawArea, DrawObject o)

{

drawArea.GraphicsList.UnselectAll();

o.Selected = true;

drawArea.GraphicsList.Add(o);

drawArea.Capture = true;

drawArea.Refresh();

drawArea.SetDirty();

}

 

Код файла с классом: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 6 (Файлы классов Tool...) ].

 

ToolLine.cs (класс ToolLine). Это базовый класс для реализации инструмента рисования «Линия». Передаёт параметры объекту рисования.Реализует свойства курсора для инструмента, а также функцию добавления нового объекта линии в список объектов документа.

 

Пример события нажатия ЛКМ в области DrawArea с созданием экземпляра класса DrawLine и передачей параметров нажатия:

 

publicoverridevoid OnMouseDown(DrawArea drawArea, MouseEventArgs e)

{

AddNewObject(drawArea, newDrawLine(e.X, e.Y, e.X + 1, e.Y + 1));

}

 

Код файла с классом: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 6 (Файлы классов Tool...) ].

 

ToolRectangle.cs (класс ToolRectnagle). Это базовый класс для реализации инструмента рисования «Прямоугольник». Передаёт параметры объекту рисования.Реализует свойства курсора для инструмента, а также функцию добавления нового объекта прямоугольника в список объектов документа. Событиенажатиякнопкимыши:

 

publicoverridevoid OnMouseDown(DrawArea drawArea, MouseEventArgs e)

{

AddNewObject(drawArea, newDrawRectangle(e.X, e.Y, 1, 1));

}

 

Код файла с классом: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 6 (Файлы классов Tool...) ].

 

ToolEllipse.cs (класс ToolEllipse). Это базовый класс для реализации инструмента рисования «Эллипс». Передаёт параметры объекту рисования.Реализует свойства курсора для инструмента, а также функцию добавления нового объекта эллипса в список объектов документа. Событиенажатиякнопкимыши:

 

publicoverridevoid OnMouseDown(DrawArea drawArea, MouseEventArgs e)

{

AddNewObject(drawArea, newDrawEllipse(e.X, e.Y, 1, 1));

}

 

Код файла с классом: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 6 (Файлы классов Tool...) ].

 

ToolPolygon.cs (класс ToolPolygon). Это базовый класс для реализации инструмента рисования «Карандаш». Передаёт параметры объекту рисования.Реализует свойства курсора для инструмента, а также функцию добавления нового объекта непрерывной линии в список объектов документа.

 

Код файла с классом: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 6 (Файлы классов Tool...) ].

 

ToolPointer.cs (класс ToolPointer). Это базовый класс для реализации инструмента рисования «Выделение». Передаёт параметры объекту рисования.Реализует события связанные с выделение объектов в области рисования, работает с перемещением объекта, изменением размеров объекта и чистым выделением объект(-ов). Этот инструмент также управляет пунктирным прямоугольником выделения:

 

if (selectMode == SelectionMode.NetSelection)

{

// Удаляем прямоугольник предыдущего выделения

ControlPaint.DrawReversibleFrame(

drawArea.RectangleToScreen(DrawRectangle.GetNormalizedRectangle(startPoint, oldPoint)),

Color.Black,

FrameStyle.Dashed);

// Рисуем прямоугольник нового выделения

ControlPaint.DrawReversibleFrame(

drawArea.RectangleToScreen(DrawRectangle.GetNormalizedRectangle(startPoint, point)),

Color.Black,

FrameStyle.Dashed);

return;

}

 

Код файла с классом: [искомый код можно найти в приложении к данной лабораторной работе в (описания можно того или иного приложения можно посмотреть в пунтке № 8 протокола работы), а именно необходимо открыть Приложение № 6 (Файлы классов Tool...) ].

 

На этом формирование классов закончено. Теперь можно перейти к реализации функциональности непосредственно для главной формы и элемента, в котором будем рисовать (DrawArea).

 

Первым делом «добьём» форму LWP15About. Событие Load для формы будет таким:

 

privatevoid LWP15About_Load(object sender, EventArgs e)

{

this.Text = "Опрограмме " + Application.ProductName;

L_About.Text =

"Программа: " + Application.ProductName + "\n" +

"Версия: " + Application.ProductVersion;

}

 

Событие Click кнопки B_OK:

 

privatevoid B_OK_Click(object sender, EventArgs e)

{

this.Close();

}

 

Перейдём к DrawArea.cs. Это основной элемент, в котором происходит «рисование». Любые действия мышью совершаемые в фокусе элемента перехватываются инструментами Tool... и реализуют то или иной действие в зависимости от активного инструмента и действия с мышью. Сам элемент будет растягиваться до строки состояния внизу, границ с боку формы и панели инструментов сверху. Абсолютное значение размеров будет влиять лишь на доступную для размещения объектов область. Эти размеры будут важны лишь при создании растрового изображения (об этом в конце данного материала) на основе графики в элементе.

 

Откроем код элемента DrawArea.cs и заменим все директивы using в начале файла следующим кодом:

 

#regionДирективы Using

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Drawing;

using System.Data;

using System.Text;

using System.Windows.Forms;

using LWP15Tools; // Подключаембиблиотекуклассов

#endregion

 

Подключаем к проекту ссылку на нашу библиотеку LWP15tools: жмём правую кнопку мыши на имени проекта LWP15Draw, затем Добавить ссылку...:

 

Рис. 6. 1. Добавить ссылку: вкладка Проекты

 

В открывшемся окне переходим на вкладку Проекты и выбираем LWP15Tools, жмём ОК.

 

В коде находим:

 

namespaceLWP15Draw

{

publicpartialclassDrawArea: UserControl

{

public DrawArea()

{

InitializeComponent();

}

}

 

Заменяемна (последнююфигурную скобку в файле не трогаем):

 

namespace LWP15Draw

{

partialclassDrawArea: UserControl

{

#regionКонструктор

public DrawArea()

{

InitializeComponent();

}

#endregion

 

#regionПеречисления

publicenumDrawToolType

{

Pointer, Rectangle, Ellipse, Line, Polygon, NumberOfDrawTools

};

#endregion

 

#regionЧлены

privateGraphicsList graphicsList; // Списокобъектоврисования

privateDrawToolType activeTool; // Активныйинструментрисования

privateTool[] tools; // Массивинструментов

privateLWP15Main owner;

privateDocManager docManager;

privateContextMenuStrip m_ContextMenu;

privateUndoManager undoManager;

#endregion

 

#regionСвойства

///<summary>

/// Ссылка на владельца формы

///</summary>

publicLWP15Main Owner

{

get { return owner; }

set { owner = value; }

}

 

///<summary>

///Ссылкана DocManager

///</summary>

publicDocManager DocManager

{

get { return docManager; }

set

{

docManager = value;

}

}

 

///<summary>

///Активныйинструментрисования

///</summary>

publicDrawToolType ActiveTool

{

get { return activeTool; }

set { activeTool = value; }

}

 

///<summary>

///Списокобъектоврисования

///</summary>

publicGraphicsList GraphicsList

{

get { return graphicsList; }

set

{

graphicsList = value;

undoManager = newUndoManager(graphicsList);

}

 

}

 

///<summary>

/// true - если операция отмены возможна

///</summary>

publicbool CanUndo

{

get

{

if (undoManager!= null) { return undoManager.CanUndo; }

returnfalse;

}

}

 

///<summary>

/// true - если операция возврата возможна

///</summary>

publicbool CanRedo

{

get

{

if (undoManager!= null) { return undoManager.CanRedo; }

returnfalse;

}

}

#endregion

 

#regionПрочиефункции

 

///<summary>

///Инициализация

///</summary>

///<param name="owner"></param>

///<param name="docManager"></param>

publicvoid Initialize(LWP15Main owner, DocManager docManager)

{

SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);

// Сохраняем ссылку на владельца формы

this.Owner = owner;

this.DocManager = docManager;

// Устанавливаем инструмент по умолчанию

activeTool = DrawToolType.Pointer;

// Создаём список графических объектов

graphicsList = newGraphicsList();

// Создаём экземпляр UndoManager для текущего файла

undoManager = newUndoManager(graphicsList);

// Создаёммассивинструментоврисования

tools = newTool[(int)DrawToolType.NumberOfDrawTools];

tools[(int)DrawToolType.Pointer] = newToolPointer();

tools[(int)DrawToolType.Rectangle] = newToolRectangle();

tools[(int)DrawToolType.Ellipse] = newToolEllipse();

tools[(int)DrawToolType.Line] = newToolLine();

tools[(int)DrawToolType.Polygon] = newToolPolygon();

}

 

///<summary>

/// Добавления команды в историю

///</summary>

publicvoid AddCommandToHistory(Command command)

{

undoManager.AddCommandToHistory(command);

}

 

///<summary>

///Очисткаистории

///</summary>

publicvoid ClearHistory()

{

undoManager.ClearHistory();

}

 

///<summary>

///Отменить

///</summary>

publicvoid Undo()

{

undoManager.Undo();

Refresh();

}

 

///<summary>

///Вернуть

///</summary>

publicvoid Redo()

{

undoManager.Redo();

Refresh();

}

 

///<summary>

/// Устанавливаем флаг "грязный" (файл был изменён после последней операции сохранения)

///</summary>

publicvoid SetDirty()

{

DocManager.Dirty = true;

}

 

///<summary>

/// Обработчик нажатия правой кнопки мышки

///</summary>

///<param name="e"></param>

privatevoid OnContextMenu(MouseEventArgs e)

{

// Измененяем текущий выбор при необходимости

Point point = newPoint(e.X, e.Y);

int n = GraphicsList.Count;

DrawObject o = null;

 

for (int i = 0; i < n; i++)

{

 

if (GraphicsList[i].HitTest(point) == 0)

{

o = GraphicsList[i];

break;

}

}

 

if (o!= null)

{

 

if (!o.Selected) GraphicsList.UnselectAll();

// Выбор объекта произведён

o.Selected = true;

}

else

{

GraphicsList.UnselectAll();

}

Refresh(); // В случае изменения выбора

// Выводин контекстное меню (всплывающее).

// Элементы меню вставлены из строки меня, главного элемента "Правка"

m_ContextMenu = newContextMenuStrip();

int nItems = owner.ContextParent.DropDownItems.Count;

// Получаем элементы меню "Правка" и перемещаем их на контекстное-всплывающее меню.

// Так как каждый шаг уменьшает количество элементов, читая их в обратном порядке.

// Чтобы получить элементы в прямом порядке, вставим каждый из них в начало

for (int i = nItems - 1; i >= 0; i--)

{

m_ContextMenu.Items.Insert(0, owner.ContextParent.DropDownItems[i]);

}

// Выводит контекстное меню для владельца формы, а также обрабатывает элементы выбора.

// Преобразует координаты точки в этом окне к координатам владельца

point.X += this.Left;

point.Y += this.Top;

m_ContextMenu.Show(owner, point);

Owner.SetStateOfControls(); // Включение/выключение элементов меню

// Контекстное меню вызвано, но меню "Правка" владельца теперь пусто.

// Подписываемся на событие закрытия контекстного меню и восстанавливаем там элементы

m_ContextMenu.Closed += delegate(object sender, ToolStripDropDownClosedEventArgs args)

{

 

if (m_ContextMenu!= null)

{

nItems = m_ContextMenu.Items.Count;

for (int k = nItems - 1; k >= 0; k--) { owner.ContextParent.DropDownItems.Insert(0, m_ContextMenu.Items[k]); }

}

};

}

#endregion

}

 

По очереди инициализируем для элемента DrawArea следующие события с кодом. Вначале идёт событие Paint:

 

#region Обработчики событий

///<summary>

/// Рисование графического объекта и группировка прямоугольника выделения (опционально)

///</summary>

privatevoid DrawArea_Paint(object sender, PaintEventArgs e)

{

SolidBrush brush = newSolidBrush(Color.FromArgb(255, 255, 255));

e.Graphics.FillRectangle(brush, this.ClientRectangle);

if (graphicsList!= null) { graphicsList.Draw(e.Graphics); }

//DrawNetSelection(e.Graphics);

brush.Dispose();

}

 

Событие MouseDown, MouseMove и MouseUp для DrawArea:

 

///<summary>

/// Событие MouseDown для DrawArea

/// ЛКМ: перехватывается активным инструментом

/// ПКМ: перехватывается и описано в данном классе

///</summary>

privatevoid DrawArea_MouseDown(object sender, MouseEventArgs e)

{

if (e.Button == MouseButtons.Left) tools[(int)activeTool].OnMouseDown(this, e);

elseif (e.Button == MouseButtons.Right) OnContextMenu(e);

}

 

///<summary>

/// Событие MouseMove для DrawArea

/// Перемещение без нажатия кнопок или с нажатие левой кнопки мыши перехватываетсмя активным инструментом

///</summary>

privatevoid DrawArea_MouseMove(object sender, MouseEventArgs e)

{

if (e.Button == MouseButtons.Left || e.Button == MouseButtons.None) tools[(int)activeTool].OnMouseMove(this, e);

elsethis.Cursor = Cursors.Default;

}

 

///<summary>

/// Событие MouseUp для DrawArea

/// ЛКМ: перехватывается активным инструментом

///</summary>

privatevoid DrawArea_MouseUp(object sender, MouseEventArgs e)

{

if (e.Button == MouseButtons.Left) tools[(int)activeTool].OnMouseUp(this, e);

}

#endregion

 

Переходим к главной форме LWP15Main. Переписываем директивы using:

 

#regionДирективыUsing

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Runtime.Serialization;

using System.Diagnostics;

using System.Security;

using Microsoft.Win32;

using LWP15Tools;

#endregion

 

Находим:

 

publicpartialclassLWP15Main: Form

{

 

Заменяемна:

 

partialclassLWP15Main: Form

{

#regionЧлены

privateDrawArea drawArea;

privateDocManager docManager;

privateDragDropManager dragDropManager;

privateMruManager mruManager;

privatePersistWindowState persistState;

privatestring argumentFile = ""; // Имяфайлаизкоманднойстроки

conststring registryPath = "Software\\LWP15Draw";

#endregion

 

#regionСвойства

///<summary>

///Имяфайлаизкоманднойстроки

///</summary>

publicstring ArgumentFile

{

get { return argumentFile; }

set { argumentFile = value; }

}

 

///<summary>

///Получаемссылкунаэлементстрокименю"Правка".

/// Используется при вызове контекстного-всплывающего меню в классе DrawArea

///</summary>

///<value></value>

publicToolStripMenuItem ContextParent

{

get { returnправкаToolStripMenuItem; }

}

#endregion

 

#regionКонструктор

public LWP15Main()

{

InitializeComponent();

persistState = newPersistWindowState(registryPath, this);

}

#endregion

 

#regionОбработчикисобытийдля DocManager

///<summary>

/// Загрузка документа из потока поставляемая DocManager

///</summary>

///<param name="sender"></param>

///<param name="args"></param>

privatevoid docManager_LoadEvent(object sender, SerializationEventArgs e)

{

// DocManager просит загрузить документ в поставляемый поток

try

{

drawArea.GraphicsList = (GraphicsList)e.Formatter.Deserialize(e.SerializationStream);

}

catch (ArgumentNullException ex) { HandleLoadException(ex, e); }

catch (SerializationException ex) { HandleLoadException(ex, e); }

catch (SecurityException ex) { HandleLoadException(ex, e); }

}

 

///<summary>

/// Сохранение документа в поток поставляемый DocManager

///</summary>

///<param name="sender"></param>

///<param name="args"></param>

privatevoid docManager_SaveEvent(object sender, SerializationEventArgs e)

{

// DocManager просит сохранить документ в поставляемый поток

try

{

e.Formatter.Serialize(e.SerializationStream, drawArea.GraphicsList);

}

catch (ArgumentNullException ex) { HandleSaveException(ex, e); }

catch (SerializationException ex) { HandleSaveException(ex, e); }

catch (SecurityException ex) { HandleSaveException(ex, e); }

}

#endregion

 

Теперь поочерёдно создаём события строки меню (двойное нажатие на элементе меню для инициализации события Click). В качестве кнопок будут выступать все подпункты (дочерние пункты) меню кроме подпункта «Последние файлы» меню «Файл». Блок с кодом событий Click всей строки меню будет таким:

 

#regionОбработчикисобытийстрокименю

privatevoidсоздатьToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandNew();

}

 

privatevoidоткрытьToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandOpen();

}

 

privatevoidсохранитьToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandSave();

}

 

privatevoidсохранитькакToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandSaveAs();

}

 

privatevoidвыходToolStripMenuItem_Click(object sender, EventArgs e)

{

this.Close();

}

 

privatevoidотменитьToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandUndo();

}

 

privatevoidвернутьToolStripMenuItem1_Click(object sender, EventArgs e)

{

CommandRedo();

}

 

privatevoidвыделитьвсеToolStripMenuItem_Click(object sender, EventArgs e)

{

drawArea.GraphicsList.SelectAll();

drawArea.Refresh();

}

 

privatevoidснятьВыделениеToolStripMenuItem_Click(object sender, EventArgs e)

{

drawArea.GraphicsList.UnselectAll();

drawArea.Refresh();

}

 

privatevoidудалитьToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandDelete command = newCommandDelete(drawArea.GraphicsList);

 

if (drawArea.GraphicsList.DeleteSelection())

{

drawArea.SetDirty();

drawArea.Refresh();

drawArea.AddCommandToHistory(command);

}

}

 

privatevoidудалитьВсеToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandDeleteAll command = newCommandDeleteAll(drawArea.GraphicsList);

 

if (drawArea.GraphicsList.Clear())

{

drawArea.SetDirty();

drawArea.Refresh();

drawArea.AddCommandToHistory(command);

}

}

 

privatevoidпереместитьНазадToolStripMenuItem_Click(object sender, EventArgs e)

{

 

if (drawArea.GraphicsList.MoveSelectionToBack())

{

drawArea.SetDirty();

drawArea.Refresh();

}

}

 

privatevoidпереместитьВпередToolStripMenuItem_Click(object sender, EventArgs e)

{

 

if (drawArea.GraphicsList.MoveSelectionToFront())

{

drawArea.SetDirty();

drawArea.Refresh();

}

}

 

privatevoidпараметрыToolStripMenuItem_Click(object sender, EventArgs e)

{

 

if (drawArea.GraphicsList.ShowPropertiesDialog(drawArea))

{

drawArea.SetDirty();

drawArea.Refresh();

}

}

 

privatevoidвыделениеToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandPointer();

}

 

privatevoidкарандашToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandPolygon();

}

 

privatevoidлинияToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandLine();

}

 

privatevoidэллипсToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandEllipse();

}

 

privatevoidпрямоугольникToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandRectnagle();

}

 

privatevoidопрограммеToolStripMenuItem_Click(object sender, EventArgs e)

{

CommandAbout();

}

#endregion

 

Тожесамое проделываем для строки с иконками (панелью инструментов). Двойное нажатие на иконку инициализирует событие Click:

 

#regionОбработчикисобытийпанелиинструментов

privatevoidсоздатьToolStripButton_Click(object sender, EventArgs e)

{

CommandNew();

}

 

privatevoidоткрытьToolStripButton_Click(object sender, EventArgs e)

{

CommandOpen();

}

 

privatevoidсохранитьToolStripButton_Click(object sender, EventArgs e)

{

CommandSave();

}

 

privatevoidвыделениеToolStripButton_Click(object sender, EventArgs e)

{

CommandPointer();

}

 

privatevoidкарандашToolStripButton_Click(object sender, EventArgs e)

{

CommandPolygon();

}

 

privatevoidлинияToolStripButton_Click(object sender, EventArgs e)

{

CommandLine();

}

 

privatevoidэллипсToolStripButton_Click(object sender, EventArgs e)

{

CommandEllipse();

}

 

privatevoidпрямоугольникToolStripButton_Click(object sender, EventArgs e)

{

CommandRectangle();

}

 

privatevoidотменитьToolStripButton_Click(object sender, EventArgs e)

{

CommandUndo();

}

 

privatevoidвернутьToolStripButton_Click(object sender, EventArgs e)

{

CommandRedo();

}

 

privatevoidсправкаToolStripButton_Click(object sender, EventArgs e)

{

CommandAbout();

}

#endregion

 

Инициализируем три события для главной формы. Событие Load формы LWP15Main:

 

#regionОбработчикисобытий

privatevoid LWP15Main_Load(object sender, EventArgs e)

{

toolStripStatusLabel.Text = "Готовкработе";

// Создаёмобластьрисования

drawArea = newDrawArea();

drawArea.Location = new System.Drawing.Point(0, 0);

drawArea.Size = new System.Drawing.Size(10, 10);

drawArea.Owner = this;

this.Controls.Add(drawArea);

// Вспомогательные объекты (DocManager и прочие)

InitializeHelperObjects();

drawArea.Initialize(this, docManager);

ResizeDrawArea();

LoadSettingsFromRegistry();

// Submit to Idle event to set controls state at idle time

Application.Idle += delegate(object o, EventArgs a)

{

SetStateOfControls();

};

// Открытый файл передаётся в командную строку

if (ArgumentFile.Length > 0) OpenDocument(ArgumentFile);

// Подписываемся на событие DropDownOpened для каждого всплывающего меню

foreach (ToolStripItem item in menuStrip1.Items)

{

if (item.GetType() == typeof(ToolStripMenuItem)) { ((ToolStripMenuItem)item).DropDownOpened += LWP15Main_DropDownOpened; }

}

}

 

Событие Resize:

 

///<summary>

/// Изменение размеров DrawArea, Когда меняются размеры формы

///</summary>

privatevoid LWP15Main_Resize(object sender, EventArgs e)

{

if (this.WindowState!= FormWindowState.Minimized && drawArea!= null) { ResizeDrawArea(); }

}

 

Событие FormClosing:

 

///<summary>

/// Событие закрытия формы

///</summary>

privatevoid LWP15Main_FormClosing(object sender, FormClosingEventArgs e)

{

 

if (e.CloseReason == CloseReason.UserClosing)

{

if (!docManager.CloseDocument()) e.Cancel = true;

}

SaveSettingsToRegistry();

}

 

Последнее событие формы без инициализации (просто вставляем код после последнего события):

 

///<summary>

/// Всплывающая строка меню ("Файл", "Правка" и прочее) открыто

///</summary>

///<param name="sender"></param>

///<param name="e"></param>

void LWP15Main_DropDownOpened(object sender, EventArgs e)

{

// Устанавливаем активный инструмент на "Выделение".

// Педотвращает редки


Поделиться с друзьями:

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.89 с.