I am working on a picturebox that adds a in-depth cropping feature, I am a centered junkie, that is to say I don't find left justified images aesthetically pleasing. I just have to have everything centered. Add to this that the zoom mode of the picture box ensures that the image will be show in its entirety and be centered. I can't pass that up.

I have worked it out to perform a simple drag and drop selection rectangle system. Once the rectangle it drawn you can resize it by simply clicking on a edge of the rectangle and dragging it. If you click on the center of the rectangle you can move the entire rectangle.

My problem is that if you move the rectangle you can drag it off the image, I would like it to stop once the rectangle reaches the edge. I have worked out a way to do this, but it is really buggy and over all just doesn't work right. below is an excerpt showing how I am doing it. if anyone show me whats wrong, or help me find another method I would appreciate it.

//some vars
        bool m_mover = false;
        Size m_mover_size;
        Point m_distance;


//mouse down event handler
Rectangle mini = new Rectangle(selection.Location.X + 4, selection.Location.Y + 4, selection.Width - 8, selection.Height - 8);

            if (mini.Contains(e.Location))
            {
                m_mover = true;
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_mover_size = new Size(selection.Width, selection.Height);
            }


// THIS IS THE ON MOUSE MOVE event handler
if(m_mover)
{
 else if (this.SizeMode == PictureBoxSizeMode.Zoom)
                    {
                        Point rectloc = e.Location;

                       if((e.Location.X - m_distance.X) < ConvertToZoomed(new Point(0,0)).X)
                       {
                           rectloc.X = ConvertToZoomed(new Point(0, 0)).X;
                       }
                       else if (((e.Location.X - m_distance.X) + m_mover_size.Width) >= ConvertToZoomed(new Point(Image.Width, 0)).X)
                       {
                           int rectWidth = m_mover_size.Width;

                           float num = Math.Min((float)(((float)this.ClientRectangle.Width) / ((float)Image.Width)), (float)(((float)this.ClientRectangle.Height) / ((float)Image.Height)));
                           rectWidth = (int)((rectWidth+1) / num);
                           //rectHeight = (int)(rect.Height / num);
                           rectloc.X = ConvertToZoomed(new Point(Image.Width - rectWidth, 0)).X;
                       }
                       else
                       {
                           rectloc.X = e.Location.X - m_distance.X;
                          
                       }

                       if ((e.Location.Y - m_distance.Y) < ConvertToZoomed(new Point(0, 0)).Y)
                       {
                           rectloc.Y = ConvertToZoomed(new Point(0, 0)).Y;
                       }
                       else if (((e.Location.Y - m_distance.Y) + m_mover_size.Height) >= ConvertToZoomed(new Point(0, Image.Height)).Y)
                       {
                           int rectHeight = m_mover_size.Height;

                           float num = Math.Min((float)(((float)this.ClientRectangle.Width) / ((float)Image.Width)), (float)(((float)this.ClientRectangle.Height) / ((float)Image.Height)));
                           //rectWidth = (int)((rectWidth + 1) / num);
                           rectHeight = (int)((rectHeight + 1) / num);
                           rectloc.Y = ConvertToZoomed(new Point(0, Image.Height - rectHeight)).Y;
                       }
                       else
                       {
                           rectloc.Y = e.Location.Y - m_distance.X;
                           
                       }

                       selection = new Rectangle(rectloc.X, rectloc.Y, m_mover_size.Width, m_mover_size.Height);
                        //save the start point
                        m_Start = selection.Location;
                        //save the intermediate point
                        m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                        //Update selection

                        //m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);

                    }

                this.Invalidate();
}

// here are the methods used in the above calculations most of it is modified versions of coded provided by Ryshad

       private Point ConvertPointToImage(Point clicked)
       {
           if (this.SizeMode != PictureBoxSizeMode.Zoom)
           {
               return clicked;
           }
           //get size of original image
           Size size = this.Image.Size;
           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //reverse translation
           clicked.X -= (ClientRectangle.Width - size.Width) / 2;
           clicked.Y -= (ClientRectangle.Height - size.Height) / 2;

           //reverse scale
           clicked.X = (int)(clicked.X / num);
           clicked.Y = (int)(clicked.Y / num);

           //return image coordinates
           return clicked;
       }

       private Rectangle ConvertRectangleToImage(Rectangle clicked)
       {
           if (this.SizeMode != PictureBoxSizeMode.Zoom)
           {
               return clicked;
           }
           //get size of original image
           Size size = this.Image.Size;
           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //reverse translation
           clicked.X -= (ClientRectangle.Width - size.Width) / 2;
           clicked.Y -= (ClientRectangle.Height - size.Height) / 2;

           //reverse scale
           clicked.X = (int)(clicked.X / num);
           clicked.Y = (int)(clicked.Y / num);

           clicked.Width = (int)(clicked.Width / num);
           clicked.Height = (int)(clicked.Height / num);

           //return image coordinates
           return clicked;
       }

        // image coordinates to zoomed methods

       private Point ConvertToZoomed(Point image)
       {
           //get size of original image
           Size size = this.Image.Size;

           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //apply scale to Point
           image.X = (int)(image.X * num);
           image.Y = (int)(image.Y * num);

           //apply translation to Point
           image.X += (ClientRectangle.Width - size.Width) / 2;
           image.Y += (ClientRectangle.Height - size.Height) / 2;

           //return Zoomed Point
           return image;

       }

       private Rectangle ConvertToZoomed(Rectangle selection)
       {
           //get size of original image
           Size size = this.Image.Size;

           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //apply scale to Selection
           selection.X = (int)(selection.X * num);
           selection.Y = (int)(selection.Y * num);
           selection.Width = (int)(selection.Width * num);
           selection.Height = (int)(selection.Height * num);

           //apply translation to Selection
           selection.X += (ClientRectangle.Width - size.Width) / 2;
           selection.Y += (ClientRectangle.Height - size.Height) / 2;

           //return Zoomed Selection
           return selection;

       }

Can you upload the project demonstrating the problem? That looks rather complicated from the code you posted ;)

Also did you Paint.NET was open source? It is a fairly advanced image manipulation program.

It is complicated. I can't say that its all that elegant code. but It seems to be working except some minor problems. here is the entire extended picture box class just add it to a project, add it to a form, and put an image on its Image property. It has no error handling so be mindful of possibilities that it may crash.

remember to set its sizeMode to "zoom".

What I am trying to do is have a drawable, resizeable, moveable selection rectangle that works with a zoomed picture box that won't let the selection rectangle move off the form its about 600 lines. i have worked hard on it. if I could get it working right and bug free i would be thrilled.

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

namespace Learning_Ruber_Band_selection
{
    class EnhancedPictureBox : PictureBox
    {

        public EnhancedPictureBox()
        {
            this.Paint += new PaintEventHandler(PictureBox1_Paint);
            this.MouseDown += new MouseEventHandler(PictureBox1_MouseDown);
            this.MouseMove += new MouseEventHandler(PictureBox1_MouseMove);
            this.MouseUp += new MouseEventHandler(PictureBox1_MouseUp);

        }

       #region points translations modified from ryshad's post

