Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making DrawText break a string

So i can make drawtext break a string if the string has spaces, or if i put in \r\n at the end of the string. However, a long string that has no spaces or line breaks in it continues past the drawing rectangle and gets clipped. I would like to prevent this, if possible.

Nothing in the format flags for drawtext stood out to me that would make this happen. Any ideas?

like image 614
Gogeta70 Avatar asked May 01 '11 20:05

Gogeta70


2 Answers

Actually, this is what you want in most cases, from MSDN:

DT_EDITCONTROL

Duplicates the text-displaying characteristics of a multiline edit control. Specifically, the average character width is calculated in the same manner as for an edit control, and the function does not display a partially visible last line.

What it fails to mention is that it also breaks words in the middle if needed, like an edit control does. It does have the other effect of not showing partially visible bottom lines, but in most usages I do not think that will matter because you are probably using DT_CALCRECT ahead of time to make sure you have enough space (and if not, not drawing a partially visible line is probably best anyway). If it really mattered, you could always do something with clipping, such as give DrawText a taller rectangle, but have a smaller clip rectangle set on the device context already.

like image 58
eselk Avatar answered Nov 13 '22 20:11

eselk


What you would normally do is use the DT_WORDBREAK flag. From the DrawText documentation on MSDN, this:

Breaks words. Lines are automatically broken between words if a word would extend past the edge of the rectangle specified by the lpRect parameter. A carriage return-line feed sequence also breaks the line.

If this is not specified, output is on one line.

However, you have a single unbreakable line - that is, there are no words. You will need to look after the breaks yourself. You can solve this two ways:

  • Use DrawText with DT_CALCRECT to calculate the size of the rectangle - loop, shortening your string, until you've found the string for the first line, then repeat for the remaining string. That is, find the subset from index 0-n which fits horizontally in the width of your drawing area; find the string from n+1-m which fits horizontally again; repeat until you hit the end of your string. Concatenate these substrings with \r\n between each to force a manual break, then draw with DrawText and it will wrap correctly.

  • Use DrawTextEx and pass in a pointer to a DRAWTEXTPARAMS structure. It has a uiLengthDrawn member which is "the number of characters processed by DrawTextEx, including white-space characters. The number can be the length of the string or the index of the first line that falls below the drawing area." You should not pass in DT_NOCLIP. This probably (without testing it) will work to give you much the same information as the first method without the looping: the key bit that makes me uncertain is the phrase "below" the drawing area, and if your line is unbreakable it may think it processed the entire text.

The first method will always work and is a simple version of what I use for my own rich text processing.

like image 5
David Avatar answered Nov 13 '22 20:11

David