Самый быстрый API для рендеринга текста в Windows Forms?

Нам необходимо оптимизировать рендеринг текста для приложения C# Windows Forms, отображающего большое количество небольших строк в нерегулярной сетке. В любой момент может быть видно более 5000 ячеек, которые обновляются 4 раза в секунду. Семейство шрифтов и размер одинаковы для всех ячеек, хотя цвет может варьироваться от ячейки к ячейке, как и жирный / курсив / простой.

Я видел противоречивую информацию в Интернете о том, что TextRenderer.DrawText против Graphics.DrawString является самым быстрым / лучшим, что сводится к сравнению GDI против GDI + на уровне Win32.

Я также видел радикально разные результаты в Windows XP и Windows Vista, но моя главная цель - Windows XP. Статьи, обещающие большие успехи под WinFX и DirectX 10 здесь не помогают :-)

Какой здесь лучший подход? Я не боюсь ввести небольшой слой C++ / CLI и оптимизировать обработку контекста устройства, чтобы добиться большей производительности, но мне бы хотелось дать исчерпывающий совет о том, в каком направлении двигаться.

Обновлено: Спасибо за первые ответы. Я буду пробовать комбинацию рендеринга фонового растрового изображения и придерживаться эквивалентных вызовов GDI.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
13
0
8 248
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

GDI в целом быстрее рисует, чем GDI +. Я работал над проектом, который должен был рисовать тысячи строк и текстовых строк, и переход с GDI + на GDI позволил значительно улучшить производительность. Это было с использованием Windows XP, поэтому я не могу комментировать Vista. Я также рекомендовал бы использовать двойную буферизацию для вашего рисунка, чтобы также улучшить производительность. Создайте совместимое растровое изображение вне экрана и повторно используйте его каждый раз, когда вам нужно рисовать.

Отрисовка 5000+ текста происходит медленно даже с GDI, особенно если вам нужна прокрутка. Создайте отдельный поток рендеринга и уведомляйте поток пользовательского интерфейса каждые 200 мс и выполняйте битовую обработку текущих результатов. Это дает плавный пользовательский интерфейс.

Ответ принят как подходящий

Разработчик Microsoft опубликовал в своем блоге статью GDI против GDI + производительность отрисовки текста, которая отвечает на вопрос о необработанной скорости: в его системе GDI DrawText был примерно в 6 раз быстрее, чем GDI + DrawString.

Если вам нужно быть настоящим демоном скорости, TextOut быстрее, чем DrawText, но вам придется самостоятельно позаботиться об отсечении и переносе слов. ExtTextOut поддерживает обрезку.

Рендеринг GDI (TextRenderer) будет более согласован с другими частями Windows, использующими GDI; GDI + пытается быть независимым от устройств, поэтому некоторые интервалы и эмболизация несовместимы. См. Пример несогласованного рендеринга в инструменте настройки контактной зоны SQL Server 2005.

Пример приложения в ссылке в блоге - это то, что я использовал, когда увидел большую разницу между Vista и XP - на моем ПК с Vista GDI и GDI + были равны, в то время как на XP я вижу разницу в 6 раз, о которой упоминает автор ... Это вероятно, проблема с драйвером Vista, но подчеркивает некоторые трудности здесь - спасибо!

Dave Moore 16.09.2008 16:18

Историческая справка: ExtTextOut раньше был самым быстрым способом нарисовать сплошной прямоугольник на некоторых картах / драйверах :)

Roger Lipscombe 23.01.2009 19:37

К сожалению, упомянутой статьи больше нет, вот резервная копия: blogs.msdn.com/cjacks/archive/2006/05/19/602021.aspx

NiKiZe 08.01.2020 18:01

Создание класса взаимодействия C++ / CLI для рисования в машинном коде приведет к безумно быстрому рисованию. Мы были свидетелями этого и измерили это.

Если вы этого не сделаете, мы обнаружили, что graphics.DrawString немного быстрее, чем TextRenderer.DrawText.

В моей 64-битной системе Windows 7 TextOut даже немного медленнее, чем DrawString! TextRenderer.DrawText намного медленнее, чем DrawString.

Я тоже это обнаружил ... но я не могу найти причину, почему !?

Matthew Layton 26.01.2015 19:44

Согласно недавнему опыту, самый быстрый вывод текста достигается через ExtTextOut с флагом ETO_GLYPH_INDEX. За это приходится платить: вы больше не печатаете символы, а напрямую печатаете глифы шрифта. Это означает, что вам необходимо преобразовать ваши обычные строки символов в строки индексов глифов перед вызовом ExtTextOut, либо вызывая GetCharacterPlacement каждый раз, либо вызывая эту функцию только один раз для создания вашей собственной таблицы перевода, которая будет действительна до тех пор, пока новый шрифт не будет выбран в ОКРУГ КОЛУМБИЯ. Помните, что индексы глифов являются 16-битными, поэтому вы можете хранить их в строке Unicode и вызывать версию ExtTextOutW независимо от размера исходного символа строки.

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