如何正确显示重叠的用户控件?

时间:2012-01-31 20:55:46

标签: c# .net winforms user-controls

我使用C#,VisualStudio 2010,我为Windows窗体应用程序创建了一个自定义UserControl。除了展示自己并允许自己被拖到其他地方之外,他们没有太多的行为。然而,它们是圆形的,当它们在角落重叠时我无法正确显示它们。

以下是我在屏幕上绘制它们的代码:

  public void Circle_Paint(object sender, PaintEventArgs e)
  {
     var g = e.Graphics;

     g.FillEllipse(brushForOuterCircle, 0, 0, Width, Height);
     g.FillEllipse(brushForInnerCircle, lineWidth, lineWidth, Width - 2*lineWidth, Height - 2*lineWidth);

     if(!textLocation.HasValue)
     {
        SizeF m = g.MeasureString(text, textFont);
        textLocation = new PointF((float)((Width - m.Width)/2.0), (float)((Height - m.Height)/2.0));
     }
     g.DrawString(text, textFont, brushForText, textLocation.Value);
  }

以下是错误显示的示例,AB圈的东南部分不显示,因为CD会覆盖该区域。

enter image description here 我应该如何防止这种情况,有没有办法告诉UserControl"默认情况下你是透明的;我不能画的任何部分应该保持如此" ?

3 个答案:

答案 0 :(得分:3)

尝试:

通过覆盖

在您的用户控件上设置第一个WS_EX_COMPOSITED扩展样式
protected override CreateParams CreateParams
{
   get
   {
     CreateParams cp = base.CreateParams;
     cp.ExStyle |= 0x00000020; // add this
     return cp;
   }
}

之后不要在背景中画任何东西

protected override void OnPaintBackground(PaintEventArgs e)
{
   // leave this empty 
}

最后在Paint画出你的形状。

应该工作。

答案 1 :(得分:1)

试试这个。按照此处的建议创建TransparencyControl:Transparent images with C# WinForms

using System;
using System.Windows.Forms;
using System.Drawing;

public class TransparentControl : Control
{
    private readonly Timer refresher;
    private Image _image;

    public TransparentControl()
    {
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        BackColor = Color.Transparent;
        refresher = new Timer();
        refresher.Tick += TimerOnTick;
        refresher.Interval = 50;
        refresher.Enabled = true;
        refresher.Start();
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;
            return cp;
        }
    }

    protected override void OnMove(EventArgs e)
    {
        RecreateHandle();
    }


    protected override void OnPaint(PaintEventArgs e)
    {
        if (_image != null)
        {
            e.Graphics.DrawImage(_image, (Width / 2) - (_image.Width / 2), (Height / 2) - (_image.Height / 2));
        }
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
       //Do not paint background
    }

    //Hack
    public void Redraw()
    {
        RecreateHandle();
    }

    private void TimerOnTick(object source, EventArgs e)
    {
        RecreateHandle();
        refresher.Stop();
    }

    public Image Image
    {
        get
        {
            return _image;
        }
        set
        {
            _image = value;
            RecreateHandle();
        }
    }
}

答案 2 :(得分:1)

您还应该设置区域,使其忽略应该透明的区域的鼠标单击。以下面的控件为例。这是一个描绘圆圈的控件。我将Region设置为Ellipse,导致WinForms不绘制圆圈外的区域。通过设置区域,它也知道忽略区域外区域的鼠标点击。


using System;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public class RoundControl : Control
    {
        private readonly GraphicsPath _path;

        public RoundControl()
        {
            _path = new GraphicsPath();
        }

        protected override void OnResize(EventArgs e)
        {
            _path.Reset();
            _path.AddEllipse(ClientRectangle);
            Invalidate(Region);
            Region = new Region(_path);
            base.OnResize(e);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _path.Dispose();
            }
            base.Dispose(disposing);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            using (Pen borderPen = new Pen(ForeColor, 8))
            {
                e.Graphics.DrawEllipse(borderPen, ClientRectangle);
            }
            base.OnPaint(e);
        }
    }
}

This is what two 'RoundControl' instances look like when rendered in a Form