none
Adding Drag/Drop/Resizable Selection Rectangle to Image Editor RRS feed

  • Question

  • Hi,

    I'm new to using C# (Express edition 2010) and am trying to use an Image Editor (Windows Form App) with available tutorials (http://howtoideas.net/how-to-crop-an-image-using-c) and source files/code (http://howtoideas.net/wp-content/uploads/C%20Sharp%20Source%20Codes/Image%20Processing%20-%20HowToIdeas.rar) to build my own.

    To make it easier for the user to select an area of a photo to crop, I would like to add a selection rectangle that can be re-sized, dragged, and once correctly positioned, get the rectangles top left x,y and bottom right x,y for use in the separate cropping action. This selection rectangle also needs to be on top of the pictureBox1 and transparent, but needs a visible border. Maybe call up the selection rectangle from a menu button ("select crop area").

    Have been searching online, reading, but haven't found any useful leads.

    Quite a challenge for a C# new user. :-)

    I would appreciate any suggestions, leads, sample code, etc.

    Much thanks.

    Kind Regards,

    saratogacoach

     



    Saturday, January 7, 2012 12:05 AM

Answers

  • Hi,

    here's a modified version of the example that lets you create the rectangle like before with the left mouseButton and move the rectangle with the right mouseButton:

        public partial class Form1 : Form
        {
            private PictureBox pictureBox1 = new PictureBox();
            private PictureBox pictureBox2 = new PictureBox();
    
            private Random _rnd = new Random();
            private Point _pt;
            private Point _ptOffset;
    
            private  Rectangle _r;
    
            public Form1()
            {
                InitializeComponent();
    
                //setup the Controls, usually done in design-mode
                this.ClientSize = new Size(624, 412);
                this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
    
                pictureBox1.ClientSize = new Size(400, 400);
                pictureBox1.Location = new Point(12, 6);
                //assign a - here- dynamically created - picture
                this.pictureBox1.Image = SetUpPictures(this.pictureBox1);
                this.pictureBox1.MouseDown += new MouseEventHandler(pictureBox2_MouseDown);
                this.pictureBox1.MouseMove += new MouseEventHandler(pictureBox2_MouseMove);
                this.pictureBox1.MouseUp += new MouseEventHandler(pictureBox2_MouseUp);
                this.pictureBox1.Paint += new PaintEventHandler(pictureBox2_Paint);
                this.Controls.Add(pictureBox1);
    
                pictureBox2.Location = new Point(418, 6);
                pictureBox2.ClientSize = new Size(200, 200);
                pictureBox2.SizeMode = PictureBoxSizeMode.Zoom;
                this.Controls.Add(pictureBox2);
    
                //cleanup, could also be handled in its event-handler method
                this.FormClosing += delegate
                {
                    foreach (Control c in this.Controls)
                        if (c is PictureBox)
                        {
                            PictureBox pb = (PictureBox)c;
                            if (pb.Image != null) pb.Image.Dispose();
                        }
                };
            }
    
            void pictureBox2_Paint(object sender, PaintEventArgs e)
            {
                //if we have a valid rectangle, draw it
                if (_r.Width > 0 && _r.Height > 0)
                {   
                    //fill
                    using(SolidBrush sb = new SolidBrush(Color.FromArgb(95, 255, 255, 255)))
                        e.Graphics.FillRectangle(sb, _r);
                    //draw
                    e.Graphics.DrawRectangle(Pens.Blue, _r);
                }
            }
    
            void pictureBox2_MouseDown(object sender, MouseEventArgs e)
            {
                //set the upper left point of our selection rectangle
                if (e.Button == MouseButtons.Left)
                    _pt = e.Location;
    
                //set inner offset for moving
                if (e.Button == MouseButtons.Right && _r.Width > 0 && _r.Height > 0)
                {
                    if (_r.Contains(e.Location))
                        _ptOffset = new Point(e.X - _r.X, e.Y - _r.Y);
                }
            }
    
            void pictureBox2_MouseMove(object sender, MouseEventArgs e)
            {
                //set the bottom right one
                if (e.Button == MouseButtons.Left)
                {
                    _r = new Rectangle(_pt.X, _pt.Y, e.X - _pt.X, e.Y - _pt.Y);
                    this.pictureBox1.Invalidate();
                }
    
                if (e.Button == MouseButtons.Right && _r.Width > 0 && _r.Height > 0)
                {
                    //move the rectangle
                    if (_r.Contains(e.Location))
                    {
                        _r.Location = new Point(e.X - _ptOffset.X, e.Y - _ptOffset.Y);
    
                        this.pictureBox1.Invalidate();
                    }
                }
            }
    
            void pictureBox2_MouseUp(object sender, MouseEventArgs e)
            {
                //display the selected part when mouse button gets released
                if (e.Button == MouseButtons.Left)
                {
                    _r = new Rectangle(_pt.X, _pt.Y, e.X - _pt.X, e.Y - _pt.Y);
                    GenerateBmp();
                }
    
                if (e.Button == MouseButtons.Right && _r.Width > 0 && _r.Height > 0)
                {
                    if (_r.Contains(e.Location))
                    {
                        _r.Location = new Point(e.X - _ptOffset.X, e.Y - _ptOffset.Y);
    
                        //redisplay selection image with new values
                        GenerateBmp();
                    }
                }
            }
    
            private void GenerateBmp()
            {
                //check, if we have a valid rectangle
                if (_r.Width > 0 && _r.Height > 0)
                {
                    //create a new Bitmap with the size of the selection-rectangle
                    Bitmap bmp = new Bitmap(_r.Width, _r.Height);
    
                    //draw the selectex part of the original image
                    using (Graphics g = Graphics.FromImage(bmp))
                        g.DrawImage(this.pictureBox1.Image, new Rectangle(0, 0, _r.Width, _r.Height), _r, GraphicsUnit.Pixel);
    
                    //grab the old image of the picturebox
                    Image bOld = this.pictureBox2.Image;
    
                    //assign our new one
                    this.pictureBox2.Image = bmp;
    
                    //dispose the old one, if not null (previously no image assigned to that control)
                    if (bOld != null)
                        bOld.Dispose();
                }
            }
    
            private Bitmap SetUpPictures(PictureBox pb)
            {
                //create a bitmap to display
                Bitmap bmp1 = new Bitmap(pb.ClientSize.Width, pb.ClientSize.Height);
    
                //get the graphics-context
                using (Graphics g = Graphics.FromImage(bmp1))
                {
                    //get a random, opaque, color
                    Color c = Color.FromArgb(255, _rnd.Next(256), _rnd.Next(256), _rnd.Next(256));
                    g.Clear(c);
    
                    //better smoothinmode for round shapes
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    
                    //draw ten shapes to the bitmap
                    for (int i = 0; i < 10; i++)
                    {
                        //loaction and size rectangle
                        Rectangle r = new Rectangle(_rnd.Next(pb.ClientSize.Width / 2), _rnd.Next(pb.ClientSize.Height / 2),
                            _rnd.Next(pb.ClientSize.Width / 2), _rnd.Next(pb.ClientSize.Height / 2));
    
                        //random color
                        Color c2 = Color.FromArgb(_rnd.Next(256), _rnd.Next(256), _rnd.Next(256), _rnd.Next(256));
    
                        //one color brush
                        using (SolidBrush sb = new SolidBrush(c2))
                        {
                            //check, if i is odd or even and decide on that to draw rectangles or ellipses
                            if ((i & 0x01) == 1)
                                g.FillEllipse(sb, r);
                            else
                                g.FillRectangle(sb, r);
                        }
                    }
                }
    
                //return our artwork
                return bmp1;
            }
        }
    

    Regards,

      Thorsten

    Saturday, January 7, 2012 2:54 PM
  • Is there a better way to make -r invisible after cropping? ...



    Hi,

    I'd assign a new rectanlge with a width and height of 0 tho the variable _r (Maybe set the location also to a value out of the controls area)

    Regards,

      Thorsten

    • Marked as answer by saratogacoach Monday, January 9, 2012 4:06 PM
    Monday, January 9, 2012 3:59 PM

