如何避免Graphics.MeasureString()因无效零宽连接符引发异常?
解决GDI+处理含零宽连接符字符串时的ExternalException问题
我完全懂你的痛点——GDI+对某些Unicode组合字符(比如你遇到的\u200d零宽连接符)的支持确实拉胯,尤其是面对用户不可控的输入时,总不能让程序直接崩掉。你说Visual Studio能正常渲染也没错,它用的根本不是GDI+那套老引擎,咱们换个思路就能绕开这个坑:
方案1:改用TextRenderer替代Graphics.MeasureString
TextRenderer基于GDI而非GDI+,对Unicode的支持完善得多,尤其是这类特殊组合字符。不管是测量还是绘制,替换起来都很简单:
测量字符串:
Size size = TextRenderer.MeasureText("?\u200d", yourFont);
绘制字符串:
TextRenderer.DrawText(graphics, "?\u200d", yourFont, yourRectangle, yourForeColor, yourTextFormatFlags);
这个方案是最直接的,代码改动量极小,大部分场景下都能解决问题。
方案2:预处理字符串,安全处理组合字符
如果必须依赖GDI+(比如有特殊的绘制需求),可以先对字符串做预处理,确保GDI+能正确解析。比如用System.Globalization.StringInfo遍历字符串的文本元素,帮GDI+识别组合字符的边界:
var stringInfo = new StringInfo("?\u200d"); StringBuilder sb = new StringBuilder(); foreach (string textElement in stringInfo.GetTextElementEnumerator()) { // StringInfo会自动处理组合字符的拆分,直接拼接即可 sb.Append(textElement); } string safeString = sb.ToString(); // 用处理后的字符串进行测量和绘制 SizeF size = graphics.MeasureString(safeString, yourFont);
这个方案能帮GDI+避开无效字符组合的坑,不过需要多做些测试覆盖极端场景。
方案3:升级到.NET Core/.NET 5+的新文本API
如果你在用较新的.NET版本,微软已经在新框架里改进了文本渲染逻辑,或者可以直接用SkiaSharp这类跨平台图形库——它对Unicode的支持堪称完美,零宽连接符这类字符完全不在话下:
// SkiaSharp测量字符串示例 SKPaint paint = new SKPaint { Typeface = SKTypeface.FromFamilyName(yourFont.Name), TextSize = yourFont.Size }; SKRect bounds = new SKRect(); paint.MeasureText("?\u200d", ref bounds); float width = bounds.Width; float height = bounds.Height;
这个方案适合需要跨平台或者对文本渲染质量要求高的场景。
补充:为啥Visual Studio能渲染?
你猜的完全正确,Visual Studio的UI大多基于WPF或自定义渲染引擎,这些引擎对Unicode组合字符的支持比GDI+好太多。GDI+是比较老旧的技术,在Unicode支持上留下了不少遗留问题,碰到这类特殊字符翻车也正常。
内容的提问来源于stack exchange,提问作者Oliver Bock
相关产品推荐
相关产品推荐

