如何防止多个图像相互重叠

时间:2018-03-09 10:16:01

标签: c# visual-studio

我正在尝试在表单中创建一些自定义按钮,理论上应该如下图所示:

Buttons

我创建了自定义窗体控件类来制作每个按钮。它们是使用PictureBox实现的,PictureBox为点击状态保存一个图像,为未点击状态保存另一个图像。该课程的代码如下:

public partial class MyCustomButton: PictureBox
{
    public MyCustomButton()
    {
        InitializeComponent();

    }

    //variables
    private Image NormalImage;
    private Image ClickedImage;

    //public properties
    public Image ImangeNormal
    {
        get { return NormalImage; }
        set { NormalImage = value; }
    }
    public Image ImageClicked
    {
        get { return ClickedImage; }
        set { ClickedImage = value; }
    }

    //Button event properties implementation
    private void MyCustomButton_MouseDown(object sender, MouseEventArgs e)
    {
        if (HitTest(this, e.X, e.Y))
            this.Image = ClickedImage;

    }

    private void MyCustomButton_MouseUp(object sender, MouseEventArgs e)
    {
        if (HitTest(this, e.X, e.Y))
            this.Image = NormalImage;
    }

    private void MyCustomButton_MouseMove(object sender, MouseEventArgs e)
    {
        {
            if (HitTest(this, e.X, e.Y))
                this.Cursor = Cursors.Hand;
            else
                this.Cursor = Cursors.Default;
        }
    }

    //Test if the mouse is over the 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;
    }
}

正如您在上面的课程中看到的,它测试鼠标是否在实际图像上而不是PictureBox的背景上;并且只有在实际图像上单击时,才会显示单击的图像。但由于PictureBox的矩形形状如下图所示,我仍无法纠正PictureBoxes相互重叠的问题:

Overlapping Buttons

我也知道在 Picturebox.Backcolor 属性中设置背景透明,会使背景对其父类透明。但是,因为,每个PictureBox与其他2个图片框以及表格部分重叠。怎么能成为可能呢?最有可能的情况是,使用PictureBox无法完成;但是用Label实现。我试图为此编码,但没有成功。如何实现点击和普通图像,以及通过标签解决它的 HitTest(PictureBox控件,int x,int y) 方法?如果有人能帮助我解决这个问题,或找到解决方法,我将非常感激。

1 个答案:

答案 0 :(得分:1)

我可以通过覆盖OnPaint事件来绘制三角形然后将Region设置为相同的区域来制作一个简单的三角形按钮。

我没有花时间让控制旋转,它只是为了说明而涂成灰色。我已经评论了需要改变以支持这些事情的代码的关键点。

class ArrowButton : Button
{
    protected override void OnPaint(PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.SmoothingMode = SmoothingMode.HighQuality;
        float h = this.Height;
        float w = this.Width;

        // This defines the shape of the triangle
        // This is an upwards pointing triangle
        PointF[] pts = new PointF[] { new PointF(w / 2, 0), new PointF(0, w), new PointF(w, h) };

        // This points down
        //PointF[] pts = new PointF[] { new PointF(0, 0), new PointF(w, 0), new PointF(w / 2, h) };

        // Paints the triangle a grey colour
        g.FillPolygon(Brushes.Gray, pts);

        GraphicsPath gp = new GraphicsPath();
        gp.AddPolygon(pts);
        this.Region = new Region(gp);
    }
}

将控件添加到表单并确保其具有方形尺寸。它们看起来像是在设计师中重叠,但点击事件只会在三角区域内发射。