       private Point ConvertPointToImage(Point clicked)
       {
           if (this.SizeMode != PictureBoxSizeMode.Zoom)
           {
               return clicked;
           }
           //get size of original image
           Size size = this.Image.Size;
           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //reverse translation
           clicked.X -= (ClientRectangle.Width - size.Width) / 2;
           clicked.Y -= (ClientRectangle.Height - size.Height) / 2;

           //reverse scale
           clicked.X = (int)(clicked.X / num);
           clicked.Y = (int)(clicked.Y / num);

           //return image coordinates
           return clicked;
       }

       private Rectangle ConvertRectangleToImage(Rectangle clicked)
       {
           if (this.SizeMode != PictureBoxSizeMode.Zoom)
           {
               return clicked;
           }
           //get size of original image
           Size size = this.Image.Size;
           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //reverse translation
           clicked.X -= (ClientRectangle.Width - size.Width) / 2;
           clicked.Y -= (ClientRectangle.Height - size.Height) / 2;

           //reverse scale
           clicked.X = (int)(clicked.X / num);
           clicked.Y = (int)(clicked.Y / num);

           clicked.Width = (int)(clicked.Width / num);
           clicked.Height = (int)(clicked.Height / num);

           //return image coordinates
           return clicked;
       }

        // image coordinates to zoomed methods

       private Point ConvertToZoomed(Point image)
       {
           //get size of original image
           Size size = this.Image.Size;

           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //apply scale to Point
           image.X = (int)(image.X * num);
           image.Y = (int)(image.Y * num);

           //apply translation to Point
           image.X += (ClientRectangle.Width - size.Width) / 2;
           image.Y += (ClientRectangle.Height - size.Height) / 2;

           //return Zoomed Point
           return image;

       }

       private Rectangle ConvertToZoomed(Rectangle selection)
       {
           //get size of original image
           Size size = this.Image.Size;

           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //apply scale to Selection
           selection.X = (int)(selection.X * num);
           selection.Y = (int)(selection.Y * num);
           selection.Width = (int)(selection.Width * num);
           selection.Height = (int)(selection.Height * num);

           //apply translation to Selection
           selection.X += (ClientRectangle.Width - size.Width) / 2;
           selection.Y += (ClientRectangle.Height - size.Height) / 2;

           //return Zoomed Selection
           return selection;

       }

       #endregion


       Rectangle selection;
        bool m_Drawing = false;
        Point m_Start;
        bool m_mover = false;
        Size m_mover_size;
        Point m_distance;
        bool m_H_sizer = false;
        bool m_V_sizer = false;
        Point m_droploc;
        bool m_HT_sizer = false;
        bool m_VT_sizer = false;

        bool m_NE_sizer = false;
        bool m_SW_sizer = false;
        bool m_NW_sizer = false;


        bool OverImage = false;


        private void PictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right && selection.Contains(e.Location))
            {


                if (SizeMode == PictureBoxSizeMode.CenterImage)
                {

                    Point start = TranslateCenterImageMousePosition(selection.Location);

                    Rectangle sect = new Rectangle(start, selection.Size);

                    Bitmap b2 = ((Bitmap)Image).Clone(sect, Image.PixelFormat);

                    Clipboard.SetImage((Image)b2);
                }
                else if (SizeMode == PictureBoxSizeMode.Normal)
                {
                    Bitmap b2 = ((Bitmap)Image).Clone(selection, Image.PixelFormat);
                    Clipboard.SetImage((Image)b2);
                }
                else if (SizeMode == PictureBoxSizeMode.Zoom)
                {
                    Rectangle sect = TranslateZoomRectangle(selection);


                   Bitmap b2 = ((Bitmap)Image).Clone(sect, Image.PixelFormat);

                    Clipboard.SetImage((Image)b2);

                    this.Invalidate();

                   // MessageBox.Show(e.Location.ToString() + " clientw=" + ClientRectangle.Height.ToString() + "imageh=" + Image.Height.ToString() + " image w=" + Image.Width.ToString() + "endrect=" + (selection.X + selection.Width).ToString());
                  
                }

                MessageBox.Show("Copied to clip board");

                return;

            }


