所以我在调试时遇到了这个问题,我得到了一个访问冲突,但是当我在没有调试器的情况下运行时,我得到一个错误,告诉我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 ( );
}
答案 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
,不要处置它们)。让我展示一个非常天真的实现(很容易扩展到缓存Pen
和SolidBrush
):
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);
}