Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

RUS_-_Karejev_-_Razrabotka_Windows-prilozhenij

.pdf
Скачиваний:
36
Добавлен:
02.02.2015
Размер:
8 Мб
Скачать
☆

openFileDialog1, Свойство

Значение

Title

 

Сохранение изображения

 

 

 

pictureBox1, Свойство

Значение

 

ContextMenu

contextMenu1

 

Dock

Fill

 

 

SizeMode

StretchImage

 

Приложение будет отображать в элементе управления PictureBox загруженный рисунок. Добавляем обработчик пункта меню mnuOpen:

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

{

OpenFileDialog diag = new OpenFileDialog();

diag.Filter = "jpg files (*.jpg)|*.jpg|All files (*.*)|*.*" ; if (diag.ShowDialog() == DialogResult.OK)

{

pictureBox1.Image = new Bitmap(diag.OpenFile());

}

pictureBox1.Image= new Bitmap(diag.OpenFile());

}

Несмотря на определение формата jpeg в качестве основного, элемент PictureBox поддерживает также работу с форматами Bitmap

(.bmp), Icon (.ico), GIF (.gif), Metafile (.wmf). Сохранения файла практически не отличается от сохранения содержимого текстового поля:

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

{

SaveFileDialog diag = new SaveFileDialog();

diag.Filter = "jpg files (*.jpg)|*.jpg|All files (*.*)|*.*" ; if(diag.ShowDialog() != DialogResult.OK)

return;

// Получаем адрес файла.

string filename = diag.FileName;

FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite); pictureBox1.Image.Save(fs, System.Drawing.Imaging.ImageFormat.Jpeg); fs.Close();

}

Листинг 6.6.

Обратите внимание на возможность конвертирования форматов — метод Save свойства предоставляет возможность сохранения содержимого PictureBox в различных форматах (рис. 6.9).

Рис. 6.9. Второй параметр метода Save принимает название графического формата

Мы выбрали формат Jpeg — при открытии рисунка в другом формате, например, Bmp, и последующем сохранении он будет конвертирован в этот формат.

Элемент управления PictureBox поддерживает несколько вариантов отображения загружаемого рисунка (рис. 6.10).

увеличить изображение

Рис. 6.10. Режимы отображения рисунка элементов PictureBox: подогнать размер (StretchImage), истинный размер (Normal), по центру (CenterImage), автоматический размер (AutoSize)

Мы установили свойству SizeMode значение StretchImage, и поэтому при открывании рисунка его размер автоматически подгоняется под размер PictureBox и, соответственно, формы. Истинный размер выводит рисунок в его действительных

пропорциях; при этом на экране помещается только его часть. Конечно, в этом режиме необходима прокрутка рисунка — об этом чуть позже. Режим по центру располагает рисунок в его реальных пропорциях так, чтобы его центр совпадал с центром PictureBox. Последний режим — автоматический размер — подгоняет размеры PictureBox под размер открываемого изображения.

На рис. 6.10 он визуально совпадает с режимом StretchImage — дело в том, что мы установили свойству Dock значение Fill и поэтому PictureBox уже имеет максимально большой размер.

В классе формы создадим массив ArrayMenu, в котором будут содержаться значения режимов:

private PictureBoxSizeMode[] ArrayMenu =

{

PictureBoxSizeMode.StretchImage,

PictureBoxSizeMode.Normal,

PictureBoxSizeMode.CenterImage,

PictureBoxSizeMode.AutoSize

};

Переменная selectedMode будет возвращать выбранное значение:

private int selectedMode = 0;

В обработчиках пунктов меню будем выбирать одно значение из массива:

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

{

if (sender is MenuItem)

{

MenuItem menuitem = (MenuItem)sender; selectedMode = menuitem.Index; pictureBox1.SizeMode = ArrayMenu[0]; pictureBox1.Invalidate();

}

}

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

{

if (sender is MenuItem)

{

MenuItem menuitem = (MenuItem)sender; selectedMode = menuitem.Index;

pictureBox1.SizeMode = ArrayMenu[1]; pictureBox1.Invalidate();

}

}

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

{

if (sender is MenuItem)

{

MenuItem menuitem = (MenuItem)sender; selectedMode = menuitem.Index;

pictureBox1.SizeMode = ArrayMenu[2]; pictureBox1.Invalidate();

}

}

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