            Rectangle mini = new Rectangle(selection.Location.X + 4, selection.Location.Y + 4, selection.Width - 8, selection.Height - 8);
            Rectangle selectionM = new Rectangle(selection.Location.X - 3, selection.Location.Y - 3, selection.Width + 6, selection.Height + 6);
            Rectangle SEsizeRect = new Rectangle(selection.Location.X + selection.Width - 3, selection.Location.Y + selection.Height - 3, 6, 6);
            Rectangle NEsizeRect = new Rectangle(selection.Location.X + selection.Width - 3, selection.Location.Y - 3, 6, 6);
            Rectangle SWsizeRect = new Rectangle(selection.Location.X - 3, selection.Location.Y + selection.Height - 3, 6, 6);
            Rectangle NWsizeRect = new Rectangle(selection.Location.X - 3, selection.Location.Y - 3, 6, 6);
            if (mini.Contains(e.Location))
            {
                m_mover = true;
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_mover_size = new Size(selection.Width, selection.Height);
            }
            else if (SEsizeRect.Contains(e.Location))
            {
                m_Drawing = true;
                return;
            }
            else if (NEsizeRect.Contains(e.Location))
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_NE_sizer = true;
                return;
            }
            else if (SWsizeRect.Contains(e.Location))
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_SW_sizer = true;
                return;
            }
            else if (NWsizeRect.Contains(e.Location))
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_NW_sizer = true;
                return;
            }
            else if (selectionM.Contains(e.Location) && e.Location.X > (mini.Location.X + mini.Width))
            {
                m_H_sizer = true;
            }
            else if (selectionM.Contains(e.Location) && e.Location.Y > (mini.Location.Y + mini.Height))
            {
                m_V_sizer = true;
            }
            else if (selectionM.Contains(e.Location) && e.Location.X < mini.Location.X)
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_HT_sizer = true;
            }
            else if (selectionM.Contains(e.Location) && e.Location.Y < mini.Location.Y)
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_VT_sizer = true;
            }
            else
            {
                //Remember where mouse was pressed
                m_Start = e.Location;
                //Clear the selection rectangle
                selection = new Rectangle(); ;
                this.Invalidate();
                //Selection drawing is on
                m_Drawing = true;
            }
        }

        private void  // ERROR: Handles clauses are not supported in C#
    PictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (m_Drawing)
            {

                if (SizeMode == PictureBoxSizeMode.Normal)
                {
                    Point newDrop = e.Location;
                    Point p = e.Location;
                    if (p.X < 0)
                    {
                        newDrop.X = 0;
                    }
                    if (p.X > Image.Width)
                    {
                        newDrop.X = Image.Width;
                    }
                    if (p.Y < 0)
                    {
                        newDrop.Y = 0;
                    }
                    if (p.Y > Image.Height)
                    {
                        newDrop.Y = Image.Height;
                    }

                    selection = RectangleFromPoints(m_Start, newDrop);
                    //save the intermediate point
                    m_droploc = newDrop;
                    //Update selection
                }

                else if (this.SizeMode == PictureBoxSizeMode.Zoom)
                {
                    Point newDrop = e.Location;

                    Point p = ConvertPointToImage(e.Location);
                    if (p.X < 0)
                    {
                        newDrop.X = ConvertToZoomed(new Point(0,ConvertPointToImage(e.Location).Y)).X;
                    }
                    if (p.X > Image.Width)
                    {
                        newDrop.X = ConvertToZoomed(new Point(Image.Width, ConvertPointToImage(e.Location).Y)).X;
                    }
                    if (p.Y < 0)
                    {
                        newDrop.Y = ConvertToZoomed(new Point(ConvertPointToImage(e.Location).X, 0)).Y;
                    }
                    if (p.Y > Image.Height)
                    {
                        newDrop.Y = ConvertToZoomed(new Point(ConvertPointToImage(e.Location).X, Image.Height)).Y;
                    }

                    selection = RectangleFromPoints(m_Start, newDrop);
                    //save the intermediate point
                    m_droploc = newDrop;
                    //Update selection

                }
                else
                {
                    selection = RectangleFromPoints(m_Start, e.Location);
                    m_droploc = e.Location;
                }

             
                this.Invalidate();
            }
            else if (m_mover)
            {
                if (this.SizeMode == PictureBoxSizeMode.Normal)
                {
                    selection = new Rectangle(e.Location.X - m_distance.X, e.Location.Y - m_distance.Y, m_mover_size.Width, m_mover_size.Height);
                    //save the start point
                    m_Start = selection.Location;
                    //save the intermediate point
                    m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                    //Update selection
                } 
                else if (this.SizeMode == PictureBoxSizeMode.Zoom)
                    {
                        Point rectloc = e.Location;

                       if((e.Location.X - m_distance.X) < ConvertToZoomed(new Point(0,0)).X)
                       {
                           rectloc.X = ConvertToZoomed(new Point(0, 0)).X;
                       }
                       else if (((e.Location.X - m_distance.X) + m_mover_size.Width) >= ConvertToZoomed(new Point(Image.Width, 0)).X)
                       {
                           int rectWidth = m_mover_size.Width;

                           float num = Math.Min((float)(((float)this.ClientRectangle.Width) / ((float)Image.Width)), (float)(((float)this.ClientRectangle.Height) / ((float)Image.Height)));
                           rectWidth = (int)((rectWidth+1) / num);
                           //rectHeight = (int)(rect.Height / num);
                           rectloc.X = ConvertToZoomed(new Point(Image.Width - rectWidth, 0)).X;
                       }
                       else
                       {
                           rectloc.X = e.Location.X - m_distance.X;
                          
                       }

                       if ((e.Location.Y - m_distance.Y) < ConvertToZoomed(new Point(0, 0)).Y)
                       {
                           rectloc.Y = ConvertToZoomed(new Point(0, 0)).Y;
                       }
                       else if (((e.Location.Y - m_distance.Y) + m_mover_size.Height) >= ConvertToZoomed(new Point(0, Image.Height)).Y)
                       {
                           int rectHeight = m_mover_size.Height;

                           float num = Math.Min((float)(((float)this.ClientRectangle.Width) / ((float)Image.Width)), (float)(((float)this.ClientRectangle.Height) / ((float)Image.Height)));
                           //rectWidth = (int)((rectWidth + 1) / num);
                           rectHeight = (int)((rectHeight + 1) / num);
                           rectloc.Y = ConvertToZoomed(new Point(0, Image.Height - rectHeight)).Y;
                       }
                       else
                       {
                           rectloc.Y = e.Location.Y - m_distance.X;
                           
                       }

                       selection = new Rectangle(rectloc.X, rectloc.Y, m_mover_size.Width, m_mover_size.Height);
                        //save the start point
                        m_Start = selection.Location;
                        //save the intermediate point
                        m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                        //Update selection

                        //m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);

                    }

                this.Invalidate();
            }
            else if (m_NE_sizer)
            {
                selection.Width = e.Location.X - selection.Location.X;
                int Ysize = m_droploc.Y - (e.Location.Y + m_distance.Y);
                selection.Location = new Point(m_Start.X, e.Location.Y + m_distance.Y);
                selection.Height = Ysize;
                //save the intermediate point
                m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                //Update selection
                this.Invalidate();
                return;
            }
            else if (m_SW_sizer)
            {
                int Xsize = m_droploc.X - (e.Location.X + m_distance.X);
                selection.Location = new Point(e.Location.X + m_distance.X, m_Start.Y);
                selection.Width = Xsize;

                selection.Height = e.Location.Y - selection.Location.Y;


                //Update selection
                this.Invalidate();
                return;
            }
            else if (m_NW_sizer)
            {
                int Xsize = m_droploc.X - (e.Location.X + m_distance.X);
                int Ysize = m_droploc.Y - (e.Location.Y + m_distance.Y);
                selection.Location = new Point(e.Location.X + m_distance.X, e.Location.Y + m_distance.Y);
                selection.Width = Xsize;

                selection.Height = Ysize;

                //Update selection
                this.Invalidate();
                return;
            }
            else if (m_H_sizer)
            {
                selection.Width = e.Location.X - selection.Location.X;
                //save the intermediate point
                m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                //Update selection
                this.Invalidate();
            }
            else if (m_V_sizer)
            {
                selection.Height = e.Location.Y - selection.Location.Y;
                //save the intermediate point
                m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                //Update selection
                this.Invalidate();
            }
            else if (m_HT_sizer)
            {
                int Xsize = m_droploc.X - (e.Location.X + m_distance.X);
                selection.Location = new Point(e.Location.X + m_distance.X, m_Start.Y);
                selection.Width = Xsize;
                //Update selection
                this.Invalidate();
            }
            else if (m_VT_sizer)
            {
                int Ysize = m_droploc.Y - (e.Location.Y + m_distance.Y);
                selection.Location = new Point(m_Start.X, e.Location.Y + m_distance.Y);
                selection.Height = Ysize;
                //Update selection
                this.Invalidate();
            }

            //show mouse effects
            if (!m_mover && !m_H_sizer && !m_V_sizer && !m_HT_sizer && !m_VT_sizer && !m_Drawing)
            {
                Rectangle mini = new Rectangle(selection.Location.X + 4, selection.Location.Y + 4, selection.Width - 8, selection.Height - 8);
                Rectangle SEsizeRect = new Rectangle(selection.Location.X + selection.Width - 3, selection.Location.Y + selection.Height - 3, 6, 6);
                Rectangle selectionM = new Rectangle(selection.Location.X - 3, selection.Location.Y - 3, selection.Width + 6, selection.Height + 6);
                Rectangle NEsizeRect = new Rectangle(selection.Location.X + selection.Width - 3, selection.Location.Y - 3, 6, 6);
                Rectangle SWsizeRect = new Rectangle(selection.Location.X - 3, selection.Location.Y + selection.Height - 3, 6, 6);
                Rectangle NWsizeRect = new Rectangle(selection.Location.X - 3, selection.Location.Y - 3, 6, 6);
                if (mini.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeAll;
                }
                else if (SEsizeRect.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeNWSE;
                    return;
                }
                else if (NEsizeRect.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeNESW;
                    return;
                }
                else if (SWsizeRect.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeNESW;
                    return;
                }
                else if (NWsizeRect.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeNWSE;
                    return;
                }
                else if (selectionM.Contains(e.Location) && e.Location.X > (mini.Location.X + mini.Width))
                {
                    this.Cursor = Cursors.SizeWE;
                }
                else if (selectionM.Contains(e.Location) && e.Location.Y > (mini.Location.Y + mini.Height))
                {
                    this.Cursor = Cursors.SizeNS;
                }
                else if (selectionM.Contains(e.Location) && e.Location.X < mini.Location.X)
                {
                    this.Cursor = Cursors.SizeWE;
                }
                else if (selectionM.Contains(e.Location) && e.Location.Y < mini.Location.Y)
                {
                    this.Cursor = Cursors.SizeNS;
                }
                else
                {
                    this.Cursor = Cursors.Default;
                }
            }
        }

        //Returns a rectangle from 2 points
        private Rectangle RectangleFromPoints(Point p1, Point p2)
        {
            int x;
            int y;

            if (p1.X <= p2.X)
            {
                x = p1.X;
            }
            else
            {
                x = p2.X;
            }

            if (p1.Y <= p2.Y)
            {
                y = p1.Y;
            }
            else
            {
                y = p2.Y;
            }

            return new Rectangle(x, y, Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y));
        }

        private void  // ERROR: Handles clauses are not supported in C#
    PictureBox1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            m_Drawing = false;
            m_mover = false;
            m_H_sizer = false;
            m_V_sizer = false;
            m_HT_sizer = false;
            m_VT_sizer = false;
            m_NE_sizer = false;
            m_SW_sizer = false;
            m_NW_sizer = false;

            //save the start point
            m_Start = selection.Location;
            //save the intermediate point
            m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);


        }


        SolidBrush hbr = new SolidBrush(Color.FromArgb(25, Color.Blue));
        Pen borderpen = new Pen(new SolidBrush(Color.FromArgb(100, Color.Blue)));

        private void
    PictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            if (selection != null)
            {
                //There is a selection rectangle so draw it
                e.Graphics.FillRectangle(hbr, selection);
                borderpen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
                e.Graphics.DrawRectangle(borderpen, selection);
            }
        }

        private void SelectAll() //NOT FINISHED
        {
           // Rectangle rectangle = LayoutUtils.DeflateRect(base.ClientRectangle, base.Padding);
            Rectangle rectangle = new Rectangle();
            if (this.Image != null)
            {
                switch (SizeMode)
                {
                    case PictureBoxSizeMode.Normal:
                    case PictureBoxSizeMode.AutoSize:
                        rectangle.Size = this.Image.Size;
                        selection = rectangle;
                        return;

                    case PictureBoxSizeMode.StretchImage:
                        selection = rectangle;
                        return;
                      

                    case PictureBoxSizeMode.CenterImage:
                        rectangle.X += (rectangle.Width - this.Image.Width) / 2;
                        rectangle.Y += (rectangle.Height - this.Image.Height) / 2;
                        rectangle.Size = this.Image.Size;
                        selection = rectangle;
                        return;

                    case PictureBoxSizeMode.Zoom:
                        {
                            Size size = this.Image.Size;
                            float num = Math.Min((float)(((float)base.ClientRectangle.Width) / ((float)size.Width)), (float)(((float)base.ClientRectangle.Height) / ((float)size.Height)));
                            rectangle.Width = (int)(size.Width * num);
                            rectangle.Height = (int)(size.Height * num);
                            rectangle.X = (base.ClientRectangle.Width - rectangle.Width) / 2;
                            rectangle.Y = (base.ClientRectangle.Height - rectangle.Height) / 2;
                            selection = rectangle;
                            return;
                        }
                }
            }
        }



    }
}

