Why doesn’t my MessageBox wrap at the right location?


A customer reported that the MessageBox function was wrapping text "at the wrong location."

Our program displays a message with the MessageBox function, and we use the '\n' character to force line breaks at positions we choose. But we've found that starting in Windows Vista, the line breaks we placed are not working. The MessageBox function is inserting its own line breaks, which interferes with our custom text layout. It used to be that the width of the message box would expand to fit the longest line in the message.

The MessageBox function is one of those "leave the driving to us" type of functions. You give it a string to display, select which buttons you want, and sit back and relax while the MessageBox function does the work. The trade-off for the simplicity is that you also lose control over the experience. The MessageBox function decides where to place the dialog and how big to make it, which in turn determines where the line breaks go.

The algorithm used by MessageBox to determine the size of the message box has changed many times over the lifetime of Windows. In Windows 3.1, it was the width of the longest line, or 5/8 of the width of the screen, whichever was smaller. Windows 95 chose the smallest of the following which resulted in a dialog box that fit inside the working area:

  • the width of the longest line,
  • 5/8 of the width of the working area,
  • 3/4 of the width of the working area,
  • 7/8 of the width of the working area,

Notice that even in Windows XP, the dialog box was not guaranteed to be the width of the longest line. If the longest line was more than 5/8 of the width of the working area, the MessageBox is probably going to insert its own line breaks beyond ones you inserted explicitly.

Windows Vista changed the algorithm again, in recognition of two things. First, monitors are now much larger than they were in 1995. And second, the consequence of these larger monitors is that the 7/8 rule resulted in message boxes that were unreadable because they were 10 inches wide and half an inch tall. The old algorithm did not age well, but then again, it was written back in the days when the really cool kids had 1024×768 screens. Nowadays, even the kids from the wrong side of the tracks have screens that are regularly 1400 or even 1600 pixels wide.

The new algorithm merely adds another option to the table of choices:

  • the width of the longest line,
  • 278 DLU,
  • 5/8 of the width of the working area,
  • 3/4 of the width of the working area,
  • 7/8 of the width of the working area,

Note that the details of the MessageBox line breaking algorithm are provided for historical purposes only. Do not write code which relies on them, because who knows, they may change again in the next version of Windows.

The algorithm was changed at the request of the visual design team; after all, it's the job of the visual design team to make these sorts of visual design decisions. If you don't want some black-turtleneck-wearing designer in Redmond to decide where your line breaks go, then don't use MessageBox. And you don't have to go and convert every single message box to its own dialog template; just write a function called MessageBoxWithLineBreaksExactlyWhereIPutThem function that takes the same parameters as MessageBox but lays out the text exactly the way you want it. (The DT_CALCRECT flag will be useful here.)