{

if (sender is MenuItem)

{

MenuItem menuitem = (MenuItem)sender; selectedMode = menuitem.Index;

pictureBox1.SizeMode = ArrayMenu[3]; pictureBox1.Invalidate();

}

}

Листинг 6.7.

В каждом обработчике мы добавили метод Invalidate для перерисовки содержимого pictureBox1 после выбора пункта меню.

Удобно, когда выбранный пункт меню помечается галочкой (см. рис. 6.10). Переходим в режим дизайна, выделяем пункт меню Вид (View) и в окне Properties дважды щелкаем в поле события Popup:

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

{

if (sender is MenuItem)

{

bool ImLoad = (pictureBox1.Image != null);

foreach (MenuItem menuitem in ((MenuItem)sender).MenuItems)

{

menuitem.Enabled = ImLoad;

menuitem.Checked = (this.selectedMode == menuitem.Index);

}

}

}

В обработчиках пунктов контекстного меню дублируем код для соответствующих пунктов главного меню:

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

{

Вставляем скопированный код для mnuResize_Click

}

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

{

Вставляем скопированный код для mnuActual _Click

}

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

{

Вставляем скопированный код для mnuCenterImage _Click

}

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

{

Вставляем скопированный код для mnuAutoSize _Click

}

Запускаем приложение. Оно должно походить на приложение, изображенное на рис. 6.10. Добавим теперь к нашему приложению строку состояния, на которую будет выводиться размер загруженного изображения и его адрес. Из окна ToolBox перетаскиваем на форму элемент StatusBar, щелкаем в поле его свойства Panels и в открывшемся окне StatusBarPanel Collection Editor

добавляем панели sbFile и sbSize (рис. 6.11 и рис. 6.12).

Рис. 6.11. Панель sbFile. Свойству Width панели установлено значение 500 пикселей

Рис. 6.12. Панель sbSize

Свойству ShowPanels элемента statusBar1 устанавливаем значение True. В обработчике пункта меню "Открыть" — код для вывода на панель sbFile адреса файла, а на панель sbSize — его размер:

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

{

…

//Строка для вывода во время загрузки изображения

sbFile.Text

= "Загрузка " + diag.FileName;

//Строка

для вывода после загрузки изображения

sbFile.Text

= "Изображение " + diag.FileName;

//Вывод ширины

(Width) и высоты (Height) изображения

sbSize.Text= String.Format("{0:#} x {1:#}", pictureBox1.Image.Width, pictureBox1.Image.Height);

}

Листинг 6.8.

Запускаем и тестируем приложение (рис. 6.13).

Рис. 6.13. Строка состояния приложения Picture Viewer

Печать содержимого PictureBox

Теперь займемся печатью изображений, помещенных в PictureBox. Добавляем на форму элементы PrintDocument, PageSetupDialog, PrintPreviewDialog и PrintDialog. На этот раз мы не будем настраивать визуально свойства этих элементов. Создаем обработчиков пунктов меню, в которых просто вызываем диалоговые окна:

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

{

PageSetupDialog diag = new PageSetupDialog(); diag.Document = printDocument1; diag.ShowDialog();

}

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

{

PrintPreviewDialog diag = new PrintPreviewDialog(); diag.Document = printDocument1;

diag.ShowDialog();

}

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

{

PrintDialog diag = new PrintDialog(); diag.Document = printDocument1;

if (diag.ShowDialog() == DialogResult.OK)

{

printDocument1.Print();

}

}

Листинг 6.9.

Обратите внимание на свойство диалоговых окон Document — мы программно устанавливаем значение printDocument1. Переключаемся в режим дизайна, выделяем объект printDocument1 и в окне Properties дважды щелкаем в поле события

PrintPage:

private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)

{

}

Дальнейший код будет относиться к этому обработчику. Проверяем наличие изображения в pictureBox1:

if (pictureBox1.Image == null)

{

e.Cancel = true; return;

}

Определяем печатную область страницы:

float leftMargin = e.MarginBounds.Left; float rightMargin = e.MarginBounds.Right; float topMargin = e.MarginBounds.Top; float bottomMargin= e.MarginBounds.Bottom;

float printableWidth = e.MarginBounds.Width; float printableHeight = e.MarginBounds.Height;

Cоздаем экземпляр graph класса Graphics:

Graphics graph = e.Graphics;

