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.UserC ontrol
{
#region Members
public System.Windows.Forms.Pictu reBox PicBox;
private System.Windows.Forms.Panel OuterPanel;
private System.ComponentModel.Cont ainer 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.Pictu reBox();
this.OuterPanel = new System.Windows.Forms.Panel ();
this.OuterPanel.SuspendLay out();
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.BorderStyl e = System.Windows.Forms.Borde rStyle.Fix edSingle;
this.OuterPanel.Controls.A dd(this.Pi cBox);
this.OuterPanel.Dock = System.Windows.Forms.DockS tyle.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.Out erPanel);
this.Name = "PictureBox";
this.Size = new System.Drawing.Size(210, 190);
this.OuterPanel.ResumeLayo ut(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.Stretch Image;
PicBox.Location = new Point ( 0, 0 );
PicBox.SizeMode = PictureBoxSizeMode.AutoSiz e;
OuterPanel.Dock = DockStyle.Fill;
//OuterPanel.Cursor = System.Windows.Forms.Curso rs.NoMove2 D;
OuterPanel.AutoScroll = true;
OuterPanel.MouseEnter += new EventHandler(PicBox_MouseE nter);
PicBox.MouseEnter += new EventHandler(PicBox_MouseE nter);
OuterPanel.MouseWheel += new MouseEventHandler(PicBox_M ouseWheel) ;
PicBox.MouseDown += new MouseEventHandler(PicBox_M ouseDown);
PicBox.MouseMove += new MouseEventHandler(PicBox_M ouseMove);
PicBox.MouseUp += new MouseEventHandler(PicBox_M ouseUp);
}
void PicBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
WindowsApplicationPlayer.N ativeWIN32 .Invalidat eRect(IntP tr.Zero, IntPtr.Zero, true);
//ControlPaint.DrawReversi bleFrame(s election, this.BackColor, FrameStyle.Dashed);
down = true;
selection = Rectangle.Empty;
ControlPaint.DrawReversibl eFrame(sel ection, this.BackColor, FrameStyle.Dashed);
start = this.PointToScreen(new Point(e.X, e.Y));
}
}
void PicBox_MouseMove(object sender, MouseEventArgs e)
{
if (down)
{
ControlPaint.DrawReversibl eFrame(sel ection, 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.DrawReversibl eFrame(sel ection, this.BackColor, FrameStyle.Dashed);
}
}
void PicBox_MouseUp(object sender, MouseEventArgs e)
{
if (down)
{
//ControlPaint.DrawReversi bleFrame(s election, 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.Pix elFormat.F ormat16bpp Rgb555 );
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.Stretch Image;
}
}
/// <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.Stretch Image;
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.DrawReversi bleFrame(s election, 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.
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.UserC
{
#region Members
public System.Windows.Forms.Pictu
private System.Windows.Forms.Panel
private System.ComponentModel.Cont
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.Pictu
this.OuterPanel = new System.Windows.Forms.Panel
this.OuterPanel.SuspendLay
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
this.OuterPanel.BorderStyl
this.OuterPanel.Controls.A
this.OuterPanel.Dock = System.Windows.Forms.DockS
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.Out
this.Name = "PictureBox";
this.Size = new System.Drawing.Size(210, 190);
this.OuterPanel.ResumeLayo
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.Stretch
PicBox.Location = new Point ( 0, 0 );
PicBox.SizeMode = PictureBoxSizeMode.AutoSiz
OuterPanel.Dock = DockStyle.Fill;
//OuterPanel.Cursor = System.Windows.Forms.Curso
OuterPanel.AutoScroll = true;
OuterPanel.MouseEnter += new EventHandler(PicBox_MouseE
PicBox.MouseEnter += new EventHandler(PicBox_MouseE
OuterPanel.MouseWheel += new MouseEventHandler(PicBox_M
PicBox.MouseDown += new MouseEventHandler(PicBox_M
PicBox.MouseMove += new MouseEventHandler(PicBox_M
PicBox.MouseUp += new MouseEventHandler(PicBox_M
}
void PicBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
WindowsApplicationPlayer.N
//ControlPaint.DrawReversi
down = true;
selection = Rectangle.Empty;
ControlPaint.DrawReversibl
start = this.PointToScreen(new Point(e.X, e.Y));
}
}
void PicBox_MouseMove(object sender, MouseEventArgs e)
{
if (down)
{
ControlPaint.DrawReversibl
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.DrawReversibl
}
}
void PicBox_MouseUp(object sender, MouseEventArgs e)
{
if (down)
{
//ControlPaint.DrawReversi
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.Pix
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.Stretch
}
}
/// <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.Stretch
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.DrawReversi
//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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER