Как вставить картинку в pictureBox C#
У многие новичков возникают вопросы при написании программа на C#. Один из часто задаваемых, как использовать компонент pictureBox и как использовать этот класс. Если вы пользуетесь конструктором в visual studio это одно, да вам легко перетащить из панели элементов pictureBox и в свойствах Image вставить изображение. Но что делать если вам требуется изменить картинку программно, или вовсе при нажатии кнопки менять изображения. Вот об этом и поговорим в этой статье. Прежде всего вам потребуется сама картинка, я создал новое приложение назвал его pictureBox скачал из интернета 4 картинки, на форме разместил компонент pictureBox 150х150 и button. рис 1.
Теперь нам потребуется добавить наши картинки в проект, для это выбираем свойство нашего проекта рис 2.

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

Молодцы теперь мы умеем добавлять ресурсы в наш проект, сюда так же можно добавлять и другого формата файлы, видео, музыку, текстовые файлы. Если вы были внимательны, то в обозревателе решений в папке Resources появились наши картинки. рис 3.

Теперь перейдем не посредственно коду программы, а именно одним из его свойств.
Свойство Image компонента PictureBox:
Загрузка и отображение картинки в Windows Forms c C#

В данном примере я покажу Вам как можно загрузить картинку из Интернета и отобразить ее в пользовательском интерфейсе. Изображение будет отображаться при нажатии на кнопку причем, каждый раз будет новое изображение.
Интерфейс MainForm.Designer.cs
namespace ShowImagwFromInternetWinForm
partial class MainForm
///
///
private System.ComponentModel.IContainer components = null;
///
///
/// true if managed resources should be disposed; otherwise, false.protected override void Dispose(bool disposing)
if (disposing && (components != null))
components.Dispose();
>
base.Dispose(disposing);
>
#region Windows Form Designer generated code
///
/// the contents of this method with the code editor.
///
private void InitializeComponent()
this.ImagePictureBox = new System.Windows.Forms.PictureBox();
this.DownloadImageButton = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.ImagePictureBox)).BeginInit();
this.SuspendLayout();
//
// ImagePictureBox
//
this.ImagePictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.ImagePictureBox.BackColor = System.Drawing.SystemColors.ActiveCaption;
this.ImagePictureBox.Location = new System.Drawing.Point(12, 12);
this.ImagePictureBox.Name = «ImagePictureBox»;
this.ImagePictureBox.Size = new System.Drawing.Size(435, 462);
this.ImagePictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.ImagePictureBox.TabIndex = 0;
this.ImagePictureBox.TabStop = false;
//
// DonwloadImageButton
//
this.DownloadImageButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.DownloadImageButton.Cursor = System.Windows.Forms.Cursors.Hand;
this.DownloadImageButton.Location = new System.Drawing.Point(12, 496);
this.DownloadImageButton.Name = «DonwloadImageButton»;
this.DownloadImageButton.Size = new System.Drawing.Size(435, 49);
this.DownloadImageButton.TabIndex = 1;
this.DownloadImageButton.Text = «Загрузить»;
this.DownloadImageButton.UseVisualStyleBackColor = true;
this.DownloadImageButton.Click += new System.EventHandler(this.DonwloadImageButton_Click);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 19F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(459, 557);
this.Controls.Add(this.DownloadImageButton);
this.Controls.Add(this.ImagePictureBox);
this.Name = «Form1»;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = «Главное окно»;
((System.ComponentModel.ISupportInitialize)(this.ImagePictureBox)).EndInit();
this.ResumeLayout(false);
private PictureBox ImagePictureBox;
private Button DownloadImageButton;
>
>
Код формы с логикой программы
namespace ShowImagwFromInternetWinForm
public partial class MainForm : Form
public MainForm()
InitializeComponent();
>
/**
* Загружает изображение
* и возвращает его как массив байт
*
*/
private static byte[] DownloadImage(string url)
using var httpClient = new HttpClient();
var response = httpClient.GetByteArrayAsync(url).Result;
/**
*
* Обработчик нажатия кнопки загрзки
*
*/
private void DonwloadImageButton_Click(object sender, EventArgs e)
DownloadImageButton.Text = «Картинка загружается. «;
// вызываем загрузку внутри отдельной задачи, чтобы не блокировать интерфейс
Task.Run(() =>
// загружаем картинку
var imageBytes = DownloadImage(«https://source.unsplash.com/random»);
// создаем объект Bitmap из массива байт
var bitmap = new Bitmap(new MemoryStream(imageBytes));
// Устанавливаем изображение для отображение пользователю
ImagePictureBox.Image = bitmap;
Таким образом, при запуске этой программы Вы увидите пустое окно, в которое при нажатии на кнопку будет загружено изображение.

![]()
Создано 23.08.2022 08:29:08
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
- Кнопка:
Она выглядит вот так: - Текстовая ссылка:
Она выглядит вот так: Как создать свой сайт - BB-код ссылки для форумов (например, можете поставить её в подписи):
Комментарии ( 0 ):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.
Copyright © 2010-2023 Русаков Михаил Юрьевич. Все права защищены.
Как отобразить картинку в PictureBox на форме?
Нужно отобразить в PictureBox картинку с построенной программой диаграммой в Excel.
По идее, картинка должна быть в папке с ресурсами, но я не понимаю куда она сохраняется и как ее отобразить в самой программе в PictureBox в таком случае?
using System; using System.Windows.Forms; using XL = Microsoft.Office.Interop.Excel; namespace WindowsApplication1 < public partial class Form1 : Form < public Form1() < InitializeComponent(); >private void button1_Click(object sender, EventArgs e) < XL.Application XL1 = new XL.Application(); // Объявляем объект XL1.Workbooks.Add(); // Добавляем рабочую книгу // Заполнить ячейки A2 (со 2 по 6) XL1.ActiveSheet.Cells[1, 2] = textBox1.Text; XL1.ActiveSheet.Cells[1, 3] = textBox2.Text; XL1.ActiveSheet.Cells[1, 4] = textBox3.Text; XL1.ActiveSheet.Cells[1, 5] = textBox4.Text; XL1.ActiveSheet.Cells[1, 6] = textBox5.Text; // Добавить новую диаграмму XL1.Charts.Add(); // Задаем тип графика - диаграммма XL1.ActiveChart.ChartType = XL.XlChartType.xlPie; // Отключаем легенду и задаем имя диаграммы XL1.ActiveChart.HasLegend = false; XL1.ActiveChart.HasTitle = true; XL1.ActiveChart.ChartTitle.Characters.Text = "Diagram"; // Сохраняем график в растровом файле XL1.ActiveChart.Export("myFile.jpg"); //Bitmap myImage = new Bitmap("myFile.jpg"); //pictureBox1.Image = (Image)myImage; XL1.Visible = true; >

- Вопрос задан более трёх лет назад
- 2772 просмотра
1 комментарий
Простой 1 комментарий
Как вставить картинку в windows forms c
БлогNot. C#: работаем с графикой и графическими компонентами в приложениях Windows Forms
C#: работаем с графикой и графическими компонентами в приложениях Windows Forms
Для работы с изображениями в библиотеке .NET определён базовый класс System.Drawing.Image , который предоставляет функциональные возможности для производных классов System.Drawing.Bitmap (растровая графика) и System.Drawing.MetaFile (векторная графика). Этот класс содержит методы для создания (и сохранения) объектов типа Image из указанного файла, потока данных и т.д.
Когда требуется перерисовка элемента управления, происходит событие Paint , которое, в зависимости от задачи, можно как программировать явно, так и полагаться на его автоматический вызов, происходящий, когда изменилась графическая канва объекта. Для отрисовки готового файла с изображением, имя которого задано или получено из диалога открытия файла OpenFileDialog , мы должны создать или получить из аргумента PaintEventArgs метода Paint графическую канву типа System.Drawing.Graphics а затем уже вывести на неё изображение.
Для использования готовых методов обработки изображений (поворот, масштабирование, изменение цвета и т.п.) мы программно создаём объект типа System.Drawing.Bitmap , копирующий имеющееся изображение, выполняем его обработку, а затем выводим изменённый объект в компоненту, предназначенную для отображения, такую как PictureBox .
Проект Lab5_1. Выведем выбранный в стандартном диалоге открытия файла рисунок на форму (пункт меню Файл — Открыть) и принудительно перерисуем по пункту меню Правка — Перерисовать. В свойствах диалога открытия файла openFileDialog1 указано Filter = Все файлы|*.*|Рисунки BMP|*.bmp|Рисунки JPEG|*.jpg|Рисунки PNG|*.png а свойство FileName равно пустой строке. В классе формы пропишем объекты «Изображение» и «Имя файла»:
private Image Img; private String Name;
Напишем обработчик открытия файла:
//Обработка меню Файл - Открыть openFileDialog1.ShowDialog(); Name = openFileDialog1.FileName.Trim(); if (String.IsNullOrEmpty(Name)) return; try < Img = new Bitmap(Name); //или так: Img = Image.FromFile(Name); >catch (Exception ex) < MessageBox.Show(ex.Message + Environment.NewLine + "(не могу открыть файл)", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); toolStripLabel1.Text = "Файл не выбран"; Img = null; return; >this.ClientSize = new System.Drawing.Size(Img.Width, Img.Height); //Размер формы подгогнали под размер картинки toolStripLabel1.Text = Name; //Имя файла вывели в панель инструментов this.Refresh(); //Потребовать перерисовки!
По событию Paint формы будет выполняться отрисовка объекта Img на текущей канве, Y-координата для вставки рисунка учитывает пространство, занимаемое по вертикали компонентами menuStrip1 и toolStripLabel1 :
private void Form1_Paint(object sender, PaintEventArgs e) < if (Img != null) < Point p = new Point(0, menuStrip1.Size.Height+ toolStripLabel1.Size.Height); e.Graphics.DrawImage(Img, p); >>
Объект «Графика», представляющий собой поверхность для рисования, также может быть получен для канвы формы (вот обработчик пункта меню Правка — Перерисовать):
if (Img != null)
или из загруженного (сгенерированного) изображения, например, см. код для пункта меню Файл — Создать:
Img = new Bitmap(200, 200, System.Drawing.Imaging.PixelFormat.Format24bppRgb); Graphics Gr = Graphics.FromImage(Img); // Теперь становятся доступными методы класса Graphics! Pen pen = new Pen(Color.ForestGreen, 4.0F); Gr.DrawLine(pen, 0, 0, 199, 199); Gr.RotateTransform(180.0F); //поворот на 180 градусов Img.Save("example.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); //сохранение this.Refresh();
-
Image — рисунок. Само изображение можно загрузить программно через свойство ImageLocation , например, в методе Load формы:
openFileDialog1.ShowDialog(); if (openFileDialog1.FileName != null) this.pictureBox1.ImageLocation = this.openFileDialog1.FileName;
Для возможности прокрутки загруженного изображения достаточно разместить PictureBox на элементе Panel с установленным свойством AutoScroll = true (и Dock = Fill , если панель должна занимать всю клиентскую часть окна) и при этом для PictureBox указать SizeMode = AutoSize . После этого можно загрузить рисунок кодом вида
Image Img = new Bitmap(openFileDialog1.FileName); pictureBox1.Image = Img;
- ErrorImage — позволяет задать изображение, выводимое при ошибке загрузки;
- InitialImage — позволяет задать изображение, выводимое в процессе загрузки.
- ImageList (вкладка Компоненты) — список изображений, который можно использовать для «прокрутки» картинок или как список иконок для меню, вкладок и т.п.
- Timer (вкладка Компоненты), позволяет обрабатывать периодическое событие Tick и организовывать смену картинок в реальном времени, частота повторения события в миллисекундах задаётся свойством Interval .
Мы используем их в следующей теме.
Проект Lab5_2. Основные операции над изображениями. Кроме pictureBox1 , размещённого на Panel как описано выше, форма включает в себя стандартный диалог открытия файла openFileDialog1 , меню Файл — Открыть (обработчик аналогичен предыдущему примеру) и меню «Правка», откуда мы будем вызывать обработчики загруженного изображения.
5.2.1. Поворот и отражение изображений. В этом примере выведенный в PictureBox рисунок поворачивается на 180 градусов и выводится обратно в PictureBox :
if (pictureBox1.Image != null) < Bitmap bitmap1 = new Bitmap(pictureBox1.Image); if (bitmap1 != null) < bitmap1.RotateFlip(RotateFlipType.Rotate180FlipY); pictureBox1.Image = bitmap1; >>
Остальные повороты (отражения) – другие значения параметра RotateFlipType .
5.2.2. Масштабирование изображения или его части. Код ниже показывает, как можно программно уменьшить загруженное в компоненту PictureBox изображение в 2 раза:
if (pictureBox1.Image == null) return; Bitmap bitmap1 = new Bitmap (pictureBox1.Image); //взяли рисунок из компоненты Graphics Gr1 = Graphics.FromImage (bitmap1); //получили поверхность рисования из исходного рисунка Bitmap bitmap2 = new Bitmap (bitmap1.Width / 2, bitmap1.Height / 2, Gr1); //сделали вдвое меньший рисунок с тем же разрешением Graphics Gr2 = Graphics.FromImage (bitmap2); //получили поверхность рисования из меньшего рисунка Rectangle compressionRectangle = new Rectangle (0, 0, bitmap1.Width / 2, bitmap1.Height / 2); //определили масштабирующий прямоугольник Gr2.DrawImage (bitmap1, compressionRectangle); //отрисовали на поверхности второго рисунка первый со сжатием Pen MyPen = new Pen (Color.Red); //на измененном рисунке можно что-то подрисовать Gr2.DrawRectangle (MyPen, 0, 0, bitmap2.Width - 1, bitmap2.Height - 1); //например, сделать красную рамку pictureBox1.Image = bitmap2; //назначили второй рисунок компоненте pictureBox1.Size = bitmap2.Size; //поставили размер компоненты по размерам нового рисунка this.ClientSize = pictureBox1.Size; //. и такой же размер клиентской формы
Добавим пункт меню Файл — Сохранить и сохраним изображение:
if (pictureBox1.Image == null) return; Bitmap bitmap1 = new Bitmap (pictureBox1.Image); try < bitmap1.Save (openFileDialog1.FileName); //Сохраняем под именем из диалога открытия файла //Может вызвать исключение, если исходный файл ещё открыт >catch (Exception ex)
pictureBox1.Image.Save (openFileDialog1.FileName);
К сожалению, этот код может вызвать исключение, если исходный файл ещё открыт. Для «надёжных» операций с файлами при открытии изображений используйте FileStream , чтобы контролировать весь процесс (перепишем обработчик пункта меню «Открыть»):
openFileDialog1.ShowDialog (); if (openFileDialog1.FileName.Trim () != "" && openFileDialog1.FileName != null) < System.IO.FileStream file; try < file = new System.IO.FileStream (openFileDialog1.FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Inheritable); >catch (Exception ex) < MessageBox.Show (ex.Message + "\nНе удалось открыть файл", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; >pictureBox1.Image = Image.FromStream (file); file.Close (); >
5.2.3. Изменение цвета на изображении. На форму добавлен стандартный СolorDialog и выбранный в нём цвет ставится прозрачным.
if (pictureBox1.Image == null) return; Bitmap bitmap1 = new Bitmap (pictureBox1.Image); if (colorDialog1.ShowDialog () == DialogResult.OK)
5.2.4. Фильтрация всего изображения или его части (по пикселям). В качестве примера уменьшим вдвое интенсивность синего цвета на картинке, избегая пикселей, цвет которых близок к белому (интенсивности красной, зелёной и синей компонент больше значения 250):
if (pictureBox1.Image == null) return; Bitmap bitmap1 = new Bitmap (pictureBox1.Image); for (int x = 0; x < bitmap1.Width; x++) for (int y = 0; y < bitmap1.Height; y++) < Color pixelColor = bitmap1.GetPixel (x, y); if (pixelColor.R >250 && pixelColor.G > 250 && pixelColor.B > 250) continue; //не фильтруем пиксели, чей цвет близок к белому Color newColor = Color.FromArgb (pixelColor.R, pixelColor.G, pixelColor.B / 2); bitmap1.SetPixel (x, y, newColor); > pictureBox1.Image = bitmap1;
Аналогично можно реализовать любую другую фильтрацию цветов, но из-за «ручного» прохода по пикселям скорость выполнения процесса может быть заметно ниже, чем для пп. 5.2.1-5.2.3. Более быстрый способ преобразования всех цветов рисунка даёт применение фильтрации на основе класса ColorMatrix . В качестве примера приведём код, преобразующий цветное изображение к оттенкам серого:
if (pictureBox1.Image == null) return; Bitmap bitmap1 = new Bitmap (pictureBox1.Image); Bitmap bitmap2 = new Bitmap (bitmap1.Width, bitmap1.Height); Graphics g = Graphics.FromImage (bitmap2); float [] [] Map = < new float[] , new float[] , new float[] , new float[] , new float[] >; System.Drawing.Imaging.ColorMatrix GrayscaleMatrix = new System.Drawing.Imaging.ColorMatrix (Map); System.Drawing.Imaging.ImageAttributes attributes = new System.Drawing.Imaging.ImageAttributes (); attributes.SetColorMatrix (GrayscaleMatrix); Rectangle rect = new Rectangle (0, 0, bitmap1.Width, bitmap1.Height); g.DrawImage (bitmap1, rect, 0, 0, bitmap1.Width, bitmap1.Height, GraphicsUnit.Pixel, attributes); pictureBox1.Image = bitmap2;
О классе ColorMatrix можно почитать, например, по ссылке. В нашем фильтре соотношение «весов» красной, зелёной и синей цветовых компонент 0.3 — 0.59 — 0.11 отражает чувствительность человеческого глаза к оттенкам красного, зелёного и синего.
В некоторых случаях фильтровать изображения можно и сменой свойства Image.PixelFormat , но вариант Format16bppGrayScale в GDI+ не сработал.
5.2.5. Сохранить рисунок так, как он выглядит на компоненте. Следует понимать, что свойство SizeMode управляет отображением рисунка в компоненте, при сохранении пропорции рисунка не изменятся от того, что он был выведен, например, при SizeMode=StretchImage (принудительно растянут по размерам компоненты, возможно, с нарушением пропорций). Тем не менее — а можно ли сохранить рисунок так, как он был выведен в компоненту? Да, можно, например, так:
if (pictureBox1.Image == null) return; pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; pictureBox1.Dock = DockStyle.Fill; //установили растягивание Bitmap bitmap1 = new Bitmap (pictureBox1.Image); Bitmap bitmap2 = new Bitmap (pictureBox1.Width, pictureBox1.Height); //у 2-го рисунка - размер компоненты Graphics g = Graphics.FromImage (bitmap2); //получили графический контекст из 2-го рисунка g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bicubic; //настроили режим интерполяции g.DrawImage (bitmap1, new Rectangle(0,0, bitmap2.Width, bitmap2.Height)); //отрисовали в контекст 2-го рисунка исходный, неискажённый рисунок pictureBox1.Image = bitmap2; //назначили искажённый рисунок компоненте сохранитьToolStripMenuItem_Click (this, e); //вызвали метод сохранения pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize; pictureBox1.Dock = DockStyle.None; //восстановили свойства pictureBox1.Image = bitmap1; //вернули старый рисунок
Убедиться в том, что рисунок был пересохранён в фоновом режиме с размерами, соответствующими клиентской части формы можно, заново открыв его с диска.
5.2.6. Выделить часть рисунка и реализовать обрезку по выделенной области. В класс формы добавим следующие глобальные данные:
Rectangle selRect; //выделенный прямоугольник Point orig; //точка для привязки прямоугольника Pen pen; //перо для отрисовки bool flag; //флажок показывает, находимся ли в режиме выделения части рисунка
Инициализируем их, например, в имеющемся конструкторе формы:
public Form1() < InitializeComponent(); pen = new Pen (Brushes.Blue, 0.8f); //цвет и толщина линии выделения pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; //штрихи selRect = new Rectangle (0, 0, 0, 0); flag = false; >
Реализация динамического выделения мышью потребует взаимодействия нескольких событий (нажатие кнопки мыши, отпускание кнопки мыши и перемещение мыши). Для удобства используем также динамическое переключение обработчика события Paint (чтобы рисовать рамку выделения только тогда, когда она нужна – происходит перемещение курсора мыши на pictureBox при зажатой левой кнопке).
private void pictureBox1_Paint (object sender, PaintEventArgs e) < //Этот обработчик мы создали в конструкторе //Для ситуации, когда выделяем рамку e.Graphics.DrawRectangle (Pens.Black, selRect); >private void Selection_Paint (object sender, PaintEventArgs e) < //Добавили свой обработчик Paint для остальных ситуаций e.Graphics.DrawRectangle (pen, selRect); >private void pictureBox1_MouseDown (object sender, MouseEventArgs e) < //Этот обработчик мы создали в конструкторе //Нажали мышку - включаем наш обработчик и выключаем стандартный pictureBox1.Paint -= new PaintEventHandler (pictureBox1_Paint); pictureBox1.Paint += new PaintEventHandler (Selection_Paint); orig = e.Location; //запомнили, где начало выделения flag = true; >private void pictureBox1_MouseUp (object sender, MouseEventArgs e) < //Этот обработчик мы создали в конструкторе //отжали мышку - всё наоборот pictureBox1.Paint -= new PaintEventHandler (Selection_Paint); pictureBox1.Paint += new PaintEventHandler (pictureBox1_Paint); pictureBox1.Invalidate (); //принудительно перерисовать flag = false; //выйти из режима выделения >private void pictureBox1_MouseMove (object sender, MouseEventArgs e) < //Этот обработчик мы создали в конструкторе if (flag) < //если в режиме выделения selRect = GetSelectionRectangle (orig, e.Location); //запоминаем выделенное if (e.Button == MouseButtons.Left) < pictureBox1.Refresh (); //рефрешим картинку по нажатию левой кнопки >> > private Rectangle GetSelectionRectangle (Point orig, Point location) < //Этот метод пришлось написать, чтобы координаты выделения правильно запоминались //независимо от того, в какую сторону тащим курсор мыши Rectangle rect = new Rectangle (); int dX = location.X - orig.X, dY = location.Y - orig.Y; System.Drawing.Size size = new System.Drawing.Size (Math.Abs (dX), Math.Abs (dY)); //размеры текущего выделения if (dX >= 0 && dY >= 0) rect = new Rectangle (orig, size); else if (dX < 0 && dY >0) rect = new Rectangle (location.X, orig.Y, size.Width, size.Height); else if (dX > 0 && dY
Теперь, при наличии на изображении выделенной рамки selRect можно, например, реализовать его обрезание по границам этой рамки:
if (pictureBox1.Image == null) return; if (selRect.Width > 0 && selRect.Height > 0)
Проект Lab5_3. Рисование фигур. Показанный выше подход нетрудно применить для рисования геометрических примитивов на канве PictureBox или формы.
Создадим форму как в предыдущем примере с PictureBox , расположенным на Label , у компонент установлены те же свойства.
Рассмотрим варианты рисования линии на канве PictureBox . При движении мыши с зажатой левой кнопкой наша линия должна динамически обновляться, а при отпускании кнопки — добавляться на существующий рисунок.
Опишем в классе формы необходимые данные:
Point p1, p2; //начало и конец линии Pen pen1; //перо Brush brush1; //кисть Bitmap Img1, Img2; //основная картинка, на которой рисуем и буферная Graphics gr; //графический контекст bool isPressed; //флажок "кнопка мыши зажата"
Для самой формы нам понадобится запрограммировать событие Load , где мы инициализируем эти объекты, то есть, создадим рисунок размером с клиентскую часть окна формы, назначим его компоненте, создадим перо и выставим в «ложь» флажок:
Img1 = new Bitmap (ClientSize.Width, ClientSize.Height); pictureBox1.Image = Img1; gr = Graphics.FromImage (Img1); pen1 = new Pen (Color.Black); isPressed = false;
Всё остальное запрограммируем в событиях PictureBox . На нажатие кнопки мыши будем включать флажок и запоминать место клика p1 :
private void pictureBox1_MouseDown (object sender, MouseEventArgs e)
На отпускание кнопки получим координаты второй точки p2 и соединим её с первой, проведя линию на образе Img1 . Заметим, что в реальном коде можно добавлять точки в контейнер, например, в список List из объектов Point . Если при этом запоминать, какой именно объект рисовался, можно в нужные моменты просто перерисовывать объекты по списку (что может предотвратить «утечки памяти» при работе приложения), а также удалять или динамически изменять их.
private void pictureBox1_MouseUp (object sender, MouseEventArgs e)
На перемещение мыши обработка будет немного хитрей. Если кнопка не зажата, ничего делать не нужно, а в противном случае будем проводить текущую линию на копии рисунка Img2 , созданной из Img1 , чтобы не получилось «веера» из линий при перемещении мыши с зажатой кнопкой. Img2 всё равно придётся временно назначить рисунком для PictureBox , чтобы линия была видна в процессе движения мыши.
private void pictureBox1_MouseMove (object sender, MouseEventArgs e) < if (!isPressed) return; //Кнопка не зажата - выйти p2 = e.Location; Img2 = new Bitmap (Img1); pictureBox1.Image = Img2; gr = Graphics.FromImage (Img2); gr.DrawLine (pen1, p1, p2); pictureBox1.Invalidate (); >
В показанном примере все координаты отсчитывались «внутри PictureBox » и получались непосредственно из аргумента MouseEventArgs обработчика события. По-другому можно сделать, используя координаты курсора относительно экрана Cursor.Position.X , Cursor.Position.Y , а затем вычитая из них координаты верхнего левого угла формы Location.X , Location.Y (и, возможно, дополнительные значения, учитывающие занятое другими компонентами пространство на форме):
int x1 = Cursor.Position.X - Location.X, y1 = Cursor.Position.Y - Location.Y;
Расположив на панели инструментов приложения дополнительные кнопки для выбора геометрического примитива, цвета и т. п., мы можем получить приложение графический-редактор (см. прикреплённый проект, где ряд возможностей уже добавлен).
Обратите внимание в коде проекта Lab5_3: при рисовании линии и эллипса координаты второй точки могут быть и «меньше» (ближе к левому верхнему углу холста), чем первой. При рисовании же прямоугольника область экрана должна быть задана, начиная с левого верхнего угла. Метод GetRectangle , вызываемый при обработке событий pictureBox1_MouseUp и pictureBox1_MouseMove , корректирует эту проблему, как и при выделении прямоугольником в проекте Lab5_2.

Простая рисовалка на Windows Forms C#
Проект Lab5_4. Другой контекст. В завершение заметим, что отрисовка, выполняемая в объекте графического контекста, позволяет без каких-либо изменений основного кода «перенести» графический объект на другую канву, например, на экран вместо окна приложения.
Пусть в классе формы имеется метод Draw , создающий некоторый рисунок:
void Draw (System.Drawing.Graphics g) < //Графический контекст передан в наш метод Pen [] pens = < Pens.Red, Pens.Yellow, Pens.Green >; //Разные перья для рисования int width = ( this.ClientSize.Width - 1 ) / 2, height = ( this.ClientSize.Height - 1 ) / 2; //Половинки ширины и высоты клиентской части окна for (int i = 0; i < 3; i++) //Демо - рисуем перьями g.DrawRectangle (pens [i], i * width, i * height, width, height); Brush [] brushes = < Brushes.Red, Brushes.Yellow, Brushes.Green >; //Разные кисти для выполнения заливки цветом for (int i = 0; i < 3; i++) //Демо - рисуем кистями g.FillEllipse (brushes [i], i * width, i * height, width, height); g.DrawLine (pens [2], 0, 0, width * 2, height * 2); //Рисуем линию пером >
Как и в начале статьи, мы могли бы вызвать его кодом вида
Graphics g = this.CreateGraphics (); Draw (g);
для отображения картинки непосредственно на канве формы.
Теперь выведем рисунок в контексте графического экрана Windows поверх всех окон.
Убедимся, что к файлу формы подключены нужные пространства имён:
using System.Runtime.InteropServices; using System.Drawing;
В классе формы (например, после конструктора) укажем ссылки на нужные методы библиотеки user32.dll , которые нам потребуются:
[DllImport ("user32.dll")] public static extern IntPtr GetDC (IntPtr hwnd); [DllImport ("user32.dll")] public static extern void ReleaseDC (IntPtr hwnd, IntPtr dc);
В методе рисования (например, по событию Paint формы) вызовем наш метод с другим контекстом:
private void Form1_Paint (object sender, PaintEventArgs e)
Также можно потребовать где-нибудь принудительной перерисовки, например, по клику на форме:
private void Form1_Click (object sender, EventArgs e)
- в верхнем меню выбрать команду Проект — Добавить существующий элемент. ;
- в списке типов файлов выбрать «Исполняемые файлы», показать расположение нужного файла ( c:\Windows\System32\user32.dll ) и нажать «Добавить»;
- выбрать добавленный файл в Обозревателе решений, в окне «Свойства» указать для него значение «Копировать в выходной каталог» равным «Копировать более новую версию»;
- после этого прототипы нужных функций библиотеки можно описать в классе формы с атрибутами public static extern и предшествующей директивой [DllImport («user32.dll»)] , как мы делали выше.
- сохранение полученных графических файлов;
- прокрутка файлов, если они «не помещаются» в окне компоненты PictureBox ;
- возможность построить изображение более, чем в одном масштабе (или масштабировать его программно);
- не менее двух настраиваемых параметров, позволяющих изменить внешний вид объекта (например, для объекта «дом» — количество этажей и количество окон на каждом этаже).
05.04.2023, 19:26 [2360 просмотров]
