Just when you think you know a function...

by Michael S. Kaplan, published on 2006/01/19 03:01 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2006/01/19/514656.aspx


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


# Michael S. Kaplan on 19 Jan 2006 7:47 AM:

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. :-)

# Mihai on 19 Jan 2006 1:31 PM:

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."

# Michael S. Kaplan on 19 Jan 2006 1:59 PM:

It is actually entirely safe -- they are basically two invisible letters with directionality (I talk about it in the other post!).

# Michael Dunn_ on 20 Jan 2006 5:16 PM:

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.

# Michael S. Kaplan on 20 Jan 2006 5:33 PM:

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....

referenced by

2009/04/09 Two wrongs don't make a right, but two lefts can take a good whack at it

2006/05/28 Mirror, mirror... before whom I fuss, does mirroring work well in GDI+?

2006/02/08 They make 'em smarter than GetDateFormat

2006/02/01 On [not] localizing a MessageBox from code

2006/01/21 Return of the Mark

2006/01/19 What are directional marks -- chumps who point?

go to newer or older post, or back to index or month or day