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;
}