Почему DrawString демонстрирует неожиданное поведение в C # Winforms? - PullRequest
6 голосов
/ 08 мая 2009

Я подклассифицировал элемент управления в 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

Если вы увеличите масштаб, вы увидите, например, что расстояние между первым «как» отличается от расстояния между вторым «как» (1 пиксель против 2 пикселей). Кто-нибудь знает, что может быть причиной этого, или как я могу предотвратить это? При прорисовке с использованием разных шрифтов становится намного больше странностей, но я предполагаю, что все они являются результатом одной и той же проблемы.

Заранее благодарим вас за любые идеи, которые вы можете иметь.

Ответы [ 3 ]

6 голосов
/ 08 мая 2009

Я собираюсь предположить, что это потому, что вы используете Graphics.DrawString() вместо TextRenderer.DrawText(). Первый рисует текст, используя GDI +, который является своего рода дрянным и устаревшим. Последний использует GDI, который является более современным (с точки зрения рендеринга текста). Я полагаю, что это разница, отмеченная в предыдущем ответе (WinForms vs. Windows).

Вы также можете попробовать перегрузку Graphics.DrawString(), которая принимает объект StringFormat и указать StringFormat.GenericTypographic. Тем не менее, это действительно немного взломать вокруг проблемы. Если вы используете .NET 2.0 или более позднюю версию, вы должны использовать класс TextRenderer вместо классного Graphics класса для всех ваших потребностей рендеринга текста. Graphics.MeasureString() и Graphics.DrawString() существуют строго для обратной совместимости с .NET 1.0 и 1.1.

edit: Да, и ваш код пропускает объект GDI при каждом цикле рисования. Объекты Brush являются управляемыми оболочками вокруг неуправляемых ресурсов, поэтому они должны быть явно удалены.

0 голосов
/ 08 мая 2009

Мой опыт рисования текста в подклассах управления с использованием 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);

... и семья.

Наверное, не то, что вы хотели услышать, но это так.

0 голосов
/ 08 мая 2009

Я должен быть честным, но этого никогда не случалось со мной раньше. Однако попробуйте установить для SmoothingMode значение Antialiasing:

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

Еще одна вещь, кроме того, убедитесь, что для вашего использования DoubleBuffer имеет значение true. Также постарайтесь не создавать новый SolidBrush при каждом вызове OnPaint.

...