Edited 7 Years Ago by Diamonddrake: n/a

Did i miss something? I tried copying the code to test your control but when i try to compile it says that 'TranslateCenterImageMousePosition' and 'translatezoomrectangle' canot be found : /

Sorry. I accidentally removed a block of code with those 2 methods. they are just for the actual cropping effect and not for the section problem I am having. you can remove those 2 whole if statements that do the cropping and then go from there. I will post back a fixed version of that later, right now i have to drive my girlfriend to work.

ok. here is the updated control. Now compiles. but the move still doesn't work right.

again, some insight would really be appreciated.

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

namespace Learning_Ruber_Band_selection
{
    class EnhancedPictureBox : PictureBox
    {

        public EnhancedPictureBox()
        {
            this.Paint += new PaintEventHandler(PictureBox1_Paint);
            this.MouseDown += new MouseEventHandler(PictureBox1_MouseDown);
            this.MouseMove += new MouseEventHandler(PictureBox1_MouseMove);
            this.MouseUp += new MouseEventHandler(PictureBox1_MouseUp);

        }

       #region points translations modified from ryshad's post

       private Point ConvertPointToImage(Point clicked)
       {
           if (this.SizeMode == PictureBoxSizeMode.Zoom)
           {
               //get size of original image
               Size size = this.Image.Size;
               //get value of scale
               float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

               //scale size to calculate translation
               size.Width = (int)(size.Width * num);
               size.Height = (int)(size.Height * num);

               //reverse translation
               clicked.X -= (ClientRectangle.Width - size.Width) / 2;
               clicked.Y -= (ClientRectangle.Height - size.Height) / 2;

               //reverse scale
               clicked.X = (int)(clicked.X / num);
               clicked.Y = (int)(clicked.Y / num);

               //return image coordinates
               return clicked;
           }
           else if (this.SizeMode == PictureBoxSizeMode.CenterImage)
           {
               //how the centering works
               //rectangle.X += (rectangle.Width - this.image.Width) / 2;
               // rectangle.Y += (rectangle.Height - this.image.Height) / 2;
               //--

               // got this online
               // - http://www.codeproject.com/KB/miscctrl/PictureBoxExtended.aspx

 
               int diffWidth = this.ClientRectangle.Width - Image.Width;
               int diffHeight = this.ClientRectangle.Height - Image.Height;

               diffWidth /= 2;
               diffHeight /= 2;

               clicked.X -= diffWidth;
               clicked.Y -= diffHeight;

               return clicked;

           }
           else if (this.SizeMode == PictureBoxSizeMode.StretchImage)
           {
               // Make sure our control width and height are not 0
               if (Width == 0 || Height == 0) return clicked;
               // First, get the ratio (image to control) the height and width
               float ratioWidth = (float)Image.Width / Width;
               float ratioHeight = (float)Image.Height / Height;
               // Scale the points by our ratio
               float newX = clicked.X;
               float newY = clicked.Y;
               newX *= ratioWidth;
               newY *= ratioHeight;
               return new Point((int)newX, (int)newY);

           }
           else
           {
               return clicked;
           }
       }

       private Rectangle ConvertRectangleToImage(Rectangle clicked)
       {
           if (this.SizeMode != PictureBoxSizeMode.Zoom)
           {
               return clicked;
           }
           //get size of original image
           Size size = this.Image.Size;
           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //reverse translation
           clicked.X -= (ClientRectangle.Width - size.Width) / 2;
           clicked.Y -= (ClientRectangle.Height - size.Height) / 2;

           //reverse scale
           clicked.X = (int)(clicked.X / num);
           clicked.Y = (int)(clicked.Y / num);

           clicked.Width = (int)(clicked.Width / num);
           clicked.Height = (int)(clicked.Height / num);

           //return image coordinates
           return clicked;
       }

        // image coordinates to zoomed methods

       private Point ConvertToZoomed(Point image)
       {
           //get size of original image
           Size size = this.Image.Size;

           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //apply scale to Point
           image.X = (int)(image.X * num);
           image.Y = (int)(image.Y * num);

           //apply translation to Point
           image.X += (ClientRectangle.Width - size.Width) / 2;
           image.Y += (ClientRectangle.Height - size.Height) / 2;

           //return Zoomed Point
           return image;

       }