All replies

  • Hi,

    you could use the http://msdn.microsoft.com/en-us/library/system.windows.forms.controlpaint.drawreversibleframe.aspx Method to draw a selection rectanlge,

    or you could draw that rectangle your own like: (This just draws arectangle on mouse-events and displays the selected part of the image in a seperate picturebox, I'll update that code with some comments soon)

    Edit: Added comments to the code.

        public partial class Form1 : Form
        {
            private PictureBox pictureBox1 = new PictureBox();
            private PictureBox pictureBox2 = new PictureBox();
    
            private Random _rnd = new Random();
            private Point _pt;
            private Point _pt2;
    
            public Form1()
            {
                InitializeComponent();
    
                //setup the Controls, usually done in design-mode
                this.ClientSize = new Size(624, 412);
                this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
    
                pictureBox1.ClientSize = new Size(400, 400);
                pictureBox1.Location = new Point(12, 6);
                //assign a - here- dynamically created - picture
                this.pictureBox1.Image = SetUpPictures(this.pictureBox1);
                this.pictureBox1.MouseDown += new MouseEventHandler(pictureBox2_MouseDown);
                this.pictureBox1.MouseMove += new MouseEventHandler(pictureBox2_MouseMove);
                this.pictureBox1.MouseUp += new MouseEventHandler(pictureBox2_MouseUp);
                this.pictureBox1.Paint += new PaintEventHandler(pictureBox2_Paint);
                this.Controls.Add(pictureBox1);
    
                pictureBox2.Location = new Point(418, 6);
                pictureBox2.ClientSize = new Size(200, 200);
                pictureBox2.SizeMode = PictureBoxSizeMode.Zoom;
                this.Controls.Add(pictureBox2);
    
                //cleanup, could also be handled in its event-handler method
                this.FormClosing += delegate
                {
                    foreach (Control c in this.Controls)
                        if (c is PictureBox)
                        {
                            PictureBox pb = (PictureBox)c;
                            if (pb.Image != null) pb.Image.Dispose();
                        }
                };
            }
    
            void pictureBox2_Paint(object sender, PaintEventArgs e)
            {
                //if we have a valid rectangle, draw it
                if (_pt.X - _pt2.X != 0 && _pt.Y - _pt2.Y != 0)
                {
                    e.Graphics.DrawRectangle(Pens.Blue, new Rectangle(_pt.X, _pt.Y, _pt2.X - _pt.X, _pt2.Y - _pt.Y));
                }
            }
    
            void pictureBox2_MouseDown(object sender, MouseEventArgs e)
            {
                //set the upper left point of our selection rectangle
                if (e.Button == MouseButtons.Left)
                    _pt = e.Location;
            }
    
            void pictureBox2_MouseMove(object sender, MouseEventArgs e)
            {
                //set the bottom right one
                if (e.Button == MouseButtons.Left)
                {
                    _pt2 = e.Location;
                    this.pictureBox1.Invalidate();
                }
            }
    
            void pictureBox2_MouseUp(object sender, MouseEventArgs e)
            {
                //display the selected part when mouse button gets released
                if (e.Button == MouseButtons.Left)
                {
                    GenerateBmp();
                }
            }
    
            private void GenerateBmp()
            {
                //check, if we have a valid rectangle
                if (_pt2.X - _pt.X > 0 && _pt2.Y - _pt.Y > 0)
                {
                    //create that rectangle
                    Rectangle r = new Rectangle(_pt.X, _pt.Y, _pt2.X - _pt.X, _pt2.Y - _pt.Y);
    
                    //create a new Bitmap with the size of the selection-rectangle
                    Bitmap bmp = new Bitmap(r.Width, r.Height);
    
                    //draw the selectex part of the original image
                    using (Graphics g = Graphics.FromImage(bmp))
                        g.DrawImage(this.pictureBox1.Image, new Rectangle(0, 0, r.Width, r.Height), r, GraphicsUnit.Pixel);
    
                    //grab the old image of the picturebox
                    Image bOld = this.pictureBox2.Image;
    
                    //assign our new one
                    this.pictureBox2.Image = bmp;
    
                    //dispose the old one, if not null (previously no image assigned to that control)
                    if (bOld != null)
                        bOld.Dispose();
                }
            }
    
            private Bitmap SetUpPictures(PictureBox pb)
            {
                //create a bitmap to display
                Bitmap bmp1 = new Bitmap(pb.ClientSize.Width, pb.ClientSize.Height);
    
                //get the graphics-context
                using (Graphics g = Graphics.FromImage(bmp1))
                {
                    //get a random, opaque, color
                    Color c = Color.FromArgb(255, _rnd.Next(256), _rnd.Next(256), _rnd.Next(256));
                    g.Clear(c);
    
                    //better smoothinmode for round shapes
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    
                    //draw ten shapes to the bitmap
                    for (int i = 0; i < 10; i++)
                    {
                        //loaction and size rectangle
                        Rectangle r = new Rectangle(_rnd.Next(pb.ClientSize.Width / 2), _rnd.Next(pb.ClientSize.Height / 2),
                            _rnd.Next(pb.ClientSize.Width / 2), _rnd.Next(pb.ClientSize.Height / 2));
    
                        //random color
                        Color c2 = Color.FromArgb(_rnd.Next(256), _rnd.Next(256), _rnd.Next(256), _rnd.Next(256));
    
                        //one color brush
                        using (SolidBrush sb = new SolidBrush(c2))
                        {
                            //check, if i is odd or even and decide on that to draw rectangles or ellipses
                            if ((i & 0x01) == 1)
                                g.FillEllipse(sb, r);
                            else
                                g.FillRectangle(sb, r);
                        }
                    }
                }
    
                //return our artwork
                return bmp1;
            }
        }

    Regards,

      Thorsten


    Saturday, January 7, 2012 9:28 AM
  • Hi Thorsten,

    Thank you for this help.

    I'm a beginner using C# so when I tried to test this code (and also the MSDN code that you linked to), I placed it in a new Wnidows Form App and got errors.

    I must be doing something wrong, not knowing where to place the new code, what old code to remove first.

    I'll keep trying.

    (I noticed that the Image Editor project that I am using as a behginning, with source files linked to in my posting above, does allow the user to click within the pictureBox to set a start point and an end point for cropping the photo. There is jutst no visible selection box created, so the user can see what area they have chosen for cropping. It would help to allow the user to see their chosen selection rectangle. It would be even better if they could then resize and drag that selection rectangle to create the exact area that they want to choose for cropping. I tried and tried to figure this out using this sample Image Editor project, but had no success. Maybe, you can take a look at these source files-see link above in my first posting-and possibly suggest a way to modify/add the functionality to it?)

    Again , thank you very much for your help.

    Kind Regards,

    saratogacoach

    Saturday, January 7, 2012 12:20 PM
  • Hi Thorsten,

    Thank you for this help.

    I'm a beginner using C# so when I tried to test this code (and also the MSDN code that you linked to), I placed it in a new Wnidows Form App and got errors.

    I must be doing something wrong, not knowing where to place the new code, what old code to remove first.

    ...

    Hi,

    for my example, do:

    - create a new WindowsFormsProject, name it as you want

    - wait until Form1 is shown and switch to code-view

    - remove the code for Form1 - means all that's inside the curly braces of the namespace, in words:

      - remove

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
        }
    


      from the code file, so that there's only the namespace definition with its opening and closing curly brace: [the namespaces name might be different]

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication4
    {
        //here's the place to paste the (form's) code
    }
    

    - insert the posted code at that particular place in the codefile.

    Regards,

      Thorsten



    Saturday, January 7, 2012 12:32 PM
  • Hi Thorsten,

    Thank you again.

    Unfortunately, I tried adding the code exactly as suggested and got an error:

    Error 1 'WindowsFormsApplication1.Form1' does not contain a definition for 'Form1_Load' and no extension method 'Form1_Load' accepting a first argument of type 'WindowsFormsApplication1.Form1' could be found (are you missing a using directive or an assembly reference?) 

    Still cannot run it.

    saratogacoach

    Saturday, January 7, 2012 1:53 PM
  • Hi,

    double click the error in the errors list and remove the line:

     

    this.Load += new System.EventHandler(this.Form1_Load);
    

    from the Form1.Designer.cs file

     

    (It's added automatically when you doubleclick the Form in the design-view)


    Regards,

      Thorsten

    Saturday, January 7, 2012 2:14 PM
  • Hi Thorsten,

    OK, got it working. Can now view the code from your posting above. Very nice! It allows drawing a selection rectangle, using the mouse.

    And, it allows creating a new rectangle easily, so no need to resize or drag--just create a new rectangle with better choice of area for cropping.

    Now I need to figure out:

    1. how to add this rectangle to the Image Editor sample project (source file link in first posting above)

    2. get top left X, Y, plus bottom right X, Y of final rectangle that user creates, to use for cropping event ( and maybe message box to ask "do you want to crop this?")

    (I'll be away most of the day visiting family, so I will try this late today and tomorrow.)

    Again, thank you.

    Kind Regards,

    saratogacoach


    Saturday, January 7, 2012 2:27 PM
  • Hi,

    here's a modified version of the example that lets you create the rectangle like before with the left mouseButton and move the rectangle with the right mouseButton:

        public partial class Form1 : Form
        {
            private PictureBox pictureBox1 = new PictureBox();
            private PictureBox pictureBox2 = new PictureBox();
    
            private Random _rnd = new Random();
            private Point _pt;
            private Point _ptOffset;
    
            private  Rectangle _r;
    
            public Form1()
            {
                InitializeComponent();
    
                //setup the Controls, usually done in design-mode
                this.ClientSize = new Size(624, 412);
                this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
    
                pictureBox1.ClientSize = new Size(400, 400);
                pictureBox1.Location = new Point(12, 6);
                //assign a - here- dynamically created - picture
                this.pictureBox1.Image = SetUpPictures(this.pictureBox1);
                this.pictureBox1.MouseDown += new MouseEventHandler(pictureBox2_MouseDown);
                this.pictureBox1.MouseMove += new MouseEventHandler(pictureBox2_MouseMove);
                this.pictureBox1.MouseUp += new MouseEventHandler(pictureBox2_MouseUp);
                this.pictureBox1.Paint += new PaintEventHandler(pictureBox2_Paint);
                this.Controls.Add(pictureBox1);
    
                pictureBox2.Location = new Point(418, 6);
                pictureBox2.ClientSize = new Size(200, 200);
                pictureBox2.SizeMode = PictureBoxSizeMode.Zoom;
                this.Controls.Add(pictureBox2);
    
                //cleanup, could also be handled in its event-handler method
                this.FormClosing += delegate
                {
                    foreach (Control c in this.Controls)
                        if (c is PictureBox)
                        {
                            PictureBox pb = (PictureBox)c;
                            if (pb.Image != null) pb.Image.Dispose();
                        }
                };
            }
    
            void pictureBox2_Paint(object sender, PaintEventArgs e)
            {
                //if we have a valid rectangle, draw it
                if (_r.Width > 0 && _r.Height > 0)
                {   
                    //fill
                    using(SolidBrush sb = new SolidBrush(Color.FromArgb(95, 255, 255, 255)))
                        e.Graphics.FillRectangle(sb, _r);
                    //draw
                    e.Graphics.DrawRectangle(Pens.Blue, _r);
                }
            }
    
            void pictureBox2_MouseDown(object sender, MouseEventArgs e)
            {
                //set the upper left point of our selection rectangle
                if (e.Button == MouseButtons.Left)
                    _pt = e.Location;
    
                //set inner offset for moving
                if (e.Button == MouseButtons.Right && _r.Width > 0 && _r.Height > 0)
                {
                    if (_r.Contains(e.Location))
                        _ptOffset = new Point(e.X - _r.X, e.Y - _r.Y);
                }
            }
    
            void pictureBox2_MouseMove(object sender, MouseEventArgs e)
            {
                //set the bottom right one
                if (e.Button == MouseButtons.Left)
                {
                    _r = new Rectangle(_pt.X, _pt.Y, e.X - _pt.X, e.Y - _pt.Y);
                    this.pictureBox1.Invalidate();
                }
    
                if (e.Button == MouseButtons.Right && _r.Width > 0 && _r.Height > 0)
                {
                    //move the rectangle
                    if (_r.Contains(e.Location))
                    {
                        _r.Location = new Point(e.X - _ptOffset.X, e.Y - _ptOffset.Y);
    
                        this.pictureBox1.Invalidate();
                    }
                }
            }
    
            void pictureBox2_MouseUp(object sender, MouseEventArgs e)
            {
                //display the selected part when mouse button gets released
                if (e.Button == MouseButtons.Left)
                {
                    _r = new Rectangle(_pt.X, _pt.Y, e.X - _pt.X, e.Y - _pt.Y);
                    GenerateBmp();
                }
    
                if (e.Button == MouseButtons.Right && _r.Width > 0 && _r.Height > 0)
                {
                    if (_r.Contains(e.Location))
                    {
                        _r.Location = new Point(e.X - _ptOffset.X, e.Y - _ptOffset.Y);
    
                        //redisplay selection image with new values
                        GenerateBmp();
                    }
                }
            }
    
            private void GenerateBmp()
            {
                //check, if we have a valid rectangle
                if (_r.Width > 0 && _r.Height > 0)
                {
                    //create a new Bitmap with the size of the selection-rectangle
                    Bitmap bmp = new Bitmap(_r.Width, _r.Height);
    
                    //draw the selectex part of the original image
                    using (Graphics g = Graphics.FromImage(bmp))
                        g.DrawImage(this.pictureBox1.Image, new Rectangle(0, 0, _r.Width, _r.Height), _r, GraphicsUnit.Pixel);
    
                    //grab the old image of the picturebox
                    Image bOld = this.pictureBox2.Image;
    
                    //assign our new one
                    this.pictureBox2.Image = bmp;
    
                    //dispose the old one, if not null (previously no image assigned to that control)
                    if (bOld != null)
                        bOld.Dispose();
                }
            }
    
            private Bitmap SetUpPictures(PictureBox pb)
            {
                //create a bitmap to display
                Bitmap bmp1 = new Bitmap(pb.ClientSize.Width, pb.ClientSize.Height);
    
                //get the graphics-context
                using (Graphics g = Graphics.FromImage(bmp1))
                {
                    //get a random, opaque, color
                    Color c = Color.FromArgb(255, _rnd.Next(256), _rnd.Next(256), _rnd.Next(256));
                    g.Clear(c);
    
                    //better smoothinmode for round shapes
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    
                    //draw ten shapes to the bitmap
                    for (int i = 0; i < 10; i++)
                    {
                        //loaction and size rectangle
                        Rectangle r = new Rectangle(_rnd.Next(pb.ClientSize.Width / 2), _rnd.Next(pb.ClientSize.Height / 2),
                            _rnd.Next(pb.ClientSize.Width / 2), _rnd.Next(pb.ClientSize.Height / 2));
    
                        //random color
                        Color c2 = Color.FromArgb(_rnd.Next(256), _rnd.Next(256), _rnd.Next(256), _rnd.Next(256));
    
                        //one color brush
                        using (SolidBrush sb = new SolidBrush(c2))
                        {
                            //check, if i is odd or even and decide on that to draw rectangles or ellipses
                            if ((i & 0x01) == 1)
                                g.FillEllipse(sb, r);
                            else
                                g.FillRectangle(sb, r);
                        }
                    }
                }
    
                //return our artwork
                return bmp1;
            }
        }
    

    Regards,

      Thorsten

    Saturday, January 7, 2012 2:54 PM
  • Wow! That's impressive. Thank you! :-)

    I think that the next big challenge is figuring out how to add it to the already existing code in the sample Image Editor (which already has a pictureBox1), then getting the rectangle's top left X,Y and bottom right X,Y stored to use for cropping.

    Kind Regards,

    saratogacoach

     

    Saturday, January 7, 2012 3:02 PM
  • ... then getting the rectangle's top left X,Y and bottom right X,Y stored to use for cropping.

    ...

    getting the coordinates isnt difficult, its just the Location-Property of the class level Rectangle _r (which returns the upper left corner) - and with that and its width, or height respectively, you can compute the bottom right corner.

    Regards,

      Thorsten

    Saturday, January 7, 2012 3:10 PM
  • Hi,

    When I get back later today, I'll try first to add this rectangle to the already-existing Image Editor code, see if I can get it to workout with error messages. Then, if successful, I can try to work on top left, bottom right calculations for the location property.

    Kind Regards,

    saratogacoach



    Saturday, January 7, 2012 3:20 PM
  • Hi,

    Had a chance to try to add the selection rectangle to the already-coded Image Editor sample, with no success. Each works fine separately, but I'm too much at beginner skill level to combine them in one successful working version.

    I tried another option, since the original Image Editor sample does have ability for the user to indicate 2 crop positions by clicking in the pictureBox1 (first mouse click gets and saves start point and second mouse click gets and saves end position. Only problem is that the selection chosen for cropping is not displayed.

    If the 2 sets of coordinated (start.X, start.Y and end.X and end.Y) could be used to draw a transparent selection rectangle, with a visible border on top of the pictureBox1, then the user could at least see their choice (currently, in the Image Editor sample, only the start end end coordinates are displayed as numbers in a text box). This would be a helpful feature.

    I researched MSDN for how to draw the rectangle and came up with:

    Point p = this.PointToScreen(pictureBox1.Location);
                    System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
                    System.Drawing.Graphics formGraphics = this.CreateGraphics();
                    formGraphics.FillRectangle(myBrush, new Rectangle(p.X, p.Y, width, height));
                    myBrush.Dispose();
                    formGraphics.Dispose();
    

    But the problem is that this draws an opaque rectangle without transparency and border, places its location in the wrong place in relation to pictureBox1, and it is below (and covered by) pictureBox1 (needs to be on top). I've tried many different variations, but still can not get it to work.

    Any suggestions would be much appreciated.

    Thank you for your help.

    Kind Regards,

    saratogacoach

     


    Sunday, January 8, 2012 1:33 PM
  • Hi,

    if you want to draw a non filled rectangle, use the DrawRectangle-Method instead of the FillRectangle-method.

    Here's some code only to draw a rectangle onto a pictureBox with the mouse-events.

    Create a new WindowsForms-Project, add a pictureBox to the Form and (remove the Form1 scope code from the Form1.cs file) copy-paste this code:

     

        public partial class Form1 : Form
        {
            //the upper left corner
            private Point _pt;
    
            //the rectangle
            private Rectangle _r;
    
            public Form1()
            {
                InitializeComponent();
    
                //add handlers to the events
                this.pictureBox1.MouseDown += new MouseEventHandler(pictureBox1_MouseDown);
                this.pictureBox1.MouseMove += new MouseEventHandler(pictureBox1_MouseMove);
                this.pictureBox1.MouseUp += new MouseEventHandler(pictureBox1_MouseUp);
                this.pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
            }
    
            void pictureBox1_Paint(object sender, PaintEventArgs e)
            {
                //if we have a valid rectangle, draw it
                if (_r.Width > 0 && _r.Height > 0)
                {
                    //draw
                    e.Graphics.DrawRectangle(Pens.Blue, _r);
                }
            }
    
            void pictureBox1_MouseDown(object sender, MouseEventArgs e)
            {
                //set the upper left point of our selection rectangle
                if (e.Button == MouseButtons.Left)
                    _pt = e.Location;
            }
    
            void pictureBox1_MouseMove(object sender, MouseEventArgs e)
            {
                //complete the rectangle
                if (e.Button == MouseButtons.Left)
                {
                    _r = new Rectangle(_pt.X, _pt.Y, e.X - _pt.X, e.Y - _pt.Y);
                    //let the control redraw itself
                    this.pictureBox1.Invalidate();
                }
            }
    
            void pictureBox1_MouseUp(object sender, MouseEventArgs e)
            {
                //display the selected part when mouse button gets released
                if (e.Button == MouseButtons.Left)
                {
                    _r = new Rectangle(_pt.X, _pt.Y, e.X - _pt.X, e.Y - _pt.Y);
                    //let the control redraw itself
                    this.pictureBox1.Invalidate();
                }
            }
        }

     

    Regards,

      Thorsten

     



    Sunday, January 8, 2012 7:14 PM
  • Thank you, Thorsten, very much. Impressive coding!

    I've gotten it working in a stand-alone test project (just this code and a fixed, hard-coded image). Next, I will try to adapt and include the feature in the Image Editor sample.

    Kind Regards,

    saratogacoach

     

    Sunday, January 8, 2012 7:39 PM
  • Hi Thorsten,
    Making progress. -:)
    So far, have included new code and used _r for cropping.
    Also added new function to remove -r after cropping:
    private void moveOff()
            {
                _r.Location = new Point(-500, -500);
            }
     Using it to move -r after cropping off screen.
    private void cropToolStripMenuItem_Click(object sender, EventArgs e)
            {
           pictureBox1.Image = cropImage(pictureBox1.Image, _r);       
           this.pictureBox1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseClick);
                changeSize();
                changeLocation();
                moveOff();}
     

    Is there a better way to make -r invisible after cropping?
    Again, much thanks for your help.
    Kind Regards,
    saratogacoach





    Monday, January 9, 2012 12:31 AM
  • Is there a better way to make -r invisible after cropping? ...



    Hi,

    I'd assign a new rectanlge with a width and height of 0 tho the variable _r (Maybe set the location also to a value out of the controls area)

    Regards,

      Thorsten

    • Marked as answer by saratogacoach Monday, January 9, 2012 4:06 PM
    Monday, January 9, 2012 3:59 PM
  • Hi Thorsten,

    Thank you very much!

    Kind Regards,

    saratogacoach

    Monday, January 9, 2012 4:07 PM