Создание графического приложения
Последнее обновление: 13.11.2021
Графический редактор Windows Forms
Одним из преимуществ разработки в Visual Studio приложений Windows Forms является наличие графического редактора, который позволяет в графическом виде представить
создаваемую форму и в принципе упрощает работу с графическими компонентами.
Для открытия формы в режиме графического дизайнера нажмем на в структуре проекта на файл Form1.cs либо левой кнопкой мыши двойным кликом,
либо правой кнопкой мыши и в появившемся контекстном меню выберем View Designer (также можно использовать комбинацию клавиш Shift+F7)
После этого в Visual Studio откроется выбранная форма в графическом виде.
В то же время следует отметить, что на более слабых компьютерах окно дизайнера можно открываться довольно долго, а на некоторых — довольно слабых компьютерах может и вообще не открыться.
При выборе формы в окне дизайнера внизу справа под структурой проекта мы сможем найти окно Properties(Свойства).
Так как у меня в данный момент выбрана форма как элемент управления, то в этом поле отображаются свойства, связанные с формой.
Теперь найдем в этом окне свойство формы Text и изменим его значение на любое другое:
Таким образом мы поменяли заголовок формы. И подобным образом мы можем поменять другие свойства формы, которые доступны в окне свойств.
Но Visual Studio имеет еще одну связанную функциональность. Она обладает панелью графических инструментов. И мы можем, вместо создания элементов управления в коде C#,
просто переносить их на форму с панели инструментов с помощь мыши. Так, перенесем на форму какой-нибудь элемент управления, например, кнопку. Для этого
найдем в левой части Visual Studio вкладку Toolbox (Панель инструментов). Нажмем на эту вкладку, и у нас откроется панель с элементами,
откуда мы можем с помощью мыши перенести на форму любой элемент:
Найдем среди элементов кнопку и, захватив ее указателем мыши, перенесем на форму:
Причем при выборе кнопки она открывается в окне свойств и, как и для всей формы, для кнопки в окне свойств мы можем изменить значения различных свойств.
Кроме того, если после переноса кнопки на форму мы откроем файл Form1.
namespace HelloApp { partial class Form1 { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // // button1 // this.button1.Location = new System.Drawing.Point(312, 187); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(94, 29); this.button1.TabIndex = 0; this.button1.Text = "button1"; this.button1.UseVisualStyleBackColor = true; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(800, 450); this.Controls.Add(this.button1); this.Name = "Form1"; this.Text = "METANIT.COM"; this.ResumeLayout(false); } #endregion private Button button1; } }
Мы видим, что в класс Form1 была добавлена переменная button1
типа Button и для этой переменной, как и для объекта формы, задан ряд свойств.
И если в окне свойств мы поменяем значения этих свойств, то в этом файле также изменяться их значения. Как в случае с текстом формы:
this.Text = "METANIT.COM";
Это визуальная часть. Теперь приступим к самому программированию. Добавим простейший код на языке C#, который бы выводил сообщение по нажатию кнопки.
Для этого перейдем в файл кода Form1.cs, который связан с этой формой. По умолчанию после создания проекта он имеет код типа следующего:
namespace HelloApp { public partial class Form1 : Form { public Form1() { InitializeComponent(); } } }
Изменим этот код следующим образом:
namespace HelloApp { public partial class Form1 : Form { public Form1() { InitializeComponent(); button1.Click += button1_Click; } private void button1_Click(object? sender, EventArgs e) { MessageBox.Show("Привет"); } } }
Кнопка обладает событием Click, которое генерируется при нажатии. В данном случае в конструкторе формы мы подвязываем к кнопке button1 в качестве обработчика события
нажатия метод button1_Click
, в котором с помощью метода MessageBox.Show выводит сообщение. Текст сообщения передается в метод в качестве параметра.
Стоит отметить, что графический дизайнер позволяет автоматически сгенерировать обработчик нажатия кнопки. Для этого надо
в окне дизайнера нажать на кнопку на форме двойным щелчком мыши.
Теперь запустим проект и мы увидим форму с кнопкой, на которую мы можем нажать и получить сообщение:
Provide feedback
Saved searches
Use saved searches to filter your results more quickly
Sign up
Appearance settings
💥 Похожие видео
Paint Application in C# Visual Studio By Rohit Programming ZoneСкачать
C# .NET Windows Form | СОЗДАЁМ PAINT НА C#Скачать
Секреты программы Paint, о которых ты не знал !Скачать
Создаем свой векторный графический редактор на C# с нуля урок 1Скачать
Рисуем ГРАФИКИ и пишем КОД — Маленький проектСкачать
C# №15 Программируем собственный Paint #2Скачать
🌟 Дополнительные видео
Уроки C# / Как сделать первое Windows приложениеСкачать
Создаём текстовый редактор на C# Windows FormsСкачать
C# №14 Программируем собственный Paint #1Скачать
C#: работаем с графикой и графическими компонентами в приложениях Windows Forms
Для работы с изображениями в библиотеке .NET определён базовый класс System.Drawing.Image
, который предоставляет функциональные возможности для производных классов System.Drawing.Bitmap
(растровая графика) и System.Drawing.MetaFile
(векторная графика). Этот класс содержит методы для создания (и сохранения) объектов типа Image
из указанного файла, потока данных и т.д.
Когда требуется перерисовка элемента управления, происходит событие Paint
, которое, в зависимости от задачи, можно как программировать явно, так и полагаться на его автоматический вызов, происходящий, когда изменилась графическая канва объекта.
Для отрисовки готового файла с изображением, имя которого задано или получено из диалога открытия файла OpenFileDialog
, мы должны создать или получить из аргумента PaintEventArgs
метода Paint
графическую канву типа System.Drawing.Graphics
а затем уже вывести на неё изображение.
Графическая канва позволяет посредством инструментов типов Pen
(перо), Brush
(кисть) и других работать с методами рисования контурных и залитых цветом геометрических примитивов, имена первых начинаются префиксом «Draw», а вторых «Fill». При этом код отрисовки не будет меняться в зависимости от того, создана графика для поверхности формы методом CreateGraphics
или получена из изображения с помощью метода FromImage
.
Для использования готовых методов обработки изображений (поворот, масштабирование, изменение цвета и т.п.) мы программно создаём объект типа 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) { Graphics g = this.CreateGraphics(); Point p = new Point(0, menuStrip1.Size.Height + toolStripLabel1.Size.Height); g.DrawImage(Img, p); }
или из загруженного (сгенерированного) изображения, например, см. код для пункта меню Файл — Создать:
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();
Обычно рисунки не отображают на канве формы, а работают с компонентом PictureBox
(вкладка Стандартные), представляющим собой контейнер для размещения рисунка, вот его основные свойства:
Image
— рисунок. Само изображение можно загрузить программно через свойствоImageLocation
, например, в методеLoad
формы:openFileDialog1.ShowDialog(); if (openFileDialog1.FileName != null) this.pictureBox1.ImageLocation = this.openFileDialog1.FileName;
или же присвоить этому свойству объект
Image
, как мы делали выше.SizeMode
— режим вывода:Normal
— по левому верхнему углу контейнера с обрезанием,StretchImage
— вписать в компонент,AutoSize
— компонент примет размеры изображения,CenterImage
— центрировать, не меняя размеры (может обрезать рисунок),Zoom
— пропорционально масштабировать по размерам компонента (пространство именPictureBoxSizeMode
).
Для возможности прокрутки загруженного изображения достаточно разместить PictureBox
на элементе Panel
с установленными свойствами AutoScroll = true
, Location = 0;0
(и Dock = Fill
, если панель должна занимать всю клиентскую часть окна) и при этом для PictureBox
указать SizeMode = AutoSize
. После этого можно загрузить рисунок кодом вида
Image Img = new Bitmap(openFileDialog1.FileName); pictureBox1.Image = Img;
ErrorImage
— позволяет задать изображение, выводимое при ошибке загрузки;InitialImage
— позволяет задать изображение, выводимое в процессе загрузки.
К другим полезным компонентам можно отнести:
ImageList
(вкладка Компоненты) — список изображений, который можно использовать для «прокрутки» картинок или как список иконок для меню, вкладок и т.п.Timer
(вкладка Компоненты), позволяет обрабатывать периодическое событиеTick
и организовывать смену картинок в реальном времени, частота повторения события в миллисекундах задаётся свойствомInterval
.
Мы используем их в следующей теме.
Скачать пример Lab5_1 в архиве .zip с проектом C# Visual Studio 2019 (12 Кб)
Проект 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) { MessageBox.Show (ex.Message + "\nНе удалось сохранить файл", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; }
Как вариант:
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) { bitmap1.MakeTransparent (colorDialog1.Color); pictureBox1.Image = bitmap1; }
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[] {0.30f, 0.30f, 0.30f, 0.00f, 0.00f }, new float[] {0.59f, 0.59f, 0.59f, 0.00f, 0.00f }, new float[] {0.11f, 0.11f, 0.11f, 0.00f, 0.00f }, new float[] {0.00f, 0.00f, 0.00f, 1.00f, 0.00f }, new float[] {0.00f, 0.00f, 0.00f, 0.00f, 1.00f } }; 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 < 0) rect = new Rectangle (orig.X, location.Y, size.Width, size.Height); else rect = new Rectangle (location, size); return rect; }
Теперь, при наличии на изображении выделенной рамки selRect
можно, например, реализовать его обрезание по границам этой рамки:
if (pictureBox1.Image == null) return; if (selRect.Width > 0 && selRect.Height > 0) { Bitmap bitmap1 = new Bitmap (pictureBox1.Image); Bitmap bitmap2 = new Bitmap (selRect.Width, selRect.Height); Graphics g = Graphics.FromImage (bitmap2); g.DrawImage (bitmap1, 0, 0, selRect, GraphicsUnit.Pixel); pictureBox1.Image = bitmap2; selRect = new Rectangle (0, 0, 0, 0); }
Скачать пример Lab5_2 в архиве .zip с проектом C# Visual Studio 2019 (14 Кб)
Проект Lab5_3. Рисование фигур. Показанный выше подход нетрудно применить для рисования геометрических примитивов на канве PictureBox
или формы.
Создадим форму как в предыдущем примере с PictureBox
, расположенным на Panel
, у компонент установлены те же свойства (для PictureBox дополнительно укажем Dock = Fill
).
Рассмотрим варианты рисования линии на канве 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) { isPressed = true; p1 = e.Location; }
На отпускание кнопки получим координаты второй точки p2
и соединим её с первой, проведя линию на образе Img1
. Заметим, что в реальном коде можно добавлять точки в контейнер, например, в список List
из объектов Point
. Если при этом запоминать, какой именно объект рисовался, можно в нужные моменты просто перерисовывать объекты по списку (что может предотвратить «утечки памяти» при работе приложения), а также удалять или динамически изменять их.
private void pictureBox1_MouseUp (object sender, MouseEventArgs e) { p2 = e.Location; gr = Graphics.FromImage (Img1); gr.DrawLine (pen1, p1, p2); gr.Save (); isPressed = false; pictureBox1.Invalidate (); }
На перемещение мыши обработка будет немного хитрей. Если кнопка не зажата, ничего делать не нужно, а в противном случае будем проводить текущую линию на копии рисунка 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.
Скачать пример Lab5_3 в архиве .zip с проектом C# Visual Studio 2019 (19 Кб)
Простая рисовалка на 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) { IntPtr desktopPtr = GetDC (IntPtr.Zero); Graphics g = Graphics.FromHdc (desktopPtr); Draw (g); g.Dispose (); ReleaseDC (IntPtr.Zero, desktopPtr); }
Также можно потребовать где-нибудь принудительной перерисовки, например, по клику на форме:
private void Form1_Click (object sender, EventArgs e) { Invalidate (); }
Подключить к проекту внешнюю библиотеку можно и непосредственно, например, для нашего случая:
- в верхнем меню выбрать команду Проект — Добавить существующий элемент…;
- в списке типов файлов выбрать «Исполняемые файлы», показать расположение нужного файла (
c:\Windows\System32\user32.dll
) и нажать «Добавить»;- выбрать добавленный файл в Обозревателе решений, в окне «Свойства» указать для него значение «Копировать в выходной каталог» равным «Копировать более новую версию»;
- после этого прототипы нужных функций библиотеки можно описать в классе формы с атрибутами
public static extern
и предшествующей директивой[DllImport ("user32.dll")]
, как мы делали выше.
Скачать пример Lab5_4 в архиве .zip с проектом C# Visual Studio 2019 (11 Кб)
Задание по теме может быть, например, таким: реализовать графическое приложение в соответствии с вариантом. Предусмотреть в приложении следующие возможности:
- сохранение полученных графических файлов;
- прокрутка файлов, если они «не помещаются» в окне компоненты
PictureBox
; - возможность построить изображение более, чем в одном масштабе (или масштабировать его программно);
- не менее двух настраиваемых параметров, позволяющих изменить внешний вид объекта (например, для объекта «дом» — количество этажей и количество окон на каждом этаже).
05.04.2023, 19:26 [8692 просмотра]
К этой статье пока нет комментариев, Ваш будет первым
Содержание
- Графический редактор
- Графический редактор C#
- Решение
- Объекты Graphics и Drawing в Windows Forms Graphics and Drawing in Windows Forms
- в этом разделе In This Section
- Справочник Reference
- Связанные разделы Related Sections
- Простейший графический редактор
- Написание графического редактора
Графический редактор
Графический редактор
Всем привет! Надо написать графический редактор на C# ( курсовая работа ) Минимальный набор.
Графический редактор
Мне задали Лабу.Графический редактор.Вот содержание лабы. В конце дано задание из 6.
Графический редактор
Добрый день! Помогите, пожалуйста создать такое приложение. На форме расположена область, в.
Графический редактор
Помогите пожалуйста.Графический редактор. Напишите программу — редактор графики, аналог Paint.
Вложения
Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.
Графический редактор C#
Здравствуйте, задали такое задание, написать графический редактор, писать надо с элементами ООП, то.
Графический редактор
рисую елементарные примитив (к примеру прямоугольник) в MouseDown запоминаю начальные координаты.
Простейший графический редактор
Здравствуйте уважаемые форумчане. Нужна ваша помощь. Создаю простейший графический редактор.
Графический редактор — выбор инструментов
Здравствуйте читающим. Написал программу мини графический редактор. Основными инструментами.
Графический редактор с интерфейсом MDI
Абсолютно нет времени на изучение MDI. Надеюсь кто-нибудь поможет до завтра.
Написать простейший графический редактор
Необходимо сделать такой себе мини редактор в котором можно добавлять круги, квадраты, текст. И.
Графический редактор C#
Вложения
OOPKursovoi.rar (179.6 Кб, 41 просмотров) |
Графический редактор
Запуталась совсем что натворила (( Хотела создать что то вреде Paint но запуталась что творю . .
Графический редактор
рисую елементарные примитив (к примеру прямоугольник) в MouseDown запоминаю начальные координаты.
Графический редактор на С#
Можете выложить пример графического редактора типапаинт на си шарп. Р.S Не выкладывайте исходники.
Графический редактор
Мне задали Лабу.Графический редактор.Вот содержание лабы. В конце дано задание из 6.
Сударь, как вы вообще умудрились до курсового доучиться? Сделанные косяки выдают полное непонимание предмета работы. Я даже не знаю с чего начать перечисление ошибок. У вас сам принцип использования классов некорректен.
1. Снести всё уже написанное — это лютая дичь.
2. Сесть за тетрадку, и нарисовать общую схему классов проекта — какие они будут, где будут использоваться, зачем они нужны, кому будут наследовать, и от кого будут наследоваться. А, раз уж задание такое расплывчатое — извращаться можно по максимуму. Чисто навскидку:
— Создаём класс Figure. Он будет содержать базовые параметры, такие как координаты, высоту и ширину фигуры. Ещё можно добавить цвет заливки и цвет обводки.
— От него наследуем классы разных конкретных фигур — круга, линии, квадрата и т.п. Дочерние классы по сути будут просто отрисовывать на предоставленном полотне фигуру.
— Создаём класс Canvas. Это будет полотно рисования, в котором будет список фигур и метод перерисовки. Плюс — методы добавления или удаления фигуры из списка.
3. В классе формы создаём и инициализируем экземпляр класса Canvas. Делаем всякие рюшечки для выбора фигуры цвета и т.п. Ну и дописываем само рисование, которое будет заключаться в добавлении фигуры в список, при отпускании кнопки мыши. Ну и перерисовку Canvas.
То что написано выше — это крайне примерный план того как нужно эту задачу выполнять.
А, ну и чисто вдогонку. Не рисуется квадрат у вас потому, что вы при каждой инициализации класса Square создаёте новый экземпляр формы (который просто не отображается, т.к. не был вызвае form.Show()), на котором и рисуете свой квадрат.
Решение
Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.
Графический редактор
Помогите пожалуйста.Графический редактор. Напишите программу — редактор графики, аналог Paint.
Графический редактор
Ребята, подскажите как реализовать рисование прямоугольника как в Paint. т.е. пока левая кнопка.
Графический редактор
Хочу написать графический редактор в C#. Встал вопрос о панели инструментов. В фотошопе эта.
Графический редактор
Здраствуйте. Подскажите пожайлуста как можно осуществить следующие. Я хочу написать простенький.
Объекты Graphics и Drawing в Windows Forms Graphics and Drawing in Windows Forms
Среда CLR использует расширенную реализацию Windows интерфейс графических устройств (GDI) с именем GDI+. The common language runtime uses an advanced implementation of the Windows Graphics Device Interface (GDI) called GDI+. С помощью GDI+ можно создавать графики, рисовать текст и манипулировать графическими изображениями как объектами. With GDI+ you can create graphics, draw text, and manipulate graphical images as objects. Интерфейс GDI+ обеспечивает производительность и простоту использования. GDI+ is designed to offer performance and ease of use. GDI+ можно использовать для отрисовки графических изображений на Windows Forms и элементы управления. You can use GDI+ to render graphical images on Windows Forms and controls. Хотя вы не можете использовать GDI+ непосредственно в веб-формах, можно отображать графические изображения с помощью серверного веб-элемента управления Image. Although you cannot use GDI+ directly on Web Forms, you can display graphical images through the Image Web Server control.
В этом разделе вы найдете разделы, в которых представлены основные принципы программирования GDI+. In this section, you will find topics that introduce the fundamentals of GDI+ programming. Хотя он не является полным справочником, в нем содержатся сведения об объектах Graphics, Pen, Brush и Color и способах выполнения таких задач, как рисование фигур, создание текста, отображение рисунков. Although not intended to be a comprehensive reference, this section includes information about the Graphics, Pen, Brush, and Color objects, and explains how to perform such tasks as drawing shapes, drawing text, or displaying images. Дополнительные сведения см. в справочнике по GDI+. For more information, see GDI+ Reference.
Если вы хотите немедленно приступить к работе, см. статью Приступая к программированию графики. If you’d like to jump in and get started right away, see Getting Started with Graphics Programming. Она содержит разделы, посвященные использованию кода для рисования линий, фигур, текста и других элементов в формах Windows Forms. It has topics on how to use code to draw lines, shapes, text, and more on Windows forms.
в этом разделе In This Section
Общие сведения о графике Graphics Overview
Общие сведения об управляемых классах, связанных с графикой. Provides an introduction to the graphics-related managed classes.
Управляемый код GDI+ About GDI+ Managed Code
Предоставляет сведения об управляемых классах GDI+. Provides information about the managed GDI+ classes.
Использование управляемых графических классов Using Managed Graphics Classes
Демонстрирует выполнение различных задач с помощью управляемых классов GDI+. Demonstrates how to complete a variety of tasks using the GDI+ managed classes.
Справочник Reference
System.Drawing
Предоставляет доступ к основным графическим функциям GDI+. Provides access to GDI+ basic graphics functionality.
System.Drawing.Drawing2D
Расширенные функциональные возможности для создания двухмерной и векторной графики. Provides advanced two-dimensional and vector graphics functionality.
System.Drawing.Imaging
Предоставляет расширенные графические функции GDI+. Provides advanced GDI+ imaging functionality.
System.Drawing.Text
Предоставляет расширенный набор типографических функций GDI+. Provides advanced GDI+ typography functionality. Классы в этом пространстве имен позволяют создавать и использовать коллекции шрифтов. The classes in this namespace can be used to create and use collections of fonts.
System.Drawing.Printing
Функции печати. Provides printing functionality.
Рисование и отрисовка пользовательского элемента управления Custom Control Painting and Rendering
Подробные сведения о способах написания кода для рисования элементов управления. Details how to provide code for painting controls.
Простейший графический редактор
Написать простейший графический редактор
Необходимо сделать такой себе мини редактор в котором можно добавлять круги, квадраты, текст. И.
Как нарисовать точку в форме (простейший графический редактор)?
Решил сделать простейший графический редактор и встретился с проблемой, никак не могу реализовать.
Наложение фигур друг на друга (простейший графический редактор)
Всем доброго времени суток! Я создала простенький графический редактор, но у меня возникла.
Графический редактор
Всем привет! Надо написать графический редактор на C# ( курсовая работа ) Минимальный набор.
Вложения
ImageProcessing-source-code.zip (54.6 Кб, 132 просмотров) |
External Exception was unhandled.
В GDI+ возникла ошибка общего вида.
Пожалуйста помогите разобраться!
Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.
Графический редактор
Мне задали Лабу.Графический редактор.Вот содержание лабы. В конце дано задание из 6.
Графический редактор
Запуталась совсем что натворила (( Хотела создать что то вреде Paint но запуталась что творю . .
Графический редактор
рисую елементарные примитив (к примеру прямоугольник) в MouseDown запоминаю начальные координаты.
Графический редактор
Добрый день! Помогите, пожалуйста создать такое приложение. На форме расположена область, в.
Написание графического редактора
Создание графического редактора
Сам я начинаю только вникать в программирование(Windows Forms c#) Суть задания (большую часть я.
Создание простого графического редактора
Здравствуйте, форумчане! Нужна помощь по созданию графического редактора Много что посмотрел, но.
Разработка простейшего графического редактора
Всем привет. Постановка задачи заключается в написании простейшего графического редактора с.
Литература с примерами создания графического редактора
Подскажите доступную литературу, где описаны примеры создания графического редактора на С#.
Отрисовка дожна происходить в событии onPaint формы, иначе не будет перирисовывать ваша картинка. Т.е. при «загрязнении» (сворачивании, перемещении) формы, изображение исчезнет.
Вы должны создать экземпля класса.
В вашем случае:
nikooolay, там же в примере msdn все есть, даже с примером.
e.Graphics.DrawImage(newImage, rect);, где e- PainEventArgs = параметры для перерисовки формы.
Не нужно делать все методом тыка. Почти в любой книге по C# есть глава о GDI+. Или в том же msdn есть практические руководства.
ЧИТАЙТЕ ЛИТЕРАТУРУ!
Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.
С чего начать создание векторного графического редактора
Добрый день, уважаемые разработчики! Поделитесь, пожалуйста вашими мнениями, на некоторые вопросы.
Функция сдвига по определенной оси для графического редактора
Есть программа рисующая линии по списку вершин и списку ребер. В результате программа выводит.
Есть у кого-нибудь код графического редактора (типо Paint’a)?
Не смогу точно сделать графический редактор, возможно у Вас есть код и Вы сможете поделиться им.
Написание визуального HTML-редактора
Появилось желание написать простенький визуальный HTML редактор. Задумался над основным объектом-.