|
При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан. Затем: Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз. |
Работа с печатью и изображениями
Рисование в Windows-формах
Библиотека .NET Framework предоставляет чрезвычайно большой набор классов для реализации рисования в Windows-формах. Кривые Безье, текстурные кисти и перья, трансформация изображения, всевозможные виды градиентной заливки, слои, — практически все атрибуты крупного графического пакета могут быть воссозданы на одном из языков .NET Framework. Для рассмотрения этих методов и свойств потребовалась бы отдельная книга, поэтому мы ограничимся простым приложением, позволяющим рисовать линиями различного цвета и толщины. Создайте новое приложение и назовите его EasyPaint. Устанавливаем следующие значения свойств формы:
| Form1, форма, свойство | Значение |
|---|---|
| BackColor | ActiveCaptionText |
| Icon |
Code\Glava6\EasyPaint\Icon\rc_bitmap.ico |
| Text | EasyPaint |
Добавляем на форму элементы управления MainMenu и ColorDialog. Создаем следующие пункты меню:
Как обычно, рисовать мы будем при удержании и перемещении левой кнопки мыши. В классе формы добавляем объекты:
//Переменная, отвечающая за включения режима рисования. //Значение true — режим включен bool DrawMode = false; //Создаем массив точек, из которых будут формироваться линии ArrayList points = new ArrayList();
Для рисования линий и кривых в библиотеки .NET Framework имеется класс Pen, экземпляр которого нам и нужно создать:
Pen mainPen;
В графических программах принято в рабочей области изменять курсор — пользователю удобнее рисовать, когда он имеет вид карандаша. Можно просто установить значение из перечисления свойства Cursor формы (рис. 6.16), но как быть, если нужен вид, не входящий в это перечисление?
Самый простой способ добавить произвольный курсор к приложению — это поместить изображение курсора (в данном случае, Pencil.cur) в папку bin\Debug приложения и в конструкторе формы указать этот курсор в качестве основного:
public Form1()
{
InitializeComponent();
this.Cursor = new Cursor("Pencil.cur");
mainPen = new Pen(this.ForeColor);
}Во второй строчке мы также устанавливаем цвет созданного пера mainPen. Переключаемся в режим дизайна, в окне Properties в событиях формы дважды щелкаем в поле событий MouseDown, MouseMove, MouseUp:
//Событие возникает при нажатии на кнопку мыши.
private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
//Если нажата левая кнопка мыши
if(e.Button==MouseButtons.Left)
{
//Включаем режим рисования
DrawMode = true;
//Удаляем все элементы из массива points
points.Clear();
}
}
//Событие возникает при перемещении мыши
private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
//Если включен режим рисования
if(DrawMode)
{
//Создаем экземпляр pt класса Point,
//представляющий собой точку с координатами мыши в данный момент
Point pt = new Point(e.X, e.Y);
//Добавляем созданную точку в массив points
points.Add(pt);
if (points.Count<=1) return;
//Создаем новый массив pts, содержащий число точек в массиве points
Point [] pts = new Point [ points.Count];
//Преобразуем массив points в массив pts, начиная с первого элемента
points.CopyTo(pts, 0);
//Создаем экземпляр graph класса Graphics для рисования
Graphics graph = this.CreateGraphics();
//Вызываем метод DrawCurve для рисования кривой, которому
//передаем перо mainPen и массив pts
graph.DrawCurve(mainPen, pts);
}
}
//Событие возникает при отпускании кнопки мыши
private void Form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
//Отключаем режим рисования.
DrawMode = false;
}
Листинг
6.11.
Логика работы предельно проста — при нажатии левой кнопки мыши включается режим рисования; при ее перемещении формируется массив точек с текущими координатами мыши, массив изображений точек pts затем передается методу DrawCurve, который и рисует линию. При отпускании кнопки режим рисования отключается.
В обработчике пункта меню Color при выборе цвета будет создаваться новое перо:
private void mnuColor_Click(object sender, System.EventArgs e)
{
if(colorDialog1.ShowDialog()==DialogResult.OK)
{
mainPen = new Pen(colorDialog1.Color);
}
}Запускаем приложение. Вызывая диалоговое окно выбора цвета, можно рисовать разными цветами на форме (рис. 6.17).
Диалоговое окно выбора ширины линии. Элемент управления TrackBar
Займемся теперь линией для рисования — создадим собственное диалоговое окно, позволяющее устанавливать ее ширину. В окне Solution Explorer щелкаем правой кнопкой на имени проекта и в появившемся контекстном меню выбираем Add/Add Windows Form… . Называем новую форму LineWidth.cs, из окна Toolbox перетаскиваем на нее две кнопки, надпись, панель, элементы NumericUpDown , TrackBar (рис. 6.18) и устанавливаем следующие значения свойств:
| LineWidth, форма, свойство | Значение |
|---|---|
| Name | LineWidth |
| AcceptButton | BtnOK |
| CancelButton | BtnCancel |
| FormBorderStyle | FixedDialog |
| MaximizeBox | False |
| MinimizeBox | False |
| Size | 254; 286 |
| Text | Толщина линии |
| trackBar1, свойство | Значение |
|---|---|
| DecimalPlaces | 1 |
| Location | 16; 168 |
| Maximum | 100 |
| Minimum | 1 |
| Size | 224; 45 |
| TickFrequency | 5 |
| Value | 5 |
Наша задача — сделать так, чтобы при перемещении ползунка или вводе значения на форме LineWidth выводился эскиз линии, а затем, после закрытия диалогового окна, можно было рисовать линией с выбранной толщиной. В классе формы создаем метод DrawLine, который будет рисовать на панели эскиз линии:
private void DrawLine()
{
//Создаем переменную, которая равна ординате точки,
//делящий элемент panel1 по высоте пополам
int y = panel1.Bottom/2;
//Создаем точку point1 лежащей на левой границе панели, c ординатой y
Point point1 = new Point(panel1.Left,y);
//Создаем точку point2 лежащей на правой границе панели, c ординатой y
Point point2 = new Point(panel1.Right,y);
//Создаем экземпляр graph класса Graphics для рисования
Graphics graph = panel1.CreateGraphics();
//Определяем толщину линии, равную значению в элементе numericUpDown1
float f = Decimal.ToSingle(numericUpDown1.Value);
//Создаем экземпляр pen для рисования линии
Pen pen = new Pen (Color. Blue, f);
//Соединяем точки point1 и point2
graph.DrawLine(pen, point1, point2);
}Создаем свойство PenWidth, которое будет возвращать значение толщины для пера главной формы:
public float PenWidth
{
get
{
float f = Decimal.ToSingle(numericUpDown1.Value);
return f;
}
}При вызове диалогового окна на панели сразу будет появляться эскиз линии по умолчанию, для этого создаем обработчик события Paint формы, в котором вызываем метод DrawLine:
private void LineWidth_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
DrawLine();
}Связываем перемещение ползунка элемента trackBar1 со значением в поле элемента numericUpDown1, для чего в обработчике события Scroll вводим переменную val, связывающую свойства Value этих элементов:
private void trackBar1_Scroll(object sender, System.EventArgs e)
{
int val = trackBar1.Value;
numericUpDown1.Value = val;
}Аналогично, для связывания значения в поле элемента numericUpDown1 с перемещением ползунка в обработчике события ValueChanged вводим переменную val2:
private void numericUpDown1_ValueChanged(object sender, System.EventArgs e)
{
int val2 = (int)numericUpDown1.Value;
trackBar1.Value = val2;
DrawLine();
}В этом обработчике мы также вызываем метод DrawLine для вывода эскиза линии на форме. Последнее, что нам осталось сделать, — добавить обработчик в пункте меню "Толщина линии" главной формы:
private void mnuWidth_Click(object sender, System.EventArgs e)
{
LineWidth diag = new LineWidth();
if (diag.ShowDialog(this)== DialogResult.OK)
{
mainPen = new Pen(mainPen.Color, diag.PenWidth);
}
}Запускаем приложение. Теперь можно рисовать не только разными цветами, но и разной толщиной пера (рис. 6.19).
На диске, прилагаемом к книге, вы найдете приложение EasyPaint (Code\Glava6\ EasyPaint).
Code\Glava6\EasyPaint\Icon\rc_bitmap.ico


