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:
# Mihai on 19 Jan 2006 1:31 PM:
# Michael S. Kaplan on 19 Jan 2006 1:59 PM:
# Michael Dunn_ on 20 Jan 2006 5:16 PM:
# Michael S. Kaplan on 20 Jan 2006 5:33 PM:
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