В документе, формируемом для печати, не содержится текста — ведь мы имеем дело с изображением. Но интересно будет выводить на печать строку, указывающую, к примеру, размер изображения. Для этого создадим экземпляр font класса Font:

Font font= new Font("Comic Sans MS", 16); //Определяем высоту шрифта

float fontHeight = font.GetHeight(graph); //Определяем размер пробелов

float spaceWidth = graph.MeasureString(" ", font).Width;

Определяем область, в которую будет вписываться изображение; размер наибольшей стороны изображения составляет 90% от кратчайшей стороны листа:

float imageLength;

float Xposition = leftMargin;

float Yposition = topMargin + fontHeight; if (printableWidth < printableHeight)

{

imageLength = printableWidth * 90/100; Yposition += imageLength;

}

else

{

imageLength = printableHeight * 90/100; Xposition += imageLength + spaceWidth;

}

Выводим изображение в области rectImage:

Rectangle rectImage= new Rectangle((int)leftMargin + 1, (int)topMargin + 1, (int)imageLength,(int)imageLength); graph.DrawImage(pictureBox1.Image,(int)leftMargin + 1, (int)topMargin + 1, (int)imageLength,(int)imageLength);

Определяем область rectText и выводим в нее строку с указанием размера файла (используется метод PrintTextString):

RectangleF rectText = new RectangleF(Xposition, Yposition, rightMargin - - Xposition, bottomMargin - Yposition);

PrintText (graph, font,"Размер изображения: ", Convert.ToString (pictureBox1.Image.Size), ref rectText);

}

На этом код метода printDocument1_PrintPage заканчивается. Для вывода изображения все готово. Остается только написать метод PrintText, который будет выводить текстовую строку. Привожу код этого метода с комментариями:

protected void PrintText( Graphics graph,

Font font,

string name,

string text,

ref RectangleF

rectText)

 

 

 

 

 

{

 

 

 

 

 

// Определяем размеры печатной области для текста:

 

 

 

float leftMargin = rectText.Left;

 

 

 

 

float rightMargin = rectText.Right;

 

 

 

 

float topMargin = rectText.Top;

 

 

 

 

float bottomMargin = rectText.Bottom;

 

 

 

 

//Определяем высоту текста и координаты, где он будет выводиться:

 

 

float fontHeight = font.GetHeight(graph);

 

 

 

 

float Xposition = rectText.Left;

 

 

 

 

float Yposition = topMargin + fontHeight;

 

 

 

 

//Определяем ширину текста и размер пробелов

 

 

 

float spaceWidth = graph.MeasureString(" ",

font).Width;

 

 

float nameWidth

= graph.MeasureString(name, font).Width;

 

 

graph.DrawString(name, font,

Brushes.Black, new PointF(Xposition, Yposition)); leftMargin += nameWidth + spaceWidth;

Xposition = leftMargin;

//Формируем несколько строк для текста в случае,

//если он не будет умещаться на одной строке string[] words

=text.Split(" \r\t\n\0".ToCharArray()); foreach (string word in words)

{

float wordWidth = graph.MeasureString( word, font).Width;

if (wordWidth == 0.0) continue;

if (Xposition + wordWidth > rightMargin)

{

// Начало с новой строки

Xposition = leftMargin; Yposition += fontHeight;

if (Yposition > bottomMargin)

{

break;

}

}

graph.DrawString(word, font,Brushes.Black, new PointF(Xposition, Yposition)); Xposition += wordWidth;

}

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

rectText.Y = Yposition;

rectText.Height = bottomMargin - Yposition;

}

Листинг 6.10.

Запускаем приложение. При выборе книжной ориентации страницы рисунок вписывается с сохранением своих пропорций (рис. 6.14), затем выводится на печать (рис. 6.15).

Рис. 6.14. Предварительный просмотр приложения Picture Viewer

Рис. 6.15. Вывод рисунка в окно виртуального принтера программы pdfFactoryPro

В конце лекции приводится полный листинг приложения Picture Viewer, а исходный проект имеется на диске, прилагаемом к книге

(Code\Glava6\ Picture Viewer).

Рисование в Windows-формах

