System.ArgumentException:参数无效。 GraphicsPath.AddString

时间:2014-07-15 08:06:20

标签: c# argumentexception

所以我在调试时遇到了这个问题,我得到了一个访问冲突,但是当我在没有调试器的情况下运行时,我得到一个错误,告诉我A参数无效。它引导我到path.AddString(...);有什么理由为什么?老实说,所有参数都是正确的,否则编译器会抓住它。这让我很生气。

        protected override void OnPaint( PaintEventArgs e )
        {
            Graphics g = e.Graphics;
            if ( !extended )
            {
                setColor ( );
                g.FillRectangle ( new SolidBrush ( currColor ), this.ClientRectangle );
            }
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            string szbuf = Program.AppName;
            SolidBrush brushWhite = new SolidBrush ( Color.White );
            g.FillRectangle ( brushWhite, 0, 0,
            this.ClientSize.Width, this.ClientSize.Height );

            FontFamily fontFamily = this.Font.FontFamily;
            StringFormat strformat = StringFormat.GenericDefault;
            SolidBrush brush = new SolidBrush ( Color.FromArgb ( 255, 255, 255 ) );

            SizeF sz = g.MeasureString(szbuf, this.Font);
            int w = ( ( this.Width / 2 ) - ( ( int ) sz.Width / 2 ) );
            int h = 10;
            GraphicsPath path = new GraphicsPath ( );
            float emSize = g.DpiY * this.Font.Size / 72;
            path.AddString ( szbuf, fontFamily, 0, 48f, new Point ( w, h ), strformat);

            for ( int i = 1; i < 8; ++i )
            {
                Pen pen = new Pen ( getColor ( ), i ); //Color.FromArgb ( 32, 0, 128,  192 ), i );
                pen.LineJoin = LineJoin.Round;
                g.DrawPath ( pen, path );
                pen.Dispose ( );
            }

            g.FillPath ( brush, path );

            fontFamily.Dispose ( );
            path.Dispose ( );
            brush.Dispose ( );
            g.Dispose ( );
        }

1 个答案:

答案 0 :(得分:2)

这一行:

fontFamily.Dispose();

您正在处置this.Font.FontFamily个对象。 Control将处于无效状态,下次对Paint的调用将失败。你也处理Graphics对象,不要这样做,因为它可能在你的功能之后使用。

一般来说,你必须只处理你创建的对象,不多也不少(创建者有责任处置这些对象)。编译器无法捕获此类错误(除非您运行静态代码分析),因为它是由程序执行路径引起的运行时错误。如果你很幸运,你会有一个例外(ArgumentException,因为你传递了一个无效的参数:一个处置字体)。

此外,您无需明确调用Dispose(),使用using语句更安全(在例外情况下也可以使用)。让我重构你的代码

protected override void OnPaint(PaintEventArgs e)
{
    Graphics g = e.Graphics;
    if (!extended)
    {
        setColor();
        using (var backgroundBrush = new SolidBrush(currColor))
        {
            g.FillRectangle(backgroundBrush, this.ClientRectangle);
        }
    }

    g.SmoothingMode = SmoothingMode.AntiAlias;
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;

    string szbuf = Program.AppName;

    g.FillRectangle(Brushes.White, 0, 0,
        this.ClientSize.Width, this.ClientSize.Height);

    StringFormat strformat = StringFormat.GenericDefault;

    SizeF sz = g.MeasureString(szbuf, this.Font);
    int w = ((this.Width / 2) - ((int)sz.Width / 2));
    int h = 10;

    using (var path = new GraphicsPath())
    {
        float emSize = g.DpiY * this.Font.Size / 72;
        path.AddString(szbuf, Font.FontFamily, 0, 48f, new Point(w, h), strformat);

        for (int i = 1; i < 8; ++i)
        {
            using (var pen = new Pen(getColor(), i))
            {
                pen.LineJoin = LineJoin.Round;
                g.DrawPath(pen, path);
            }
        }

        g.FillPath(Brushes.White, path);
    }
}

请注意,为每种涂料创建资源效率不高(允许但非常慢)。您应该尽可能多地重用它们(例如使用字典)。此外,对于恒定颜色,最好使用预定义的画笔(例如Brushes.White,不要处置它们)。让我展示一个非常天真的实现(很容易扩展到缓存PenSolidBrush):

private Dictionary<Color, SolidBrush> _solidBrushes;
private SolidBrush GetSolidBrush(Color color)
{
    if (_solidBrushes == null)
         _solidBrushes = new Dictionary<Color, SolidBrush>();

    if (!_solidBrushes.ContainsKey(color))
        _solidBrushes.Add(color, new SolidBrush(color));

    return _solidBrushes[color];
}

然后就会像这样使用:

if (!extended)
{
    setColor();
    g.FillRectangle(GetSolidBrush(currColor), this.ClientRectangle);
}