6

我在 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 个像素)。有谁知道可能导致这种情况的原因,或者我如何防止它发生?当我用不同的字体绘制时,间距有更多类似的怪异,但我认为它们都是同一个问题的结果。

提前感谢您的任何想法。

4

3 回答 3

6

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

您也可以尝试Graphics.DrawString()使用StringFormat对象的重载并指定StringFormat.GenericTypographic. 但是,这确实是解决问题的一个技巧。如果您使用的是 .NET 2.0 或更高版本,您应该使用TextRenderer该类而不是糟糕的Graphics类来满足您的所有文本呈现需求。 Graphics.MeasureString()Graphics.DrawString()严格存在与 .NET 1.0 和 1.1 的向后兼容性。

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

于 2009-05-08T00:26:57.070 回答
0

我必须说实话,但这从未发生在我身上。但是,尝试将 SmoothingMode 设置为 Antialiasing:

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

除了另一件事,请确保您使用的 DoubleBuffer 设置为 true。另外,尽量不要在每个 OnPaint 调用中创建一个新的 SolidBrush ..

于 2009-05-07T23:55:11.970 回答
0

我使用 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);

...和家人。

可能不是你想听到的,但它确实存在。

于 2009-05-08T00:22:39.530 回答