我已经在C#WinForms中创建了一个控件,并且在我的OnPaint()处理程序中自定义绘图文本。 使用我的表单中的以下代码将字体设置为Courier New:

FontFamily family = new FontFamily("Courier New");
this.myControl.Font = new Font(family, 10);

在控件本身中,字符串存储在realText中,我使用以下代码将其绘制到屏幕上:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    e.Graphics.DrawString(realText, Font, new SolidBrush(ForeColor), ClientRectangle);
}

一些随机示例文本的结果如下所示: http://img219.imageshack.us/img219/1778/courier.png

如果你放大,你可以看到,例如,第一个'as'之间的空格不同于第二个'as'之间的空格(1个像素对2个像素)。有没有人知道可能导致这种情况的原因,或者我如何防止它发生?当我用不同的字体绘制时,间距有很多类似的怪异,但我认为它们都是同一问题的结果。

提前感谢您提出的任何想法。

有帮助吗?

解决方案

我猜这是因为你正在使用 Graphics.DrawString() 而不是 TextRenderer.DrawText() 。前者使用GDI +绘制文本,这有点蹩脚和过时。后者使用更现代的GDI(在文本渲染方面)。我相信这是前一个答案所指出的差异(WinForms vs. Windows)。

您也可以尝试使用StringFormat重载.aspx“rel =”nofollow noreferrer“> StringFormat.GenericTypographic 对象并指定TextRenderer。然而,这实际上是一个关于这个问题的黑客攻击。如果您使用的是.NET 2.0或更高版本,那么您应该使用Graphics类而不是蹩脚的Graphics.MeasureString()类来满足所有文本呈现需求。 <=>和<=>严格存在,以便与.NET 1.0和1.1向后兼容。

编辑:哦是的,你的代码在每个绘制周期都会泄漏一个GDI对象。刷对象是非托管资源周围的托管包装器,因此必须明确处理它们。

其他提示

我必须诚实,但这在我之前从未发生过。但是,请尝试将SmoothingMode设置为抗锯齿:

e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

除此之外,请确保您的使用将DoubleBuffer设置为true。此外,尽量不要在每次OnPaint调用中创建新的SolidBrush ..

我使用WinForms将文本绘制到子类控件中的经验是它使用的文本渲染引擎(GDI +?)不如Windows自己的字体引擎那么好,并且即使它运行良好也会产生不同的结果。

我是Visual Studio插件的作者( http://entrian.com/source-search )需要在Visual Studio中绘制控件,并且为了使字体看起来与Visual Studio中的标准控件(列表视图,树视图等)相同,我必须绕过WinForms并使用Win32绘制文本API:

[DllImport("gdi32.dll")]
public static extern bool ExtTextOut(IntPtr hdc, int X, int Y,
   uint fuOptions, [In] ref RECT lprc, string lpString, uint cbCount,
   [In] int[] lpDx);

......和家人。

可能不是你想听到的,但确实如此。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top