Optimizing the Text Box Shape
If you want to reformat a text box, for which we already have an initial width and height, so that it is at most four times as wide as it is high, you only need to combine the equation width×height= area where the area is kept constant, with the upper bound for the width: width£4×height. Simple algebra then gives you the criterion: width£--4×area.
Calculating the Text Box with DrawText()
I found the description of the DT_CALCRECT flag in the documentation for DrawText() confusing and so I did a few experiments to verify the behavior. Fortunately, the DrawText() function is quite robust and more versatile than the documentation suggests.
If the DT_CALCRECT is present in the flags field of the DrawText() function, the function changes the right and the bottom fields of the formatting rectangle, but it does not touch the left and top fields. The value of the right field becomes the left field plus the width of the calculated bounding box of the text after formatting; the bottom field becomes the top field plus the height of the bounding box. Hence, with DT_CALCRECT set, the rectangle parameter is half input and half output.
When you include DT_SINGLELINE in the flags field, the DrawText() function replaces all carriage return (CR) and line feed (LF) characters to a space. There is no special handling of pairs of CR and LF characters; each such character is replaced by a space character.
When neither the flags DT_SINGLELINE and DT_WORDBREAK are set, DrawText() adheres to line-breaking characters in the input string, but it does not otherwise add line breaks. Any occurrence of the CR or LF characters is a line break; a combination like CR-LF or LF-CR counts as a single line break, but CR-CR or LF-LF is a double line break. A line break does not add to the width of the bounding text box, but it does add to its height.
The DT_WORDBREAK flag makes DrawText() use the value of the right field of the formatting rectangle parameter as the right margin and it tries to format the text inside this margin. DrawText() only breaks lines between the words, there is no hyphenation algorithm hidden in the function. If the input string contains a word that is wider than the formatting rectangle, DrawText() extends the formatting rectangle to the width of that word. In a typical situation, after word breaking, the text fits a narrower rectangle than the input formatting rectangle. When DT_WORDBREAK is combined with DT_CALCRECT, DrawText() stores the updated right margin back in the formatting rectangle. So when you use DT_CALCRECT together with DT_WORDBREAK, the resulting formatting rectangle may both be wider (in the presence of a long, nonbreakable word) or narrower than the input rectangle.
I experienced DrawText() entering an infinite loop when the left field of the formatting rectangle was set to a value greater than the right field on input, and the DT_WORDBREAK flag was set. In this case, the input width of the formatting rectangle is negative, so this is arguably an input error and the behavior of DrawText() should be expected to be undefined. DrawText() does not have any difficulty when the left and right fields are set to the same value (input width is zero). I verified this DrawText() behavior on Windows 98/2000, by the way.
T.R.