使用没有提示的饼图形式创建自定义控件?

时间:2014-03-16 16:45:56

标签: c# custom-controls

我想用馅饼的形式创建一个自己的Control,而不是像之后的​​图片中的尖端。我只是不知道如何使这个工作。
http://www.directupload.net/file/d/3563/a3hvpodw_png.htm

//编辑:
好的,我忘了提到我想在之后填写它。所以,如果我是对的,我需要一个区域,但我不知道该怎么做。说实话,到目前为止我没有考虑过你的想法。我到目前为止只使用了一个Pie,就像这样:

Graphics gfx = pe.Graphics;         
Pen p = new Pen(Color.Red);
gfx.DrawPie(p, 0, 0, 200, 200, 0, 45);
base.OnPaint(pe);

这是我第一次使用自定义控件,很抱歉,如果我要问的是有点傻。

2 个答案:

答案 0 :(得分:0)

试试这个:

class ShapedControl : Control
{
    private float startAngle;
    private float sweepAngle;
    private float innerRadius;
    private float outerRadius;

    public ShapedControl()
    {
        InnerRadius = 30;
        OuterRadius = 60;
        StartAngle = 0;
        SweepAngle = 360;
    }

    [DefaultValue(0)]
    [Description("The starting angle for the pie section, measured in degrees clockwise from the X-axis.")]
    public float StartAngle
    {
        get { return startAngle; }
        set
        {
            startAngle = value;
            Invalidate();
        }
    }

    [DefaultValue(360)]
    [Description("The angle between StartAngle and the end of the pie section, measured in degrees clockwise from the X-axis.")]
    public float SweepAngle
    {
        get { return sweepAngle; }
        set
        {
            sweepAngle = value;
            Invalidate();
        }
    }

    [DefaultValue(20)]
    [Description("Inner radius of the excluded inner area of the pie")]
    public float InnerRadius
    {
        get { return innerRadius; }
        set
        {
            innerRadius = value;
            Invalidate();
        }
    }

    [DefaultValue(30)]
    [Description("Outer radius of the pie")]
    public float OuterRadius
    {
        get { return outerRadius; }
        set
        {
            outerRadius = value;
            Invalidate();
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        Graphics g = e.Graphics;
        g.Clear(this.BackColor);

        GraphicsPath gp1 = new GraphicsPath();
        GraphicsPath gp2 = new GraphicsPath();

        float xInnerPos = -innerRadius / 2f + this.Width / 2f;
        float yInnerPos = -innerRadius / 2f + this.Height / 2f;
        float xOuterPos = -outerRadius / 2f + this.Width / 2f;
        float yOuterPos = -outerRadius / 2f + this.Height / 2f;

        if (innerRadius != 0.0)
            gp1.AddPie(xInnerPos, yInnerPos, innerRadius, innerRadius, startAngle, sweepAngle);
        gp2.AddPie(xOuterPos, yOuterPos, outerRadius, outerRadius, startAngle, sweepAngle);

        Region rg1 = new System.Drawing.Region(gp1);
        Region rg2 = new System.Drawing.Region(gp2);

        g.DrawPath(Pens.Transparent, gp1);
        g.DrawPath(Pens.Transparent, gp2);

        rg1.Xor(rg2);

        g.FillRegion(Brushes.Black, rg1);

        this.Region = rg1;

    }

    //Just for testing purpose. Place a breakpoint
    //in here and you'll see it will only get called when
    //you click inside the "pie" shape
    protected override void OnClick(EventArgs e)
    {
        base.OnClick(e);
    }
}

编辑:通过将形状居中并为VS Designer添加属性,从另一个答案中窃取,使代码更好; - )

更多编辑:处理内半径== 0

的情况

答案 1 :(得分:0)

尝试这个复杂形状控件的代码示例 您可以使用StartAngleSweepAngleInnerPercent属性控制其形状。

public partial class PathUserControl : UserControl
{
    private readonly GraphicsPath outerPath = new GraphicsPath();
    private readonly GraphicsPath innerPath = new GraphicsPath();
    private float startAngle;
    private float sweepAngle = 60;
    private float innerPercent = 30;

    public PathUserControl()
    {
        base.BackColor = SystemColors.ControlDark;
    }

    [DefaultValue(0)]
    [Description("The starting angle for the pie section, measured in degrees clockwise from the X-axis.")]
    public float StartAngle
    {
        get { return startAngle; }
        set
        {
            startAngle = value;
            SetRegion();
        }
    }

    [DefaultValue(60)]
    [Description("The angle between StartAngle and the end of the pie section, measured in degrees clockwise from the X-axis.")]
    public float SweepAngle
    {
        get { return sweepAngle; }
        set
        {
            sweepAngle = value;
            SetRegion();
        }
    }

    [DefaultValue(30)]
    [Description("Percent of the radius of the excluded inner area of the pie, measured from 0 to 100.")]
    public float InnerPercent
    {
        get { return innerPercent; }
        set
        {
            if (value < 0 || value > 100f)
                throw new ArgumentOutOfRangeException("value", "Percent must be in the range 0 .. 100");
            innerPercent = value;
            SetRegion();
        }
    }

    protected override void OnResize(EventArgs e)
    {
        base.OnResize(e);
        SetRegion();
    }

    private void SetRegion()
    {
        if (Region != null)
        {
            Region.Dispose();
            Region = null;
        }

        if (ClientSize.IsEmpty)
            return;

        float innerCoef = 0.01f * InnerPercent;

        outerPath.Reset();
        innerPath.Reset();
        outerPath.AddPie(0, 0, ClientSize.Width, ClientSize.Height, StartAngle, SweepAngle);
        innerPath.AddPie(ClientSize.Width * (1 - innerCoef) / 2, ClientSize.Height * (1 - innerCoef) / 2, ClientSize.Width * innerCoef, ClientSize.Height * innerCoef, StartAngle, SweepAngle);

        Region region = new Region(outerPath);
        region.Xor(innerPath);

        Region = region;
    }
}

编辑带有XOR的@LucMorin想法很棒,我已经偷了它。