I have to make a windows form in C# where two PictureBox are overlapping. TopPictureBox is containing a transparent png picture. By default TopPictureBox can be clicked by c
One way is to check whether the colour of the pixel where the user clicked, is the same as the background colour of the form. If yes, then the user clicked on a transparent area.
(Note : As Reza mentioned, this code can be used only when there are no overlapping PictureBoxes, i.e. only when the transparent area of the image is of the same colour as the Form's background)
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
}
}
}
Checking if a position in PictureBox
is Transparent
or not depends on the Image
and SizeMode
property of PictureBox
.
You can not simply use GetPixel
of Bitmap
because the image location and size is different based on SizeMode
. You should first detect the size and location of Image
based on SizeMode
:
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;
}
Then you can simply use HitTest
method to check if the mouse is over a non-transparent area of 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");
}
Also setting BackColor
to Color.Transparent
only makes the PictureBox
transparent relative to it's parent. For example if you have 2 PictureBox
in a Form
setting the transparent back color, just cause you see the background of form. To make a PictureBox
which supports transparent background, you should draw what is behind the control yourself. You can find a TransparentPictureBox
in this post: How to make two transparent layer with c#?