Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
826 views
in Technique[技术] by (71.8m points)

c# - PictureBox - Handle Click Event on Non-Transparent Area of Image

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 clicking any visible or transparent area of the image in TopPictureBox. But I want to make that TopPictureBox only can be clicked by clicking visible area of image, not in transparent area. Also I want to make that cursor will only change on the visible area of the image, not in transparent area.

IS THERE ANY WAY TO DO THESE?

I am using this code to make TopPictureBox transparent.

TopPictureBox.BackColor = Color.Transparent;

Thank You for Help.

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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#?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.8k users

...