【问题标题】:Drawing text correctly using DrawString()使用 DrawString() 正确绘制文本
【发布时间】:2011-12-18 23:02:32
【问题描述】:

我遇到了 Graphics.DrawString() 方法的问题。我的 UserControl 使用等宽字体在面板上绘图,显然,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);

例如,当绘制“eeeeeeee”时,在 Consolas 9 中,两个 e 将不时靠近另一个 1 像素。有没有办法正确显示文本,等宽?

(我的实际问题:我正在从头开始制作自己的文本框控件,作为练习和娱乐。实际上进行得很好,但是显示文本的面板应该能够根据鼠标单击位置定位插入符号.找到正确的行很容易,因为字体的高度属性。但是,在该行中找到当前索引不是。对于非等宽字体,我无法想象确定插入符号索引的方法,但对于等宽字体它应该是可行的,因为符号的宽度是固定的。所以,也许有更好的方法来确定这一点?)

亲切的问候, 贾科

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    等宽绘制的。只是每个字符的宽度不是整数个像素——每个字符大概是 9.9 像素宽。 (为了使字符清晰易读,它在绘制字符时会将每个字符捕捉到最近的像素,这就是为什么有时您会看到两个更靠近的原因。)

    一种选择是使用AntiAlias 标志,它会停止尝试将每个字符捕捉到最近的像素——它只会对边缘进行灰度模糊处理,因此整体间距看起来相对一致。但是,抗锯齿在小字体时看起来并不好。

    或者您可以使用TextRenderer 代替Graphics.DrawString。 TextRenderer 使用旧的 GDI 渲染(而不是像 Graphics 类那样使用 GDI+),所以它根本不进行亚像素渲染——每个字符都是 9 像素宽,或者每个字符都是 10 像素宽。有时,较旧的技术更好。

    【讨论】:

    • AntiAlias 标志让我的字体看起来很糟糕,即使是 12 号
    • 谢谢!绘图现在使用 TextRenderer 可以完美地工作。使用 TextRenderer.MeasureString() 进行测量会带来一些问题。即使在将 TextFormatFlags.NoPadding 设置为 TextFormatFlags 之后,像“abcd”这样的字符串的测量值也不正确(给出的宽度为 25,应该是 28,Consolas 9),“a”奇怪地给出了 10 而不是 7。
    • 我相信您也可以将graphics.TextRenderingHint 设置为不同的值,使其以与TextRender 相同的方式绘制文本。我不记得设置它的具体值,但只有 5 个左右的选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    相关资源
    最近更新 更多