Search code examples
c#winformsopenfiledialog

How to draw multiple rectangles with mouse on an image?


I am trying to build a WinForm application that will load an image file from an openfiledialog and load it into either a panel or picturebox. I want to be able to draw multiple rectangles with the left mouse button and have them stay on the image. I have been successful in getting a single rectangle at a time on the actual form but not on an image inside a panel/picturebox. Does anyone know of a resource that would help me understand how to achieve this?

This is the code that allows me to draw a single resizable rectangle on the form, but when I change the mouse events from form1_MouseEvent to panel1_MouseEvent it does nothing..

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Temporary_Name_Utility
{
    public partial class Form1 : Form
    {
        Rectangle myRectangle;
        bool draw = false;


        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog myFile = new OpenFileDialog();
                myFile.Filter = "Image Files(*.img, *.bmp) |*.img; *.bmp;";
                myFile.InitialDirectory = "c:\\";

                if (myFile.ShowDialog() == DialogResult.OK)
                {
                    pictureBox1.BackgroundImage = Image.FromFile(myFile.FileName);
                }
            }

            catch (Exception error)
            {
                MessageBox.Show("Error loading the selected file.  Original error: " + error.Message);

            }

        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            myRectangle = new Rectangle(e.X, e.Y, 0, 0);
            this.Invalidate();
        }


        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if(draw)
            {
                using(Pen myPen = new Pen(Color.Red, 2))
                {
                    e.Graphics.DrawRectangle(myPen, myRectangle);
                }
            }
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                myRectangle = new Rectangle(myRectangle.Left, myRectangle.Top, Math.Min(e.X - myRectangle.Left, pictureBox1.ClientRectangle.Width - myRectangle.Left), Math.Min(e.Y - myRectangle.Top, pictureBox1.ClientRectangle.Height - myRectangle.Top));
            }
            this.Invalidate();
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {

        }

    }
}

Solution

  • Finally got some working code: This allows the user to draw as many rectangles as wanted with the mouse inside of the picturebox.

         using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Rectangle_Utility
    {
        public partial class Form1 : Form
        {
            Point startPos;
            Point currentPos;
            bool drawing;
            List<Rectangle> myRectangles = new List<Rectangle>();
    
            public Form1()
            {
                InitializeComponent();
                this.DoubleBuffered = true;
            }
    
            #region Menu Tool Strip
            private void selectFileToolStripMenuItem_Click(object sender, EventArgs e)
            {
                try
                {
                    //Initiate new OpenFileDialog
                    //Filter for img and bmp files
                    //Start looking in root of c:
                    OpenFileDialog myFile = new OpenFileDialog();
                    myFile.Filter = "Image Files(*.img, *.bmp) |*.img; *.bmp;";
                    myFile.InitialDirectory = "c:\\";
    
                    //Set background image of pictureBox to file selected through OpenFileDialog
                    if (myFile.ShowDialog() == DialogResult.OK)
                    {
                        pictureBox1.BackgroundImage = Image.FromFile(myFile.FileName);
    
                    }
                }
    
                catch (Exception error)
                {
                    MessageBox.Show("Error loading the selected file.  Original error: " + error.Message);
    
                }
            }
    
            private void exitToolStripMenuItem_Click(object sender, EventArgs e)
            {
                this.Close();
            }
    
            private void clearAllToolStripMenuItem_Click(object sender, EventArgs e)
            {
    
            }
    
            private void zoomToolStripMenuItem_Click(object sender, EventArgs e)
            {
    
            }
    
            private void undoLastActionToolStripMenuItem_Click(object sender, EventArgs e)
            {
    
            }
    
            private void redoLastActionToolStripMenuItem_Click(object sender, EventArgs e)
            {
    
            }
            #endregion
    
            #region Rectangle
    
            private Rectangle getRectangle()
            {
                return new Rectangle(
                    Math.Min(startPos.X, currentPos.X),
                    Math.Min(startPos.Y, currentPos.Y),
                    Math.Abs(startPos.X - currentPos.X),
                    Math.Abs(startPos.Y - currentPos.Y));
            }
    
            private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
            {
                if (e.Button == MouseButtons.Left)
                {
                    currentPos = startPos = e.Location;
                    drawing = true;
                }
    
            }
    
            private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
            {
                currentPos = e.Location;
                if (drawing) pictureBox1.Invalidate();
            }
    
            private void pictureBox1_Paint(object sender, PaintEventArgs e)
            {
                if (myRectangles.Count > 0) e.Graphics.DrawRectangles(Pens.Black, myRectangles.ToArray());
                if (drawing) e.Graphics.DrawRectangle(Pens.Red, getRectangle());
            }
    
            private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
            {
                if (drawing)
                {
                    drawing = false;
                    var rect = getRectangle();
                    if (rect.Width > 0 && rect.Height > 0) myRectangles.Add(rect);
                    pictureBox1.Invalidate();
                }
            }
    
            #endregion
    
        }
    }