Link to home
Start Free TrialLog in
Avatar of noulouk
noulouk

asked on

Select area in PictureBox

Hi Experts,

Here is my UserControl:

/* Title:
 * PictureBox with zoom and scroll functionallity
 */

#region Usings

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

#endregion

namespace PictureBoxCtrl
{
      /// <summary>
      /// Summary for the PictureBox Ctrl
      /// </summary>
      public class PictureBox : System.Windows.Forms.UserControl
      {
            #region Members

            public System.Windows.Forms.PictureBox PicBox;
            private System.Windows.Forms.Panel OuterPanel;
            private System.ComponentModel.Container components = null;
            private string m_sPicName = "";

        private bool down;
        private Point start;
        private Rectangle selection = Rectangle.Empty;

            #endregion

            #region Constants

            private double ZOOMFACTOR = 1.25;      // = 25% smaller or larger
            private int MINMAX = 5;                        // 5 times bigger or smaller than the ctrl

            #endregion

            #region Designer generated code

            private void InitializeComponent()
            {
                  this.PicBox = new System.Windows.Forms.PictureBox();
                  this.OuterPanel = new System.Windows.Forms.Panel();
                  this.OuterPanel.SuspendLayout();
                  this.SuspendLayout();
                  //
                  // PicBox
                  //
                  this.PicBox.Location = new System.Drawing.Point(0, 0);
                  this.PicBox.Name = "PicBox";
                  this.PicBox.Size = new System.Drawing.Size(150, 140);
                  this.PicBox.TabIndex = 3;
                  this.PicBox.TabStop = false;
                  //
                  // OuterPanel
                  //
                  this.OuterPanel.AutoScroll = true;
                  this.OuterPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
                  this.OuterPanel.Controls.Add(this.PicBox);
                  this.OuterPanel.Dock = System.Windows.Forms.DockStyle.Fill;
                  this.OuterPanel.Location = new System.Drawing.Point(0, 0);
                  this.OuterPanel.Name = "OuterPanel";
                  this.OuterPanel.Size = new System.Drawing.Size(210, 190);
                  this.OuterPanel.TabIndex = 4;
                  //
                  // PictureBox
                  //
                  this.Controls.Add(this.OuterPanel);
                  this.Name = "PictureBox";
                  this.Size = new System.Drawing.Size(210, 190);
                  this.OuterPanel.ResumeLayout(false);
                  this.ResumeLayout(false);

            }
            #endregion

            #region Constructors

            public PictureBox()
            {
                  InitializeComponent ();
                  InitCtrl ();      // my special settings for the ctrl
            }

            #endregion

            #region Properties

            /// <summary>
            /// Property to select the picture which is displayed in the picturebox. If the
            /// file doesn´t exist or we receive an exception, the picturebox displays
            /// a red cross.
            /// </summary>
            /// <value>Complete filename of the picture, including path information</value>
            /// <remarks>Supported fileformat: *.gif, *.tif, *.jpg, *.bmp</remarks>
            [ Browsable ( false ) ]
            public string Picture
            {
                  get { return m_sPicName; }
                  set
                  {
                        if ( null != value )
                        {
                              if ( System.IO.File.Exists ( value ) )
                              {
                                    try
                                    {
                                          PicBox.Image = Image.FromFile ( value );
                                          m_sPicName = value;
                                    }
                                    catch ( OutOfMemoryException ex )
                                    {
                                          RedCross ();
                                    }
                              }
                              else
                              {                        
                                    RedCross ();
                              }
                        }
                  }
            }

            /// <summary>
            /// Set the frametype of the picturbox
            /// </summary>
            [ Browsable ( false ) ]
            public BorderStyle Border
            {
                  get { return OuterPanel.BorderStyle; }
                  set { OuterPanel.BorderStyle = value; }
            }

        public Rectangle Selection
        {
            get { return selection; }
        }
      

            #endregion

            #region Other Methods

            /// <summary>
            /// Special settings for the picturebox ctrl
            /// </summary>
            private void InitCtrl ()
            {
                  PicBox.SizeMode = PictureBoxSizeMode.StretchImage;
            PicBox.Location = new Point ( 0, 0 );
            PicBox.SizeMode = PictureBoxSizeMode.AutoSize;
                  OuterPanel.Dock = DockStyle.Fill;
                  //OuterPanel.Cursor = System.Windows.Forms.Cursors.NoMove2D;
                  OuterPanel.AutoScroll = true;
                  OuterPanel.MouseEnter += new EventHandler(PicBox_MouseEnter);
                  PicBox.MouseEnter += new EventHandler(PicBox_MouseEnter);
                  OuterPanel.MouseWheel += new MouseEventHandler(PicBox_MouseWheel);
            PicBox.MouseDown += new MouseEventHandler(PicBox_MouseDown);
            PicBox.MouseMove += new MouseEventHandler(PicBox_MouseMove);
            PicBox.MouseUp += new MouseEventHandler(PicBox_MouseUp);
            }

