Почему DrawString демонстрирует неожиданное поведение в C # Winforms?

StackOverflow https://stackoverflow.com/questions/837565

Вопрос

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

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

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

Другие советы

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

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

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

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