       private Rectangle ConvertToZoomed(Rectangle selection)
       {
           //get size of original image
           Size size = this.Image.Size;

           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //apply scale to Selection
           selection.X = (int)(selection.X * num);
           selection.Y = (int)(selection.Y * num);
           selection.Width = (int)(selection.Width * num);
           selection.Height = (int)(selection.Height * num);

           //apply translation to Selection
           selection.X += (ClientRectangle.Width - size.Width) / 2;
           selection.Y += (ClientRectangle.Height - size.Height) / 2;

           //return Zoomed Selection
           return selection;

       }

       #endregion


       Rectangle selection;
        bool m_Drawing = false;
        Point m_Start;
        bool m_mover = false;
        Size m_mover_size;
        Point m_distance;
        bool m_H_sizer = false;
        bool m_V_sizer = false;
        Point m_droploc;
        bool m_HT_sizer = false;
        bool m_VT_sizer = false;

        bool m_NE_sizer = false;
        bool m_SW_sizer = false;
        bool m_NW_sizer = false;


        bool OverImage = false;


        private void PictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right && selection.Contains(e.Location))
            {


                if (SizeMode == PictureBoxSizeMode.CenterImage)
                {

                    Point start = ConvertPointToImage(selection.Location);

                    Rectangle sect = new Rectangle(start, selection.Size);

                    Bitmap b2 = ((Bitmap)Image).Clone(sect, Image.PixelFormat);

                    Clipboard.SetImage((Image)b2);
                }
                else if (SizeMode == PictureBoxSizeMode.Normal)
                {
                    Bitmap b2 = ((Bitmap)Image).Clone(selection, Image.PixelFormat);
                    Clipboard.SetImage((Image)b2);
                }
                else if (SizeMode == PictureBoxSizeMode.Zoom)
                {
                    Rectangle sect = ConvertRectangleToImage(selection);


                   Bitmap b2 = ((Bitmap)Image).Clone(sect, Image.PixelFormat);

                    Clipboard.SetImage((Image)b2);

                    this.Invalidate();

                   // MessageBox.Show(e.Location.ToString() + " clientw=" + ClientRectangle.Height.ToString() + "imageh=" + Image.Height.ToString() + " image w=" + Image.Width.ToString() + "endrect=" + (selection.X + selection.Width).ToString());
                  
                }

                MessageBox.Show("Copied to clip board");

                return;

            }