Библиотека .NET Framework предоставляет чрезвычайно большой набор классов для реализации рисования в Windows-формах. Кривые Безье, текстурные кисти и перья, трансформация изображения, всевозможные виды градиентной заливки, слои, — практически все атрибуты крупного графического пакета могут быть воссозданы на одном из языков .NET Framework. Для рассмотрения этих методов и свойств потребовалась бы отдельная книга, поэтому мы ограничимся простым приложением, позволяющим рисовать линиями различного цвета и толщины. Создайте новое приложение и назовите его EasyPaint.

Устанавливаем следующие значения свойств формы:

Form1, форма, свойство

Значение

BackColor

ActiveCaptionText

 

 

Icon

Code\Glava6\EasyPaint\Icon\rc_bitmap.ico

 

Text

EasyPaint

Добавляем на форму элементы управления MainMenu и ColorDialog. Создаем следующие пункты меню:

Name Text

mnuFormat &Формат

mnuColor &Цвет

mnuWidth &Толщина линии

Как обычно, рисовать мы будем при удержании и перемещении левой кнопки мыши. В классе формы добавляем объекты:

//Переменная, отвечающая за включения режима рисования. //Значение true — режим включен

bool DrawMode = false;

//Создаем массив точек, из которых будут формироваться линии

ArrayList points = new ArrayList();

Для рисования линий и кривых в библиотеки .NET Framework имеется класс Pen, экземпляр которого нам и нужно создать:

Pen mainPen;

В графических программах принято в рабочей области изменять курсор — пользователю удобнее рисовать, когда он имеет вид карандаша. Можно просто установить значение из перечисления свойства Cursor формы (рис. 6.16), но как быть, если нужен вид, не входящий в это перечисление?

Рис. 6.16. Свойство Cursor формы

Самый простой способ добавить произвольный курсор к приложению — это поместить изображение курсора (в данном случае, 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).

Рис. 6.17. Приложение EasyPaint. Курсор имеет точно такой же вид, как и в редакторе Microsoft Paint

Диалоговое окно выбора ширинылинии. Элемент управления TrackBar

Займемся теперь линией для рисования — создадим собственное диалоговое окно, позволяющее устанавливать ее ширину. В окне Solution Explorer щелкаем правой кнопкой на имени проекта и в появившемся контекстном меню выбираем Add/Add Windows Form… . Называем новую форму LineWidth.cs, из окна Toolbox перетаскиваем на нее две кнопки, надпись, панель, элементы NumericUpDown , TrackBar (рис. 6.18) и устанавливаем следующие значения свойств:

button1, свойство Значение

Name

btnOK

Location

32; 224

Text

&OK

button2, свойство Значение

Name

btnCancel

Location

136; 224

Text

 

&Отмена

 

 

 

 

 

 

 

 

 

 

LineWidth, форма, свойство

 

Значение

 

 

 

 

 

 

 

 

 

Name

 

 

 

 

 

LineWidth

 

 

 

 

 

 

 

 

 

AcceptButton

 

 

 

 

 

BtnOK

 

 

 

 

 

 

 

 

 

CancelButton

 

 

 

 

 

BtnCancel

 

 

 

 

 

 

 

 

 

FormBorderStyle

 

 

 

 

 

FixedDialog

 

 

 

 

 

 

 

 

 

MaximizeBox

 

 

 

 

 

False

 

 

 

 

 

 

 

 

 

MinimizeBox

 

 

 

 

 

False

 

 

 

 

 

 

 

Size

 

 

 

 

254; 286

 

 

 

 

 

 

 

 

 

 

Text

 

 

 

 

 

Толщина линии

 

 

 

 

 

 

 

label1, свойство

Значение

 

 

 

 

Location

8; 136

 

 

 

 

 

Text

Толщина

 

 

 

 

 

 

 

 

 

numericUpDown1, свойство

Значение

 

DecimalPlaces

 

 

1

 

 

Increment

 

 

0,1

 

Location

 

 

120; 136

 

Minimum

 

 

1

 

 

Value

 

 

1

 

 

 

 

 

trackBar1, свойство

Значение

 

DecimalPlaces

 

1

 

 

 

 

 

Location

 

16; 168

 

 

 

 

Maximum

 

100

 

 

 

 

 

Minimum

 

1

 

 

 

 

 

Size

 

224; 45

 

 

 

 

TickFrequency

 

5

 

 

 

 

 

Value

 

5

 

 

 

 

 

Рис. 6.18. Форма LineWidth в режиме дизайна

Наша задача — сделать так, чтобы при перемещении ползунка или вводе значения на форме 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;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]