PictureBox - 处理图像非透明区域的点击事件
PictureBox - Handle Click Event on Non-Transparent Area of Image
我必须在 C# 中创建一个 windows 表单,其中两个 PictureBox 重叠。 TopPictureBox 包含一个透明的 png 图片。默认情况下,可以通过单击 TopPictureBox 中图像的任何可见或透明区域来单击 TopPictureBox。但我想让 TopPictureBox 只能通过单击图像的可见区域而不是透明区域来单击。另外我想让光标只在图像的可见区域发生变化,而不是在透明区域。
有什么办法可以做到这些吗?
我正在使用此代码使 TopPictureBox 透明。
TopPictureBox.BackColor = Color.Transparent;
感谢您的帮助。
一种方法是检查用户单击的像素颜色是否与表单的背景颜色相同。如果是,则用户点击了透明区域。
(注意:如Reza所述,此代码只能在没有重叠的PictureBoxes时使用,即只有当图像的透明区域与Form的背景颜色相同时)
Color pixelColour;
private void myPicturebox_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
pixelColour = ((Bitmap)myPicturebox.Image).GetPixel(point.X, point.Y);
if (this.BackColor == pixelColour)
{
// User clicked on transparent area
}
else
{
// User clicked on image
}
}
}
检查 PictureBox
中的位置是否为 Transparent
取决于 PictureBox
的 Image
和 SizeMode
属性。
你不能简单地使用GetPixel
of Bitmap
因为图像位置和大小根据SizeMode
是不同的。您应该首先根据 SizeMode
:
检测 Image
的大小和位置
public bool HitTest(PictureBox control, int x, int y)
{
var result = false;
if (control.Image == null)
return result;
var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var r = (Rectangle)method.Invoke(control, new object[] { control.SizeMode });
using (var bm = new Bitmap(r.Width, r.Height))
{
using (var g = Graphics.FromImage(bm))
g.DrawImage(control.Image, 0, 0, r.Width, r.Height);
if (r.Contains(x, y) && bm.GetPixel(x - r.X, y - r.Y).A != 0)
result = true;
}
return result;
}
那么你可以简单地使用HitTest
方法来检查鼠标是否在PictureBox
的非透明区域上:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (HitTest(pictureBox1,e.X, e.Y))
pictureBox1.Cursor = Cursors.Hand;
else
pictureBox1.Cursor = Cursors.Default;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if (HitTest(pictureBox1, e.X, e.Y))
MessageBox.Show("Clicked on Image");
}
同时将 BackColor
设置为 Color.Transparent
只会使 PictureBox
相对于其父项透明。例如,如果您在 Form
中有 2 PictureBox
设置透明背景色,只会导致您看到表格的背景。要制作一个支持透明背景的PictureBox
,你应该自己绘制控件后面的内容。您可以在这个 post 中找到一个 TransparentPictureBox
:
我必须在 C# 中创建一个 windows 表单,其中两个 PictureBox 重叠。 TopPictureBox 包含一个透明的 png 图片。默认情况下,可以通过单击 TopPictureBox 中图像的任何可见或透明区域来单击 TopPictureBox。但我想让 TopPictureBox 只能通过单击图像的可见区域而不是透明区域来单击。另外我想让光标只在图像的可见区域发生变化,而不是在透明区域。
有什么办法可以做到这些吗?
我正在使用此代码使 TopPictureBox 透明。
TopPictureBox.BackColor = Color.Transparent;
感谢您的帮助。
一种方法是检查用户单击的像素颜色是否与表单的背景颜色相同。如果是,则用户点击了透明区域。
(注意:如Reza所述,此代码只能在没有重叠的PictureBoxes时使用,即只有当图像的透明区域与Form的背景颜色相同时)
Color pixelColour;
private void myPicturebox_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
pixelColour = ((Bitmap)myPicturebox.Image).GetPixel(point.X, point.Y);
if (this.BackColor == pixelColour)
{
// User clicked on transparent area
}
else
{
// User clicked on image
}
}
}
检查 PictureBox
中的位置是否为 Transparent
取决于 PictureBox
的 Image
和 SizeMode
属性。
你不能简单地使用GetPixel
of Bitmap
因为图像位置和大小根据SizeMode
是不同的。您应该首先根据 SizeMode
:
Image
的大小和位置
public bool HitTest(PictureBox control, int x, int y)
{
var result = false;
if (control.Image == null)
return result;
var method = typeof(PictureBox).GetMethod("ImageRectangleFromSizeMode",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var r = (Rectangle)method.Invoke(control, new object[] { control.SizeMode });
using (var bm = new Bitmap(r.Width, r.Height))
{
using (var g = Graphics.FromImage(bm))
g.DrawImage(control.Image, 0, 0, r.Width, r.Height);
if (r.Contains(x, y) && bm.GetPixel(x - r.X, y - r.Y).A != 0)
result = true;
}
return result;
}
那么你可以简单地使用HitTest
方法来检查鼠标是否在PictureBox
的非透明区域上:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (HitTest(pictureBox1,e.X, e.Y))
pictureBox1.Cursor = Cursors.Hand;
else
pictureBox1.Cursor = Cursors.Default;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if (HitTest(pictureBox1, e.X, e.Y))
MessageBox.Show("Clicked on Image");
}
同时将 BackColor
设置为 Color.Transparent
只会使 PictureBox
相对于其父项透明。例如,如果您在 Form
中有 2 PictureBox
设置透明背景色,只会导致您看到表格的背景。要制作一个支持透明背景的PictureBox
,你应该自己绘制控件后面的内容。您可以在这个 post 中找到一个 TransparentPictureBox
: