У меня есть подкласс элемента управления в 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);
}
Результат для некоторого случайного текста примера выглядит следующим образом: /img219/1778/courier.png
Если вы увеличите масштаб, вы увидите, например, что расстояние между первым "as" отличается от расстояния между вторым "as" (1 пиксель против 2 пикселей). Кто-нибудь знает, что может быть причиной этого, или как я могу предотвратить это? В интервалах гораздо больше похожих странностей, поскольку я рисую разными шрифтами, но я предполагаю, что все они являются результатом одной и той же проблемы.
Заранее спасибо за любые идеи, которые могут у вас возникнуть.
Ответ 1 · рейтинг 6 · Mike Post
Я предполагаю, что это потому, что вы используете 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.
edit: О да, и ваш код пропускает объект GDI при каждом цикле рисования. Объекты Brush - это управляемые оболочки для неуправляемых ресурсов, поэтому они должны быть удалены явно.
Ответ 2 · AlaaShaker
Должен быть честным, но раньше со мной такого никогда не случалось. Однако попробуйте установить для SmoothingMode значение Antialiasing:
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
Кроме того, убедитесь, что для свойства DoubleBuffer установлено значение true. Кроме того, старайтесь не создавать новую SolidBrush при каждом вызове OnPaint.
Ответ 3 · RichieHindle
Мой опыт рисования текста в подклассах элементов управления с помощью 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);
...и семья.
Возможно, это не то, что вы хотели услышать, но это так.