        void PicBox_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                WindowsApplicationPlayer.NativeWIN32.InvalidateRect(IntPtr.Zero, IntPtr.Zero, true);
                //ControlPaint.DrawReversibleFrame(selection, this.BackColor, FrameStyle.Dashed);
                down = true;
                selection = Rectangle.Empty;
                ControlPaint.DrawReversibleFrame(selection, this.BackColor, FrameStyle.Dashed);
                start = this.PointToScreen(new Point(e.X, e.Y));
            }
        }

        void PicBox_MouseMove(object sender, MouseEventArgs e)
        {
            if (down)
            {
                ControlPaint.DrawReversibleFrame(selection, this.BackColor, FrameStyle.Dashed);

                Point end = this.PointToScreen(new Point(e.X, e.Y));
                selection = new Rectangle(start.X, start.Y, end.X - start.X, end.Y - start.Y);

                ControlPaint.DrawReversibleFrame(selection, this.BackColor, FrameStyle.Dashed);
            }
        }

        void PicBox_MouseUp(object sender, MouseEventArgs e)
        {
            if (down)
            {
                //ControlPaint.DrawReversibleFrame(selection, this.BackColor, FrameStyle.Dashed);
                down = false;
            }
        }
            /// <summary>
            /// Create a simple red cross as a bitmap and display it in the picturebox
            /// </summary>
            private void RedCross ()
            {
                  Bitmap bmp = new Bitmap ( OuterPanel.Width, OuterPanel.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb555 );
                  Graphics gr;
                  gr = Graphics.FromImage ( bmp );
                  Pen pencil = new Pen ( Color.Red, 5 );
                  gr.DrawLine ( pencil, 0, 0, OuterPanel.Width, OuterPanel.Height );
                  gr.DrawLine ( pencil, 0, OuterPanel.Height, OuterPanel.Width, 0  );
                  PicBox.Image = bmp;
                  gr.Dispose ();
            }

            #endregion

            #region Zooming Methods

            /// <summary>
            /// Make the PictureBox dimensions larger to effect the Zoom.
            /// </summary>
            /// <remarks>Maximum 5 times bigger</remarks>
            private void ZoomIn()
            {
            if ( ( PicBox.Width < ( MINMAX * OuterPanel.Width ) ) &&
                        ( PicBox.Height < ( MINMAX * OuterPanel.Height ) ) )
                  {
                        PicBox.Width = Convert.ToInt32 ( PicBox.Width * ZOOMFACTOR );
                        PicBox.Height = Convert.ToInt32 ( PicBox.Height * ZOOMFACTOR );
                        PicBox.SizeMode = PictureBoxSizeMode.StretchImage;
                  }
            }

            /// <summary>
            /// Make the PictureBox dimensions smaller to effect the Zoom.
            /// </summary>
            /// <remarks>Minimum 5 times smaller</remarks>
            private void ZoomOut()
            {
            if ( ( PicBox.Width > ( OuterPanel.Width / MINMAX ) ) &&
                        ( PicBox.Height > ( OuterPanel.Height / MINMAX ) ) )
                  {
                        PicBox.SizeMode = PictureBoxSizeMode.StretchImage;
                        PicBox.Width = Convert.ToInt32 ( PicBox.Width / ZOOMFACTOR );
                        PicBox.Height = Convert.ToInt32 ( PicBox.Height / ZOOMFACTOR );
                  }            
            }

            #endregion

            #region Mouse events

            /// <summary>
            /// We use the mousewheel to zoom the picture in or out
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void PicBox_MouseWheel(object sender, MouseEventArgs e)
            {
            //ControlPaint.DrawReversibleFrame(selection, this.BackColor, FrameStyle.Dashed);
            //if ( e.Delta < 0 )
            //{
            //    ZoomIn ();
            //}
            //else
            //{
            //    ZoomOut ();
            //}
            }

            /// <summary>
            /// Make sure that the PicBox have the focus, otherwise it doesn´t receive
            /// mousewheel events !.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void PicBox_MouseEnter(object sender, EventArgs e)
            {
                  if ( PicBox.Focused == false )
                  {
                        PicBox.Focus ();
                  }
            }

            #endregion

            #region Disposing

            /// <summary>
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if( components != null )
                              components.Dispose();
                  }
                  base.Dispose( disposing );
            }

            #endregion
      }
}

The problem is when I select an area of my image:
if I don't use the scrollbars, the rectangle is correctly drawn.
if I move scrollbars up or down, then the rectangle is drawn to a wrong location (often outside of the picture and very far from the mouse).

Thanks in advance for your help.
ASKER CERTIFIED SOLUTION
Avatar of AlexFM
AlexFM

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of noulouk
noulouk

ASKER

Perfect thank you.