            Rectangle mini = new Rectangle(selection.Location.X + 4, selection.Location.Y + 4, selection.Width - 8, selection.Height - 8);
            Rectangle selectionM = new Rectangle(selection.Location.X - 3, selection.Location.Y - 3, selection.Width + 6, selection.Height + 6);
            Rectangle SEsizeRect = new Rectangle(selection.Location.X + selection.Width - 3, selection.Location.Y + selection.Height - 3, 6, 6);
            Rectangle NEsizeRect = new Rectangle(selection.Location.X + selection.Width - 3, selection.Location.Y - 3, 6, 6);
            Rectangle SWsizeRect = new Rectangle(selection.Location.X - 3, selection.Location.Y + selection.Height - 3, 6, 6);
            Rectangle NWsizeRect = new Rectangle(selection.Location.X - 3, selection.Location.Y - 3, 6, 6);
            if (mini.Contains(e.Location))
            {
                m_mover = true;
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_mover_size = new Size(selection.Width, selection.Height);
            }
            else if (SEsizeRect.Contains(e.Location))
            {
                m_Drawing = true;
                return;
            }
            else if (NEsizeRect.Contains(e.Location))
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_NE_sizer = true;
                return;
            }
            else if (SWsizeRect.Contains(e.Location))
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_SW_sizer = true;
                return;
            }
            else if (NWsizeRect.Contains(e.Location))
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_NW_sizer = true;
                return;
            }
            else if (selectionM.Contains(e.Location) && e.Location.X > (mini.Location.X + mini.Width))
            {
                m_H_sizer = true;
            }
            else if (selectionM.Contains(e.Location) && e.Location.Y > (mini.Location.Y + mini.Height))
            {
                m_V_sizer = true;
            }
            else if (selectionM.Contains(e.Location) && e.Location.X < mini.Location.X)
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_HT_sizer = true;
            }
            else if (selectionM.Contains(e.Location) && e.Location.Y < mini.Location.Y)
            {
                m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);
                m_VT_sizer = true;
            }
            else
            {
                //Remember where mouse was pressed
                m_Start = e.Location;
                //Clear the selection rectangle
                selection = new Rectangle(); ;
                this.Invalidate();
                //Selection drawing is on
                m_Drawing = true;
            }
        }

        private void  // ERROR: Handles clauses are not supported in C#
    PictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (m_Drawing)
            {

                if (SizeMode == PictureBoxSizeMode.Normal)
                {
                    Point newDrop = e.Location;
                    Point p = e.Location;
                    if (p.X < 0)
                    {
                        newDrop.X = 0;
                    }
                    if (p.X > Image.Width)
                    {
                        newDrop.X = Image.Width;
                    }
                    if (p.Y < 0)
                    {
                        newDrop.Y = 0;
                    }
                    if (p.Y > Image.Height)
                    {
                        newDrop.Y = Image.Height;
                    }

                    selection = RectangleFromPoints(m_Start, newDrop);
                    //save the intermediate point
                    m_droploc = newDrop;
                    //Update selection
                }

                else if (this.SizeMode == PictureBoxSizeMode.Zoom)
                {
                    Point newDrop = e.Location;

                    Point p = ConvertPointToImage(e.Location);
                    if (p.X < 0)
                    {
                        newDrop.X = ConvertToZoomed(new Point(0,ConvertPointToImage(e.Location).Y)).X;
                    }
                    if (p.X > Image.Width)
                    {
                        newDrop.X = ConvertToZoomed(new Point(Image.Width, ConvertPointToImage(e.Location).Y)).X;
                    }
                    if (p.Y < 0)
                    {
                        newDrop.Y = ConvertToZoomed(new Point(ConvertPointToImage(e.Location).X, 0)).Y;
                    }
                    if (p.Y > Image.Height)
                    {
                        newDrop.Y = ConvertToZoomed(new Point(ConvertPointToImage(e.Location).X, Image.Height)).Y;
                    }

                    selection = RectangleFromPoints(m_Start, newDrop);
                    //save the intermediate point
                    m_droploc = newDrop;
                    //Update selection

                }
                else
                {
                    selection = RectangleFromPoints(m_Start, e.Location);
                    m_droploc = e.Location;
                }

             
                this.Invalidate();
            }
            else if (m_mover)
            {
                if (this.SizeMode == PictureBoxSizeMode.Normal)
                {
                    selection = new Rectangle(e.Location.X - m_distance.X, e.Location.Y - m_distance.Y, m_mover_size.Width, m_mover_size.Height);
                    //save the start point
                    m_Start = selection.Location;
                    //save the intermediate point
                    m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                    //Update selection
                } 
                else if (this.SizeMode == PictureBoxSizeMode.Zoom)
                    {
                        Point rectloc = e.Location;

                       if((e.Location.X - m_distance.X) < ConvertToZoomed(new Point(0,0)).X)
                       {
                           rectloc.X = ConvertToZoomed(new Point(0, 0)).X;
                       }
                       else if (((e.Location.X - m_distance.X) + m_mover_size.Width) >= ConvertToZoomed(new Point(Image.Width, 0)).X)
                       {
                           int rectWidth = m_mover_size.Width;

                           float num = Math.Min((float)(((float)this.ClientRectangle.Width) / ((float)Image.Width)), (float)(((float)this.ClientRectangle.Height) / ((float)Image.Height)));
                           rectWidth = (int)((rectWidth+1) / num);
                           //rectHeight = (int)(rect.Height / num);
                           rectloc.X = ConvertToZoomed(new Point(Image.Width - rectWidth, 0)).X;
                       }
                       else
                       {
                           rectloc.X = e.Location.X - m_distance.X;
                          
                       }

                       if ((e.Location.Y - m_distance.Y) < ConvertToZoomed(new Point(0, 0)).Y)
                       {
                           rectloc.Y = ConvertToZoomed(new Point(0, 0)).Y;
                       }
                       else if (((e.Location.Y - m_distance.Y) + m_mover_size.Height) >= ConvertToZoomed(new Point(0, Image.Height)).Y)
                       {
                           int rectHeight = m_mover_size.Height;

                           float num = Math.Min((float)(((float)this.ClientRectangle.Width) / ((float)Image.Width)), (float)(((float)this.ClientRectangle.Height) / ((float)Image.Height)));
                           //rectWidth = (int)((rectWidth + 1) / num);
                           rectHeight = (int)((rectHeight + 1) / num);
                           rectloc.Y = ConvertToZoomed(new Point(0, Image.Height - rectHeight)).Y;
                       }
                       else
                       {
                           rectloc.Y = e.Location.Y - m_distance.X;
                           
                       }

                       selection = new Rectangle(rectloc.X, rectloc.Y, m_mover_size.Width, m_mover_size.Height);
                        //save the start point
                        m_Start = selection.Location;
                        //save the intermediate point
                        m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                        //Update selection

                        //m_distance = new Point(e.Location.X - selection.Location.X, e.Location.Y - selection.Location.Y);

                    }

                this.Invalidate();
            }
            else if (m_NE_sizer)
            {
                selection.Width = e.Location.X - selection.Location.X;
                int Ysize = m_droploc.Y - (e.Location.Y + m_distance.Y);
                selection.Location = new Point(m_Start.X, e.Location.Y + m_distance.Y);
                selection.Height = Ysize;
                //save the intermediate point
                m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                //Update selection
                this.Invalidate();
                return;
            }
            else if (m_SW_sizer)
            {
                int Xsize = m_droploc.X - (e.Location.X + m_distance.X);
                selection.Location = new Point(e.Location.X + m_distance.X, m_Start.Y);
                selection.Width = Xsize;

                selection.Height = e.Location.Y - selection.Location.Y;


                //Update selection
                this.Invalidate();
                return;
            }
            else if (m_NW_sizer)
            {
                int Xsize = m_droploc.X - (e.Location.X + m_distance.X);
                int Ysize = m_droploc.Y - (e.Location.Y + m_distance.Y);
                selection.Location = new Point(e.Location.X + m_distance.X, e.Location.Y + m_distance.Y);
                selection.Width = Xsize;

                selection.Height = Ysize;

                //Update selection
                this.Invalidate();
                return;
            }
            else if (m_H_sizer)
            {
                selection.Width = e.Location.X - selection.Location.X;
                //save the intermediate point
                m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                //Update selection
                this.Invalidate();
            }
            else if (m_V_sizer)
            {
                selection.Height = e.Location.Y - selection.Location.Y;
                //save the intermediate point
                m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);
                //Update selection
                this.Invalidate();
            }
            else if (m_HT_sizer)
            {
                int Xsize = m_droploc.X - (e.Location.X + m_distance.X);
                selection.Location = new Point(e.Location.X + m_distance.X, m_Start.Y);
                selection.Width = Xsize;
                //Update selection
                this.Invalidate();
            }
            else if (m_VT_sizer)
            {
                int Ysize = m_droploc.Y - (e.Location.Y + m_distance.Y);
                selection.Location = new Point(m_Start.X, e.Location.Y + m_distance.Y);
                selection.Height = Ysize;
                //Update selection
                this.Invalidate();
            }

            //show mouse effects
            if (!m_mover && !m_H_sizer && !m_V_sizer && !m_HT_sizer && !m_VT_sizer && !m_Drawing)
            {
                Rectangle mini = new Rectangle(selection.Location.X + 4, selection.Location.Y + 4, selection.Width - 8, selection.Height - 8);
                Rectangle SEsizeRect = new Rectangle(selection.Location.X + selection.Width - 3, selection.Location.Y + selection.Height - 3, 6, 6);
                Rectangle selectionM = new Rectangle(selection.Location.X - 3, selection.Location.Y - 3, selection.Width + 6, selection.Height + 6);
                Rectangle NEsizeRect = new Rectangle(selection.Location.X + selection.Width - 3, selection.Location.Y - 3, 6, 6);
                Rectangle SWsizeRect = new Rectangle(selection.Location.X - 3, selection.Location.Y + selection.Height - 3, 6, 6);
                Rectangle NWsizeRect = new Rectangle(selection.Location.X - 3, selection.Location.Y - 3, 6, 6);
                if (mini.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeAll;
                }
                else if (SEsizeRect.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeNWSE;
                    return;
                }
                else if (NEsizeRect.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeNESW;
                    return;
                }
                else if (SWsizeRect.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeNESW;
                    return;
                }
                else if (NWsizeRect.Contains(e.Location))
                {
                    this.Cursor = Cursors.SizeNWSE;
                    return;
                }
                else if (selectionM.Contains(e.Location) && e.Location.X > (mini.Location.X + mini.Width))
                {
                    this.Cursor = Cursors.SizeWE;
                }
                else if (selectionM.Contains(e.Location) && e.Location.Y > (mini.Location.Y + mini.Height))
                {
                    this.Cursor = Cursors.SizeNS;
                }
                else if (selectionM.Contains(e.Location) && e.Location.X < mini.Location.X)
                {
                    this.Cursor = Cursors.SizeWE;
                }
                else if (selectionM.Contains(e.Location) && e.Location.Y < mini.Location.Y)
                {
                    this.Cursor = Cursors.SizeNS;
                }
                else
                {
                    this.Cursor = Cursors.Default;
                }
            }
        }

        //Returns a rectangle from 2 points
        private Rectangle RectangleFromPoints(Point p1, Point p2)
        {
            int x;
            int y;

            if (p1.X <= p2.X)
            {
                x = p1.X;
            }
            else
            {
                x = p2.X;
            }

            if (p1.Y <= p2.Y)
            {
                y = p1.Y;
            }
            else
            {
                y = p2.Y;
            }

            return new Rectangle(x, y, Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y));
        }

        private void  // ERROR: Handles clauses are not supported in C#
    PictureBox1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            m_Drawing = false;
            m_mover = false;
            m_H_sizer = false;
            m_V_sizer = false;
            m_HT_sizer = false;
            m_VT_sizer = false;
            m_NE_sizer = false;
            m_SW_sizer = false;
            m_NW_sizer = false;

            //save the start point
            m_Start = selection.Location;
            //save the intermediate point
            m_droploc = new Point(selection.Location.X + selection.Width, selection.Location.Y + selection.Height);


        }


        SolidBrush hbr = new SolidBrush(Color.FromArgb(25, Color.Blue));
        Pen borderpen = new Pen(new SolidBrush(Color.FromArgb(100, Color.Blue)));

        private void
    PictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            if (selection != null)
            {
                //There is a selection rectangle so draw it
                e.Graphics.FillRectangle(hbr, selection);
                borderpen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
                e.Graphics.DrawRectangle(borderpen, selection);
            }
        }

        private void SelectAll() //NOT FINISHED
        {
           // Rectangle rectangle = LayoutUtils.DeflateRect(base.ClientRectangle, base.Padding);
            Rectangle rectangle = new Rectangle();
            if (this.Image != null)
            {
                switch (SizeMode)
                {
                    case PictureBoxSizeMode.Normal:
                    case PictureBoxSizeMode.AutoSize:
                        rectangle.Size = this.Image.Size;
                        selection = rectangle;
                        return;

                    case PictureBoxSizeMode.StretchImage:
                        selection = rectangle;
                        return;
                      

                    case PictureBoxSizeMode.CenterImage:
                        rectangle.X += (rectangle.Width - this.Image.Width) / 2;
                        rectangle.Y += (rectangle.Height - this.Image.Height) / 2;
                        rectangle.Size = this.Image.Size;
                        selection = rectangle;
                        return;

                    case PictureBoxSizeMode.Zoom:
                        {
                            Size size = this.Image.Size;
                            float num = Math.Min((float)(((float)base.ClientRectangle.Width) / ((float)size.Width)), (float)(((float)base.ClientRectangle.Height) / ((float)size.Height)));
                            rectangle.Width = (int)(size.Width * num);
                            rectangle.Height = (int)(size.Height * num);
                            rectangle.X = (base.ClientRectangle.Width - rectangle.Width) / 2;
                            rectangle.Y = (base.ClientRectangle.Height - rectangle.Height) / 2;
                            selection = rectangle;
                            return;
                        }
                }
            }
        }



    }
}

