C#点击pictureBox获得相对于图片像素的坐标
我们在软件开发实际应用中,经常会遇到测量图片中某一段长度的需求。而在C#中,图片经常显示在pictureBox控件中,鼠标的点击事件只能初步获取光标相当于控件的坐标,而不能直接获取相当于图片中的像素坐标。下面我封装了一个方法用于获取光标相当于图片的像素坐标:
private void GetImagePixLocation(Size pictureBoxSize, Size imageSize, Point pictureBoxPoint, out Point imagePoint)
{
imagePoint = new Point(0, 0);
double scale;
int detalInHeight = 0;
int detalInWidth = 0;
if (Convert.ToDouble(pictureBoxSize.Width) / pictureBoxSize.Height > Convert.ToDouble(imageSize.Width) / imageSize.Height)
{
scale = 1.0 * imageSize.Height / pictureBoxSize.Height;
detalInWidth = Convert.ToInt32((pictureBoxSize.Width * scale - imageSize.Width) / 2.0);
}
else
{
scale = 1.0 * imageSize.Width / pictureBoxSize.Width;
detalInHeight = Convert.ToInt32((pictureBoxSize.Height * scale - imageSize.Height) / 2.0);
}
imagePoint.X = Convert.ToInt32(pictureBoxPoint.X * scale - detalInWidth);
imagePoint.Y = Convert.ToInt32(pictureBoxPoint.Y * scale - detalInHeight);
}
这个方法的第一个参数是pictureBox的尺寸,第二个参数是pictureBox中图片的尺寸,第三个参数是鼠标点击pictureBox时点在pictureBox上面的坐标,第四个参数得到的是点相当于图片中的像素坐标。
下面我们扩展一下,怎么实现转动鼠标滚轮可以光标位置为中心放大缩小图片,按住鼠标左键可任意位置拖动图片,在这种复杂情况下点击pictureBox得到相当于图片的像素坐标。
首先,我们需要一个panel和pictureBox,在panel上面放置一个pictureBox,panel和pictureBox的背景颜色均设置为ActiveCaptionText或黑色,两者的尺寸相同,以使开始时图片铺满整个背景区域,且pictureBox的Dock属性不可设置为Fill。
①、pictureBox的鼠标滚轮事件需要自己定义并添加pictureBox1_MouseLeave方法,我们现在窗体的构造函数中添加此事件,并把图片显示到pictureBox控件中。
public Form2()
{
InitializeComponent();
this.MouseWheel += new MouseEventHandler(pictureBox1_MouseWheel);
Bitmap bitmap = new Bitmap(@"D:\图片\测量拟合\rim.png");
this.pictureBox1.Image = bitmap;
}
private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
{
}
②、添加鼠标点进入和离开panel和pictureBox的事件操作,并添加两个bool变量保存当前状态。
private bool _isCanDealPicture = false;//鼠标在panel或pictureBox上面都可以处理图片
private void panel1_MouseEnter(object sender, EventArgs e)
{
_isCanDealPicture = true;
}
private void panel1_MouseLeave(object sender, EventArgs e)
{
_isCanDealPicture = false;
}
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
_isCanDealPicture = true;
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
_isCanDealPicture = false;
}
③、完善鼠标滚轮滚动事件,实现在panel或pictureBox中滚动滚轮可实现放大和缩小图片,每次缩放步长为1.2倍。
private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
{
if (_isCanDealPicture)
{
double step = 1.2;
if (e.Delta > 0)
{
if (pictureBox1.Height >= Screen.PrimaryScreen.Bounds.Height * 12)
return;
pictureBox1.Height = (int)(pictureBox1.Height * step);
pictureBox1.Width = (int)(pictureBox1.Width * step);
int px = Cursor.Position.X - pictureBox1.Location.X;
int py = Cursor.Position.Y - pictureBox1.Location.Y;
int px_add = (int)(px * (step - 1.0));
int py_add = (int)(py * (step - 1.0));
pictureBox1.Location = new Point(pictureBox1.Location.X - px_add, pictureBox1.Location.Y - py_add);
Application.DoEvents();
}
else
{
if (pictureBox1.Width <= panel1.Width / 10)
return;
pictureBox1.Height = (int)(pictureBox1.Height / step);
pictureBox1.Width = (int)(pictureBox1.Width / step);
int px = Cursor.Position.X - pictureBox1.Location.X;
int py = Cursor.Position.Y - pictureBox1.Location.Y;
int px_add = (int)(px * (1.0 - 1.0 / step));
int py_add = (int)(py * (1.0 - 1.0 / step));
pictureBox1.Location = new Point(pictureBox1.Location.X + px_add, pictureBox1.Location.Y + py_add);
Application.DoEvents();
}
}
}
④、实现鼠标左键按住拖动图片可任意位置移动功能
private bool _moveFlag = false;//当鼠标在pictureBox上面左键按下时,可拖动图片移动
private int _xPos, _yPos;//保存初次点击pictureBox时的位置信息
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
_moveFlag = false;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && _moveFlag)
{
pictureBox1.Left += Convert.ToInt16(e.X - _xPos);
pictureBox1.Top += Convert.ToInt16(e.Y - _yPos);
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_moveFlag = true;
_xPos = e.X;
_yPos = e.Y;
}
}
⑤、在此已经实现了拖动和缩放图片的功能,如果这两种操作之后想得到点击鼠标得到在图片上的像素位置的话,跟上面是步骤是一样,拖动和缩放并不会影响实际位置的变动。