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

后端 未结 2 1706
难免孤独
难免孤独 2021-01-14 19:59

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

相关标签:
2条回答
  • 2021-01-14 20:21

    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
         }
       }
    }
    
    0 讨论(0)
  • 2021-01-14 20:33

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

    0 讨论(0)
提交回复
热议问题