使用DrawString()正确绘制文本

3

我在使用Graphics.DrawString()方法时遇到了问题。我的用户控件使用等宽字体在面板上绘制,但显然,DrawString()会以一种使文本不再完全等宽的方式进行格式化。我一直试图使用StringFormat来解决这个问题,但没有成功:

StringFormat sf = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.FitBlackBox | StringFormatFlags.LineLimit | StringFormatFlags.MeasureTrailingSpaces);

绘制文本的代码:
for (int i = 0; i < document.Text.Count; i++)
                g.DrawString(document.Text[i], Font, Brushes.Black, new PointF(offset - 2, offset + Font.Height * i), sf);

例如,在Consolas 9中绘制“eeeeeeee”时,偶尔会有两个'e'彼此靠近1像素。有没有一种方法可以正确显示文本,使其等宽?
(我的实际问题是:我正在从头开始制作自己的文本框控件,作为练习和娱乐。实际上进展顺利,但显示文本的面板应该能够根据鼠标单击位置定位插入符号。由于字体的高度属性,找到正确的行很容易。然而,找到该行中的当前索引不是那么容易。对于非等宽字体,我无法想象出确定插入符号索引的方法,但对于等宽字体,应该是可行的,因为一个符号的宽度是固定的。所以,也许有更好的方法来确定这个吗?)
此致 敬礼, Jacco
1个回答

4
它正在绘制等宽字体,只是每个字符的宽度不是像素的整数倍 - 每个字符可能大约有9.9个像素宽。 (为了保持字符清晰可读,绘制时会将每个字符捕捉到最近的像素,这就是为什么有时会看到两个字符更接近在一起的原因。)
一个选项是使用AntiAlias标志,它将停止尝试将每个字符捕捉到最近的像素 - 它只会灰度模糊边缘,使间距看起来相对一致。然而,抗锯齿在小字号下不好看。
或者,您可以使用TextRenderer而不是Graphics.DrawString。 TextRenderer使用旧的GDI呈现(而不是像Graphics类一样使用GDI +),因此根本不进行子像素渲染 - 每个字符要么是9个像素宽,要么是10个像素宽。有时,旧技术更好。

AntiAlias标志对我来说使字体看起来非常糟糕,即使是12号字体。 - Seth Carnegie
谢谢!现在使用TextRenderer绘制可以完美运行了。不过使用TextRenderer.MeasureString()进行测量仍然存在问题。即使将TextFormatFlags设置为NoPadding,如“abcd”之类的字符串的测量结果是不正确的(宽度为25,实际应该是28,Consolas 9),而单个字符“a”的宽度出奇地变成了10而不是7。 - Jacco Krijnen
1
我相信您也可以将 graphics.TextRenderingHint 设置为不同的值,以使其以与 TextRender 相同的方式绘制文本。我不记得要设置什么特定的值,但只有大约5个选择。 - Bradley Uffner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接