dispare not, there is bound to be a soultion :P i've been battling some medical stuff so havent had time to look at this. I'm on my feet so i'll give it my full attention today :)

hmm, i hate to say it but you have a lot of work to do on this : /
The basic concept is sound, but i think you have tied yourself in knots when it comes to relating the rectangles/points/coordinates between displayed image and the actual image.
The problems you are having stem from the fact that you arent consistently converting the coordinates and selections to and from the zoomed image.
For example. When you draw the selection on a zoomed image you use e.Location as m_Start,. In MouseMove you check that the mouse location is inside the original image by converting p to the image location. But if it is inside the bounds then you never adjust newDrop. The result is that the selection is created using m_Start and newDrop coordinates which are not scaled to the original image. eg:

Original Image = 500 x 500.
Picture Box = 250 x 250.

If i click at (100, 100) and drag to (200, 200). selection will be stored as a rectangle 100 x 100 starting at point (100, 100).

But the part of the image i have selected is actually a rectangle 200 x 200 starting at point (200, 200) on the original image.

If you like i can rewrite a portion of your code so you can see how better to approach it :)

k, i couldnt stand to leave it as it was so i went ahead with the re-write. Use or discard it as you see fit :p

The code is essentially the same as yours only tidied up and corrected. I have only rewritten the protions controlling the drawing and moving of the selection. I'll leave it to you to build in the resizing etc from this foundation.

The key here is that everything you do to the picturebox must be related back to the image. The picturebox is intended as an interface between the user and the image. So clicks/movements must be translated back to the image.

By storing the selection relative to the image and scaling it when you paint it also fixes a problem your code had with resizing the form. If you need me to go over anything just let me know :)

And here it is:

