Заставить DrawText разорвать строку

Таким образом, я могу заставить drawtext разбить строку, если в строке есть пробелы или если я вставлю \r\n в конец строки. Однако длинная строка, в которой нет пробелов или разрывов строк, продолжается за прямоугольником рисования и обрезается. Я хотел бы предотвратить это, если это возможно.

Ничто в флагах формата для drawtext не выделялось для меня, что могло бы заставить это произойти. Любые идеи?


person Gogeta70    schedule 01.05.2011    source источник
comment
Все просто: не ленись. Публикация фрагмента не должна была приносить никаких усилий.   -  person Hans Passant    schedule 02.05.2011
comment
Может вы не поняли вопроса? Я не говорю здесь о существующем фрагменте кода. Я спрашиваю о том, как заставить функцию drawtext разбить строку текста, когда она собирается выйти за пределы прямоугольника рисования, когда в тексте нет пробелов.   -  person Gogeta70    schedule 02.05.2011


Ответы (2)


Что вы обычно делаете, так это используете флаг DT_WORDBREAK. Из документации DrawText в MSDN, это:

Разбивает слова. Линии между словами автоматически разрываются, если слово выходит за край прямоугольника, заданного параметром lpRect. Последовательность перевода строки с возвратом каретки также разрывает строку.

Если это не указано, вывод осуществляется в одну строку.

Однако у вас есть единственная неразрывная строка, то есть слов нет. Вам нужно будет позаботиться о перерывах самостоятельно. Это можно решить двумя способами:

  • Используйте DrawText с DT_CALCRECT, чтобы вычислить размер прямоугольника - цикл, сокращая вашу строку, пока вы не найдете строку для первой строки, затем повторите для оставшейся строки. То есть найдите подмножество из индекса 0-n, которое соответствует ширине области рисования по горизонтали; найти строку из n+1-m, которая снова подходит по горизонтали; повторяйте, пока не дойдете до конца строки. Объедините эти подстроки с помощью \r\n между каждой, чтобы принудительно разорвать вручную, затем нарисуйте с помощью DrawText, и он будет правильно переноситься.

  • Используйте DrawTextEx и передайте указатель в структуру DRAWTEXTPARAMS. Он имеет член uiLengthDrawn, который представляет собой «количество символов, обработанных DrawTextEx, включая символы пробела. Число может быть длиной строки или индексом первой строки, которая находится ниже области рисования». Вы не должны не проходить DT_NOCLIP. Это, вероятно, (без тестирования) будет работать, чтобы дать вам ту же информацию, что и первый метод без цикла: ключевой бит, который вызывает у меня неуверенность, - это фраза «ниже» области рисования, и если ваша линия неразрывна, она может подумать он обработал весь текст.

Первый метод всегда будет работать и представляет собой простую версию того, что я использую для обработки форматированного текста.

person David    schedule 03.05.2011
comment
Спасибо, я понял это. ^_^ - person Gogeta70; 04.05.2011
comment
У меня есть массив значений COLORREF для каждого символа в строке. Я перебираю строку и проверяю цвет для каждого символа, пока не найду символ, цвет которого не совпадает с цветом последнего, или пока ширина строки (GetTextExtentPoint32) не превысит ширину области, которую я хочу нарисовать, и затем используйте drawtext для рисования строки. Это работает как шарм ^_^ - person Gogeta70; 06.05.2011
comment
Похоже, вторая процедура не работает. Я не использовал DT_NOCLIP. Я передал следующий формат: DT_NOPREFIX | DT_SINGLELINE. Тем не менее uiLengthDrawn все время получает длину всей строки, что совсем не полезно. - person Atiq Rahman; 03.09.2013
comment
Я думаю, что uiLengthDrawn просто уведомляет вас, когда вместо полного текста есть многоточие. - person jnm2; 02.05.2015

На самом деле это то, что вам нужно в большинстве случаев, из MSDN:

DT_EDITCONTROL

Дублирует характеристики отображения текста многострочного элемента управления редактированием. В частности, средняя ширина символа рассчитывается так же, как и для элемента управления редактированием, и функция не отображает частично видимую последнюю строку.

Что он не упоминает, так это то, что он также разбивает слова посередине, если это необходимо, как это делает элемент управления редактированием. У него есть еще один эффект: не показывать частично видимые нижние строки, но в большинстве случаев я не думаю, что это будет иметь значение, потому что вы, вероятно, используете DT_CALCRECT заранее, чтобы убедиться, что у вас достаточно места (а если нет, то не рисовать частично видимая линия, вероятно, лучше в любом случае). Если бы это действительно имело значение, вы всегда могли бы что-то сделать с отсечением, например, сделать DrawText более высоким прямоугольником, но уже установить меньший прямоугольник отсечения в контексте устройства.

person eselk    schedule 03.05.2014
comment
Я могу подтвердить, что DT_EDITCONTROL вместе с DT_WORDBREAK будут переноситься независимо от пробелов, поэтому ИМО это (наиболее) правильный ответ. - person SpeedFreak; 17.09.2014