Just when you think you know a function...

Sorting it all Out
Michael Kaplan's random stuff of dubious value
Be sure to read the disclaimer here first!

Just when you think you know a function...

  • Comments 10

Since the earliest days of Win32, there has been the MessageBox function.

And one would think after having so many years to play with it, I would have figured everything out about it.

But I did learn something new today about it.

There is a particular flag you can pass to it to (MB_RTLREADING) which according to the docs "Displays message and caption text using right-to-left reading order on Hebrew and Arabic systems."

(I already knew that line in the docs was wrong since it works fine on my XP English system, too -- so that's not what I learned today!)

Beyond the slightly out of date documentation issue, this flag has a serious limitation.

And that is that the developer is the one who writes the code but in many cases she is simply loading a string from a resource that a localizer is providing and thus the developer is hardly in the right position to decide whether the flag is needed, now is she? It is the localizer who needs to be able to indicate that the reading order should be right-to-left, and he should be able to do it. That is how he can make sure the dialog is mirrored properly if it needs to be in a localization into language that needs mirroring.

Grrrr.

Well, wait. It turns out he does!

If you add two U+200f (RIGHT-TO-LEFT MARKER) code points in the front of your lpText string, then it will have the same effect as if the developer had added the flag. And there is no double-negative issue that comes up if you put in the characters and add the flag, either. It is simply a cool trick that lots of localizers know about (I checked around between the time that Yaniv told me about it and I wrote this!).

Now given how U+200f works, there is never any specific reason to have two of them (it is not like the embedding flags that have state or anything -- it is just telling a rendering engine what to do with the text that follow it, logically), so as hacks go, I give it a 9 on th safety scale and at least an 8 on the coolness scale.

If you have already heard about it then you can shake your head and smile about all this, and if you have not but can seriously use this information then have fun!

Here is a nice little test application you can use to play with this. In C:

#define _UNICODE
#define UNICODE
#include <windows.h>

void main()
{
    if (IDYES == MessageBox( NULL,
                             L"Would you like to see a mirroring test with the documented flag?",
                             L"Question",
                             MB_YESNO | MB_ICONQUESTION))
    {
        MessageBox( NULL,
                    L"Mirrored by using the documented MB_RTLREADING flag",
                    L"The Test",
                    MB_OK | MB_ICONINFORMATION | MB_RTLREADING);
    }
    else
    {
        MessageBox( NULL,
                    L"\x200f\x200fMirrored by shoving two RLM markers in the front of the string",
                    L"The Test",
                    MB_OK | MB_ICONINFORMATION);
    }
}

And also in C# (using the MessageBox class):

using System;
using System.Windows.Forms;

namespace MsgBoxTest
{
  class MsgBox
  {
    [STAThread]
    static void Main(string[] args)
    {
      if (DialogResult.Yes == MessageBox.Show(
        "Would you like to see a mirroring test with the documented flag?", 
        "Question",
        MessageBoxButtons.YesNo,
        MessageBoxIcon.Question,
        MessageBoxDefaultButton.Button1))
      {
        MessageBox.Show(
          "Mirrored by using the documented MB_RTLREADING flag", 
          "The Test",
          MessageBoxButtons.OK,
          MessageBoxIcon.Information,
          MessageBoxDefaultButton.Button1,
          MessageBoxOptions.RtlReading);
      }
      else
      {
        MessageBox.Show(
          "\x200f\x200fMirrored by shoving two RLM markers in the front of the string", 
          "The Test",
          MessageBoxButtons.OK,
          MessageBoxIcon.Information,
          MessageBoxDefaultButton.Button1);
      }
    }
  }
}

Everyone I talked to swore it was common knowledge, and that they thought it was even documented in MSDN or on the web (but I could not find it, and my search results ran into other problems that I will probably blog about another time).

Here is what the two message boxes in the above applications look like:

    

Enjoy!

 

This post brought to you by U+200f, RIGHT-TO-LEFT MARKER

Comment on the blather
Leave a Comment
  • Please add 2 and 7 and type the answer here:
  • Post
Blog - Comment List
  • Of course if you knew about this convention already then feel free to point out how out of the loop I was on this one. :-)
  • Main question: is it safe to add 2 RLMs in front of every single string, no matter if it ends up in menus, dialogs, status bar, etc.?
    Because otherwise this meand localization has to hunt down only the strings that are used for MessageBox. Not really a solution.
    I still think a wrapper is a safe enough solution.

    I cannot say this is really "common knowledge". I was unable to find it documented anywhere. The only thing related is adding 2 RLM in the FileDescription of the version info, which causes the full application to be mirrored. This is documented in "Developing International Software, 2nd Ed."
  • It is actually entirely safe -- they are basically two invisible letters with directionality (I talk about it in the other post!).
  • That line from the docs is a bit confusing for me - if you're running an Arabic/Hebrew language OS, isn't all the text RTL anyway? It seems like you would only need an RTL or LTR flag if you needed to display text that ran in the opposite direction of the OS's language.

    Something else of note is the light source gets reversed too, so it's coming from the top-right of the screen.
  • Hi Mike!

    Usually, but for mirroring the extra work has to happen so that there is an indication that even though the dev laid out the dialog in on direction that it should be flipped to be in the other direction....
  • Mohit Gogia&amp;nbsp;asked me via the contact link (though the suggestion box would have better!):

    Hello...
  • Last month I talked about GetDateFormat and using the DATE_LTRREADING/DATE_RTLREADING flags with it in...
  • Well, the RIGHT-TO-LEFT MARK (and its cousin the LEFT-TO-RIGHT MARK), that is!
    (apologies to those of...
  • Indeed, this is the question I came to ask the mirror, while the wicked queen was napping (or maybe she...
  • When you were growing up, you might have had adults try to indoctrinate you with pithy biscuits of nothingness

Page 1 of 1 (10 items)