class EnhancedPictureBox : PictureBox
    {

       public EnhancedPictureBox()
        {
            this.Paint += new PaintEventHandler(PictureBox1_Paint);
            this.MouseDown += new MouseEventHandler(PictureBox1_MouseDown);
            this.MouseMove += new MouseEventHandler(PictureBox1_MouseMove);
            this.MouseUp += new MouseEventHandler(PictureBox1_MouseUp);

        }

       #region points translations modified from ryshad's post

       private Point ConvertPointToImage(Point clicked)
       {
           if (this.SizeMode == PictureBoxSizeMode.Zoom)
           {
               //get size of original image
               Size size = this.Image.Size;
               //get value of scale
               float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

               //scale size to calculate translation
               size.Width = (int)(size.Width * num);
               size.Height = (int)(size.Height * num);

               //reverse translation
               clicked.X -= (ClientRectangle.Width - size.Width) / 2;
               clicked.Y -= (ClientRectangle.Height - size.Height) / 2;

               //reverse scale
               clicked.X = (int)(clicked.X / num);
               clicked.Y = (int)(clicked.Y / num);

               //return image coordinates
               return clicked;
           }
           else if (this.SizeMode == PictureBoxSizeMode.CenterImage)
           {
               //how the centering works
               //rectangle.X += (rectangle.Width - this.image.Width) / 2;
               // rectangle.Y += (rectangle.Height - this.image.Height) / 2;
               //--

               // got this online
               // - http://www.codeproject.com/KB/miscctrl/PictureBoxExtended.aspx

 
               int diffWidth = this.ClientRectangle.Width - Image.Width;
               int diffHeight = this.ClientRectangle.Height - Image.Height;

               diffWidth /= 2;
               diffHeight /= 2;

               clicked.X -= diffWidth;
               clicked.Y -= diffHeight;

               return clicked;

           }
           else if (this.SizeMode == PictureBoxSizeMode.StretchImage)
           {
               // Make sure our control width and height are not 0
               if (Width == 0 || Height == 0) return clicked;
               // First, get the ratio (image to control) the height and width
               float ratioWidth = (float)Image.Width / Width;
               float ratioHeight = (float)Image.Height / Height;
               // Scale the points by our ratio
               float newX = clicked.X;
               float newY = clicked.Y;
               newX *= ratioWidth;
               newY *= ratioHeight;
               return new Point((int)newX, (int)newY);

           }
           else
           {
               return clicked;
           }
       }

       private Rectangle ConvertRectangleToImage(Rectangle clicked)
       {
           if (this.SizeMode != PictureBoxSizeMode.Zoom)
           {
               return clicked;
           }
           //get size of original image
           Size size = this.Image.Size;
           //get value of scale
           float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

           //scale size to calculate translation
           size.Width = (int)(size.Width * num);
           size.Height = (int)(size.Height * num);

           //reverse translation
           clicked.X -= (ClientRectangle.Width - size.Width) / 2;
           clicked.Y -= (ClientRectangle.Height - size.Height) / 2;

           //reverse scale
           clicked.X = (int)(clicked.X / num);
           clicked.Y = (int)(clicked.Y / num);

           clicked.Width = (int)(clicked.Width / num);
           clicked.Height = (int)(clicked.Height / num);

           //return image coordinates
           return clicked;
       }

        // image coordinates to zoomed methods

       private Point ConvertToZoomed(Point image)
       {
           if (this.SizeMode == PictureBoxSizeMode.Zoom)
           {
               //get size of original image
               Size size = this.Image.Size;

               //get value of scale
               float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

               //scale size to calculate translation
               size.Width = (int)(size.Width * num);
               size.Height = (int)(size.Height * num);

               //apply scale to Point
               image.X = (int)(image.X * num);
               image.Y = (int)(image.Y * num);

               //apply translation to Point
               image.X += (ClientRectangle.Width - size.Width) / 2;
               image.Y += (ClientRectangle.Height - size.Height) / 2;
           }

           //return Zoomed Point
           return image;

       }

       private Rectangle ConvertToZoomed(Rectangle selection)
       {
           if (this.SizeMode == PictureBoxSizeMode.Zoom)
           {
               //get size of original image
               Size size = this.Image.Size;

               //get value of scale
               float num = Math.Min((float)(((float)ClientRectangle.Width) / ((float)size.Width)), (float)(((float)ClientRectangle.Height) / ((float)size.Height)));

               //scale size to calculate translation
               size.Width = (int)(size.Width * num);
               size.Height = (int)(size.Height * num);

               //apply scale to Selection
               selection.X = (int)(selection.X * num);
               selection.Y = (int)(selection.Y * num);
               selection.Width = (int)(selection.Width * num);
               selection.Height = (int)(selection.Height * num);

               //apply translation to Selection
               selection.X += (ClientRectangle.Width - size.Width) / 2;
               selection.Y += (ClientRectangle.Height - size.Height) / 2;
           }

           //return Zoomed Selection
           return selection;
       }

       #endregion


        Rectangle selection;

        bool m_Drawing = false;
        bool m_mover = false;

        Point m_Start;


        private void PictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {

            //convert the point on picturebox to point on image
            Point clicked = ConvertPointToImage(e.Location);

            //ignore any click outside the image bounds
            Rectangle imageBounds = new Rectangle(new Point(0, 0), this.Image.Size);
            if (!imageBounds.Contains(clicked))
                return;

            Rectangle mini = new Rectangle(selection.Location.X + 4, selection.Location.Y + 4, selection.Width - 8, selection.Height - 8);
            if (mini.Contains(clicked))
            {
                m_mover = true;
                m_Start = clicked;
            }
            else
            {
                //Remember where mouse was pressed
                m_Start = clicked;
                //Clear the selection rectangle
                selection = new Rectangle();
                this.Invalidate();
                //Selection drawing is on
                m_Drawing = true;
            }
        }

        private void  // ERROR: Handles clauses are not supported in C#
    PictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //convert the point on picturebox to point on image
            Point clicked = ConvertPointToImage(e.Location);

            //determine image boundaries
            Rectangle imageBounds = new Rectangle(new Point(0, 0), this.Image.Size);

            
            if (m_Drawing)
            {
                //get new Point
                Point newDrop = clicked;

                //if new point is outside picture then adjust it to keep it within bounds
                if (!imageBounds.Contains(clicked))
                {
                    if (clicked.X < 0)
                    {
                        newDrop.X = 0;
                    }
                    if (clicked.X > imageBounds.Width)
                    {
                        newDrop.X = imageBounds.Width;
                    }
                    if (clicked.Y < 0)
                    {
                        newDrop.Y = 0;
                    }
                    if (clicked.Y > imageBounds.Height)
                    {
                        newDrop.Y = imageBounds.Height;
                    }
                }


                //Update selection
                selection = RectangleFromPoints(m_Start, newDrop);
            }
            else if (m_mover)
            {
                //determine distance and direction of movement
                int xChange = clicked.X - m_Start.X;
                int yChange = clicked.Y - m_Start.Y;

                //apply movement to selection
                selection.X += xChange;
                selection.Y += yChange;

                //adjust selection if movement placed it outside image
                if (!imageBounds.Contains(selection))
                {
                    if (selection.X < imageBounds.Left)
                        selection.X = imageBounds.Left;
                    if (selection.Y < imageBounds.Top)
                        selection.Y = imageBounds.Top;
                    if (selection.Right > imageBounds.Right)
                        selection.X = imageBounds.Right - selection.Width;
                    if (selection.Bottom > imageBounds.Bottom)
                        selection.Y = imageBounds.Bottom - selection.Height;                    
                }
                //update starting point
                m_Start = clicked;
            }

            //refresh image
            this.Invalidate();
        }

        //Returns a rectangle from 2 points
        private Rectangle RectangleFromPoints(Point p1, Point p2)
        {
            int x;
            int y;

            if (p1.X <= p2.X)
            {
                x = p1.X;
            }
            else
            {
                x = p2.X;
            }

            if (p1.Y <= p2.Y)
            {
                y = p1.Y;
            }
            else
            {
                y = p2.Y;
            }

            return new Rectangle(x, y, Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y));
        }

        private void  // ERROR: Handles clauses are not supported in C#
    PictureBox1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //end movement/drawing
            m_Drawing = false;
            m_mover = false;
        }


        SolidBrush hbr = new SolidBrush(Color.FromArgb(25, Color.Blue));
        Pen borderpen = new Pen(new SolidBrush(Color.FromArgb(100, Color.Blue)));

        private void
    PictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            if (selection != null)
            {
                //scale selection to picturebox
                Rectangle drawSelection = ConvertToZoomed(selection);

                //draw selection
                e.Graphics.FillRectangle(hbr, drawSelection);
                borderpen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
                e.Graphics.DrawRectangle(borderpen, drawSelection);
            }
        }


    }
Comments
Great job resurrecting my mistakes!

Thanks for the work you put into this, I am about to read through it all and see all what has been changed. I will post back with my questions. I know I will have some. thanks again.

ok, wow. that fixes everything. i wasn't sure til the end. but that's brilliant. immediately convert everything to the image coordinates and work with that and just don't worry about the selection rectangle as it exists on the picture control because just converting it to zoomed takes care of it.

I will likely run into some issues bringing this control all the way through. So I will post back here with further questions.

Thanks!

no problems :) Glad the code works for you.
As i said, the best way to approach it is to look at the pictuerbox as an interface; its purpose is to sit between the user and the data and ensure that input and output correlate.
By processing everything on the scale of the original image it avoids the problem you had where some values are scaled to the picturebox and some arent.

Thanks, everything went well this time around. I created an enum to hold the resize direction and some methods the automatically set the cursor icon and return how the rect needs to be resized. added a crop function that returns a cropped bitmap and optionally copies it to the clipboard.

Its practically a finished control. But i have more plans for it. I thank you again for your assistance. and I hope you will allow me to thank you in the "special thanks" section of the about box for my finished app.

be my guest, i'd be honoured :P
Glad its all up and running, let me know when its finished, i may well add it to my toolbox.

private void TestIfRectInsideArea()
        {
            // Test if rectangle still inside the area.
            if (rect.X < 0) rect.X = 0;\\rectangle location
            if (rect.Y < 0) rect.Y = 0;
            if (rect.Width <= 0) rect.Width = 1;
            if (rect.Height <= 0) rect.Height = 1;

            if (rect.X + rect.Width > pictureBox1.Width)
            {
                rect.Width = pictureBox1.Width - rect.X - 1; // -1 to be still show 
                if (g2 == false) (\\g2- flag to draw or modify rectangle)
                {
                    g2 = false;
                }
            }
            if (rect.Y + rect.Height > pictureBox1.Height)
            {
                rect.Height = pictureBox1.Height - rect.Y - 1;// -1 to be still show 
                if (g2 == false)
                {
                    g2= false;
                }
            }
        }
This question has already been answered. Start a new discussion instead.