Comments (44)
  1. Wyatt says:

    Wouldn't "5/8 of the width of the working area" always be smaller than "3/4 of the width of the working area"?

  2. SimonRev says:

    Not if the working area is negative :)

    Actually I am equally confused.  The only thing I can think of is a different definition of "smallest," for example the smallest area [width x height] instead of smallest width.

  3. steven says:

    Raymond says "fit inside the working area", so I would surmise that this means that the lesser widths might result in messageboxes whose height might overflow the working area. If that happens, try one step wider… I dread to think what kind of monstrous message people can come up with that would overflow the working area on my 1920×1080 monitors even at 7/8 width. It'll probably happen next Thursday.

  4. Paul M. Parks says:

    And please, please implement the CTRL-C feature correctly if you write your own message box.

  5. Damien says:

    @Wyatt: "which resulted in a dialog box that fit inside the working area:". If you make it 5/8th the width of the working area, and that forces the height larger than the working area, it doesn't fit inside the working area.

  6. Joshua Ganes says:

    @Damien: Thanks for the clarification on Wyatt's question. I was wondering the same thing.

  7. Skyborne says:

    DLU = Dialog Units, which are based on the size of the font, and thus resolution-independent.  Theoretically, anyway; a web search about DLU mostly finds lots of people trying to convert them to "pixels," and that way lies madness or heartbreak.

  8. SimonRev says:

    @Steven, Damien

    But doesn't that logic fly in the face of his statement: "And second, the consequence of these larger monitors is that the 7/8 rule resulted in message boxes that were unreadable because they were 10 inches wide and half an inch tall.", unless he is referring to some sort of bizarre monitor that is only 1" tall and 11+" wide.

    [Fine, you caught me out on the math. 5/8 is smaller than 7/8. I shouldn't have been so specific and just have written "the old rule". -Raymond]
  9. Adam Rosenfield says:

    I've found this new behavior in Vista to be rather annoying when displaying stack trace message boxes.  Our stack trace lines look like "0x12345678 FunctionName+0x124 [C:pathtosourcefile.cpp:1234+0x12]", which almost always produces lines longer than 278 DLU, resulting in really ugly line wrapping.  Yes, we _could* implement MessageBoxWithLineBreaksExactlyWhereIPutThem, but doing so is non-trivial, and it takes comparatively less effort to copy the message box text into a text editor such as Notepad to view the stack trace sensibly.  Developers have the -100 points rule, too.

  10. Chris Vesper says:

    'black-turtleneck-wearing designer in Redmond" – I love it.

  11. 640k says:

    MessageBox always has a default font (size), how many pixels is 278 DLU in Vista/7 then? Usually about 2x if I remember correct.

    @Adam Rosenfield: The problem is sadly common. MessageBox doesn't even display at all if you try to display "too much" text. And .net's default exception dialog is actually worse, cannot read it's text without copying to notepad.

  12. Boris says:

    So, if I understand correctly, a line break is suppressed if keeping it would overflow the height. If so, are only some breaks removed while others are retained or are all line breaks ignored and everything is reformatted? If it's the former, it's confusing to the developers and should be consistent. If it's the latter, "the longest line" loses its meaning, so I suspect that's not it.

    [This is all implementation detail, so you shouldn't be taking a dependency on it anyway. (If you're just curious, then you're thinking about it wrong. Take a closer look at the algorithm. Line breaks are not considered on a case-by-case basis.) -Raymond]
  13. David Ching says:

    @Adam Rosenfield – I agree, there are many behaviors of MessageBox (for example, selecting which buttons we want at the bottom, the MB_SETFOREGROUND flag, etc.) that would require significant effort to emulate.

    @Raymond – If the turtleneck dudes and dudettes are going to cause such an issue by changing the algorithm, then the solution is NOT to say, "Just don't use it."  The solution is to offer a MessageBoxEx which offers more control of the dialog size, the line break points, whether or not a vertical scrollbar is included, etc.

    [It is outside the charter of MessageBox to be a "fully customizable text dialog display engine." Feature creep turns a simple function into a complex one whose original purpose was to be simple. -Raymond]
  14. David Ching says:

    @Raymond – I accept what you say is the original charter of MessageBox. That has nothing to do with the charter of a new function, MessageBoxEx. Which is required due to the actions of the turtlenecks. It is in the interest of the Windows team to offer it so that Windows apps do not display crappy looking message boxes. This elevates the elegance of the entire Windows ecosystem.  The same way that Task Dialogs do.

    [Um, when you called MessageBox, you were already handing control over to the turtlenecks. You shouldn't complain that the turtlenecks decided to do something you said they could do. And remember, minus 100 points. And as you noted, there's already an "updated, more flexible MessageBox" – TaskDialog. -Raymond]
  15. Burak KALAYCI says:

    Why doesn't my MessageBox wrap at the right location?

    Because you are using the wrong OS. Use XP, all will be fine.

    It turns out Vista (again) broke compatibility with totally fine functionality, and Raymond says don't use the function (or 'Windows' for that matter) if you don't like it.

  16. Anonymous Coward says:

    Burak, I still think XP is better than Vista or 7, but you have to admit that in XP message boxes with a lot of text do look terrible on widescreen monitors. How would you have fixed the problem?

    And on a separate issue, I think that in most cases the advice to code your own message box is bad. It will probably be worse than the system supplied one and will probably look out of place on the next version of Windows. Better advice would be: live with it, or do something about your idiotically long lines.

  17. ERock says:

    @David Ching: we know what happens when you trust developers to do the right thing. It makes sense from a UX standpoint that for simple message boxes, you use the programmed behavior that everyone else is going to use. Unless your message box layout is so brilliant that it has to be spaced in just such a perfect way, it's just going to annoy the user who isn't going to read it anyway but will notice it's odd.

    Besides, if you wanna give it a go anyway, you can make your window look like anything you want, just gotta code it. You can ignore those convenience functions all you want if they stop being convenient for you.

  18. JamesNT says:

    I was actually curious myself of how MessageBox was changing over the years as I upgraded from one version of Windows to the next.

    However, I was one of those who didn't care as long as it looked reasonable and remained simple.  I'm in the minority, it seems.

    JamesNT

  19. coldacid says:

    @JamesNT: More likely you (and I) are in the majority, but because we're not annoyed by it, we don't make any noise about it. Squeaky wheel gets the grease and all that.

  20. JustSomeGuy says:

    I'm all for readable function names but even I think that "MessageBoxWithLineBreaksExactlyWhereIPutThem" might be a tad on the verbose side :-)

  21. Gideon7 says:

    TaskDialog has a similar problem.  What's worse is that instead of wrapping a long string such as a file path, it outright truncates it.

    The workaround is to use the undocumented flag TDIF_SIZE_TO_CONTENT.  See msdn.microsoft.com/…/bb787473.aspx

  22. asdbsd says:

    So in the end, does this new MessageBox behavior *remove* any pre-set linebreaks? I would have said "of course no", but Raymond did not renounce the "line breaks we placed are not working" part specifically… although his explanations kinda suggest only additional splitting takes place.

    (If this comment is a duplicate please just kill it)

  23. Zilla says:

    Uhh Gideon,

    It's right there in MSDN on the link you provided. Looks pretty well documented being on MSDN and all. (shrug)

  24. Worf says:

    I thought you did "rn" to force MessageBox to linebreak, not n (which just uglified things, if it did anything – last time I tried it didn't…)

  25. voo says:

    @Gideon7: I've rarely seen someone link to msdn as proof for undocumented behavior and you're even right which makes it much more funny at that.

    @Zilla: To quote msdn: "Note: This flag may not be supported in future versions of Comctl32.dll. Also, this flag is not defined in commctrl.h"

    But then as proud readers of this blog, I think we can all agree that the chances of removal of that flag are slim to none ;)

  26. Joshua says:

    The reason for calling MessageBox is often to display emergency messages (with backtrace!) when the managed windowing system has blown up.

    Do you really think it's a good idea to have every managed application developer write his own native dialog box to solve that problem?

  27. Zilla says:

    @voo

    I disagree, it's clearly documented. Not being in a header doesn't equate to it not being documented. It's in msdn, telling you what it does and why you probably don't want to use it. So it's clearly documented. The terms of the contract are there in black and white.

    That said, this whole discussion begs the question. What the heck are some of these developers trying to display with messagebox? It's designed for messages, not narratives and dialogs. If my text was being truncated, or wrapped oddly. The first thing that would come to my mind is that maybe I am trying to show more data than this paradigm is meant to represent.

    If the shell team can manage most of it's message based user interaction in a way that uses these paradigms, then I would say it works as designed. If it doesn't work for you, maybe you should rethink what it is you're trying to convey to the user. If you can't get the point across in short sentence or two, these functions are not what you should be using. DialogBox would probably be a better fit.

    Maybe that's why it appears not too many devs are upset about this, they apparently "got" the implicit paradigm.

  28. David Ching says:

    @Zilla: When you think about it, the text in all these blog comments is like what is shown in a message box.  If you notice, most of the comments are separated into paragraphs, with a blank line between paragraphs.  That's how I format my message boxes.  And that's why I'm irate if Windows doesn't preserve my paragraphs.  Same as you would probably be irate if your comment got formatted all in one gigantic paragraph.

    The reason most devs don't get visibly upset about this is not that they aren't irate.  It's because it is a breakage of backwards compatibility that gets tossed into the "cosmetic" bin, and those bugs are infinitely deferred.  We're too busy fighting compatibility issues with UAC, x64, and the latest ATL Security Update hotfix to even remember these, so kudos to Raymond for at least bringing the topic up.

    @Raymond:  TaskDialog is not a replacement for better laid out message boxes, it was an example of how MS chooses to invest to imrpove the UI of Windows apps.

  29. voo says:

    @Zilla Yeah ok, I interpreted documented in this situation as "supported", because that's pretty much what it needs to be to make a feature really useful for a long term project. Sure it'll work now, but without any guarantees that it won't stop working with the next SP that's not especially helpful – at least I don't see many situations where it'd be.

    Actually I'm not sure what the hell this note has to do in the official documentation – after all it pretty much encourages Raymond's recurring nightmare scenario (people using unsupported features). Did someone just want to be extra dev friendly and this is an rare exception or is this behavior sanctioned from above; never seen such a note before in the documentation.

  30. Zilla says:

    @voo

    I think whoever documented that particular API was probably of the following mindset.

    If we don't document it, someone will figure it out and cry that once again MS is not fully exposing their API's.

    Or

    They don't document it, people figure it out, use it. MS pulls it next service pack and people cry WTF!

    Or lastly

    Document it, so when and if they do remove that flag MS can simply say that they warned you not to use it anyway.

    Just my two cents, it's a damned if you do, damned if you don't scenario.

    @David

    Messagebox isn't meant to display large amounts of formatted data. So while I get your point, I just don't think messagebox should be used for that. It's a UI nightmare, large amount of really important data in a messagebox. User accidentally presses OK, then what? No way to go back and see your really important formatted message.

    We'll have to agree to disagree on this one.

  31. Silly Billy says:

    Is it possible to modify the window / template used by MessageBox before it goes modal?

    Sometimes I want a message box with a label+combobox in the top left corner. And pink text.

    Maybe with a thread and a hook?

    hehe.

  32. JamesNT says:

    @Chris Charabaruk:  Agreed.  It's amazing how much noise 10% of the population can make.

    JamesNT

  33. ErikF says:

    @Silly Billy: You can do something similar, and it's been supported for almost 25 years now. It's called "DialogBox()" (or DialogBoxIndirect() if you are constructing it dynamically.) It's wonderful! You can even put buttons and text anywhere you like! No needles and thread required. ;-)

    Really, if you are needing to show so much text that you are running up against the formatting restrictions of MessageBox, may I suggest using a dialog box with an edit control instead (or rich text control, if you like)?

  34. Gomer says:

    I searched for MessageBoxWithLineBreaksExactlyWhereIPutThem() in MSDN but cannot find it.  Google gives me only this page or copies of it.  If I try to use it I get compiler error.

    How to use this function?

  35. Neil says:

    I must confess to making my own reimplementation of MessageBox over fifteen years ago. Back then I just hardcoded the DrawText default width to 420 pixels, which was then converted to dialog units, and 17 added, to give the final dialog width, unless the dialog had a long caption, or the buttons were wider than the text, in which case it was widened appropriately.

    My best guess as to why I did this was that I wanted to create the message box with a custom dialog class that drew a 3-D border (in a similar manner to CTL3D.DLL).

  36. Bulletmagnet says:

    "black-turtleneck-wearing designer in Redmond" – I thought they all worked at Cupertino

  37. Boris says:

    It looks like my comment from Friday was eaten, so I'll try again. Long story short, msdn.microsoft.com/…/ms645505%28v=vs.85%29.aspx says "If the string consists of more than one line, you can separate the lines using a carriage return and/or linefeed character between each line." So my question above is, "is this false? Is it only sometimes true? If so, when?"

    [Both statements are true. There is no contradiction here. -Raymond]
  38. Boris says:

    @Raymond,

    I am not sure what you are referring to when you say "both statements", but if you mean that your post does not contradict the MSDN article then I don't get it. In your post you imply that line breaks are (sometimes?) ignored when inserted into the text passed to the MessageBox function. Or do you mean that explicit line breaks are still honored and it is only the implicit line breaks that have changed? If so, I, of course, have no problem with this.

    [I don't believe I wrote that MessageBox ever deleted explicitly-inserted line breaks. "The MessageBox function is inserting its own line breaks." Nobody ever complained "The MessageBox function is deleting line breaks." -Raymond]
  39. Neil (SM) says:

    "The line breaks we placed are not working" seems to imply that the MessageBox function is ignoring line-breaks. Hence the confusion.

    [The next sentence explains what they meant by "not working". You have to read sentences in context. -Raymond]
  40. dude says:

    @Bulletmagnet: "black-turtleneck-wearing designer in Redmond" – I thought they all worked at Cupertino

    Yet another thing m$ has copied.

  41. David Walker says:

    @Zilla:  "Begs the question" doesn't mean what you think it means.  We programmers deal in particulars and nit-picky things; otherwise I wouldn't have pointed that out.

  42. Zilla says:

    @David

    Indeed you're right

  43. Gabe says:

    Some people don't have the option to use anything but a MessageBox. If you're popping up an alert in JavaScript in IE, you're pretty much beholden to the vagaries of the MessageBox.

  44. Alex Cohn says:

    @Adam Rosenfeld: you may simply use http://www.codeproject.com/…/xmessagebox.aspx, or some similar project

Comments are closed.