Перенос слов в прямоугольник, позволяющий обрезать слова - PullRequest
3 голосов
/ 13 февраля 2012

Я создаю приложение для планирования, которое выглядит как Google Calendar, iCalendar, календарь Outlook и т. П. ... Как вы могли видеть в таких приложениях, запланированные события представлены в виде прямоугольников, которые могут быть очень маленькими, особенно еслиВы просматриваете целую неделю.

Моя задача состоит в том, чтобы дать пользователю «содержательную сводку» события, прежде чем он щелкнет по нему, используя текст в прямоугольнике.Текст должен быть очень компактным.С этой целью я хочу, чтобы он переносил строки способом, который не очень распространен, но я подозреваю, что .NET способен обрабатывать его изначально.

Если одно слово шире, чем прямоугольник, тольконачало этого слова должно показать.Но перенос по-прежнему должен происходить при встрече с пробелами, если следующее слово будет частично выходить за пределы прямоугольника.Не каждый пробел приведет к переносу на следующую строку, потому что, если два или более слова вписываются в строку, это нормально.

Я подозреваю, что ответ заключается в возможностях StringFormat, StringTrimming и FormatFlags, ноЯ не нашел правильную комбинацию для достижения целей.

Например, если у нас есть ...

Chuck Norris
Dentist Appointment

Из-за ограниченного пространства это может стать ...

Chuc
Norr
Denti
Appo

Я НЕ хочу, чтобы он стал:

Chuc
k
Norr
is
Dent
ist
Appo
intme
nt

Как вы видите в этом примере, если пользователь уже знает, кто такой Чак Норрис, присутствие буквы "k" и букв "«не помогает пользователю узнать имя.Фактически, присутствие этих букв может заставить «назначение стоматолога» быть скрытым из поля зрения, поскольку вертикальное пространство также ограничено.

Я уже знаю, как рисовать текст в прямоугольнике, который оборачивается обычным способом, иЯ также знаю, как получить его, чтобы избежать рисования любого текста, который выходит за пределы прямоугольника.Чего я не знаю, так это как заставить его обернуть его при встрече с пробелом (или возвратом каретки), не допуская при этом переноса в середине слова, если одно слово шире, чем прямоугольник.Любая помощь там?

Ответы [ 2 ]

3 голосов
/ 16 февраля 2012

Попробуйте использовать метод TextRenderer.DrawText с флагом TextFormatFlags.WordBreak:

Пример использования события рисования панели:

Private Sub Panel1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Panel1.Paint
  Dim sb As New StringBuilder
  sb.AppendLine("Chuck Norris")
  sb.AppendLine("Dentist Appointment")

  e.Graphics.Clear(Color.White)
  TextRenderer.DrawText(e.Graphics, sb.ToString, Panel1.Font, _
                        Panel1.ClientRectangle, Color.Black, Color.Empty, _
                        TextFormatFlags.WordBreak)
End Sub

Вы также можете добавить TextFormatFlags.WordEllipsis, чтобы добавить «...» в конец слов, которые обрезаются на краю прямоугольника:

TextRenderer.DrawText(e.Graphics, sb.ToString, Panel1.Font, _
                      Panel1.ClientRectangle, Color.Black, Color.Empty, _
                      TextFormatFlags.WordBreak Or TextFormatFlags.WordEllipsis)
1 голос
/ 16 февраля 2012

Я не вижу другого способа сделать это, кроме как вручную.

Насколько мне известно, нет никаких стандартных элементов управления, которые ведут себя так, как вы хотите, - следующий шаг оттуда - реализовать его самостоятельно или найти кого-то, у кого уже есть.

Тем не менее, вы можете сделать небольшие улучшения по сравнению с методом, который вы описали в комментариях. Надеюсь, вы можете переместить его из «немного клуджого» в «минималистский»

  • Создание пользовательского элемента управления, который наследуется от метки
  • Переопределите событие Paint , чтобы вы могли контролировать то, что рисуется (Вот другой понятный пример и более продвинутый )
  • Вычислять ширину строки только в тех местах, где есть пробел - вам все равно, если вы вытянете лишние символы вне холста, и вы не разбьетесь без пробелов.
  • Кэшировать окончательную информацию о строке и пересчитывать только в случае изменения размера / недействительности или изменения текста (вам необходимо отслеживать соответствующие события)

Используя пользовательский элемент управления, вы не изменяете базовое свойство Text - поэтому, если вы когда-нибудь захотите прочитать его, это будет так же, как вы его вставили. Это дает еще один бонус, который вы не используете. вам не нужно делать одно и то же преобразование везде, где вы хотите, чтобы это появилось - просто используйте ваш контроль.

Если вы наследуете от элемента управления, который делает почти то, что вам нужно (скорее всего, для метки, если у вас нет других требований), это не должно быть слишком много кода / слишком много обработки.

Если вы еще этого не сделали. Вы почти наверняка хотите, чтобы пользовательский объект представлял запись расписания в любом случае - его легче читать, обслуживать и кодировать, обеспечивает стандартный вид в приложении и т. д.

Извиняюсь, если вы уже знаете все это - поскольку у вас мало SO / Вопросов / ответов, сложно измерить ваш уровень опыта.

...