How do I indicate that I want my window to follow right-to-left layout rules?


There are many ways, depending on how wide a scope you want.

If there is one specific window that you want to follow right-to-left layout rules, then you pass the WS_EX_LAYOUT­RTL extended window style when you create the window. This extended style is inherited by child windows, so once you set a top-level window to have right-to-left layout, all child windows will have it, too. To block the WS_EX_LAYOUT­RTL extended style from being inherited by child windows, pass the WS_EX_NO­INHERIT­LAYOUT style when you create the parent window.

Sidebar: If you're calling the Message­Box function, then you don't directly control the styles of the top-level window. But there's a weird back-channel way to specify that you want the message box dialog to have the WS_EX_LAYOUT­RTL extended style: Begin the lpText string with two U+200F characters. Then again, instead of Message­Box you should be using the Task­Dialog­Indirect function which not only lets you customize the text on the buttons, but also lets you pass the TDF_RTL_LAYOUT flag to indicate that you want the dialog to be laid out according to RTL rules. (And as an aid to porting, the Task­Dialog and Task­Dialog­Indirect functions implicitly turn on the TDF_RTL_LAYOUT flag if they find that pszContent is a pointer to a string—not a MAKE­INT­RESOURCE—which begins with two U+200F characters.) End sidebar

If you want right-to-left layout rules to apply to all top-level windows in your process, you have two choices. You can either do it programmatically or declaratively. (Similar to how you can specify DPI-awareness either programmatically or declaratively.)

The programmatic way is to call Set­Process­Default­Layout(LAYOUT_RTL) from your application. The declarative way is to insert two left-to-right marks (U+200E) at the beginning of the File­Description version resource string of the executable.

Note that the caveats which apply to changing the process DPI awareness programmatically also apply to changing the default process layout programmatically: Code which calls Get­Process­Default­Layout will see the default at the time of the call, even if some code later on calls Set­Process­Default­Layout to change it.

Note also that it really is the application's call whether its default layout is left-to-right or right-to-left. A DLL shouldn't decide on its own to change the process default layout, at least not without coöperation from that process. If you are a DLL and you want to create a specific window with right-to-left layout, you should use the WS_EX_LAYOUT­RTL method so that your decision applies only to your DLL's windows. (Otherwise you're using a global setting to manage a local problem.)

Bonus chatter: Why isn't the default layout specified in the manifest like DPI-awareness? Because RTL support was added in Windows 2000, which predated application manifests by several years. If the feature were invented today, the manifest would be a much better place for declaring it.

Update

¹ Commenter SCB pointed out that there is indeed a flag to specify that you want RTL layout on your message box: MB_RTLREADING. If that flag exists, then why also have the U+200F back-channel?

Answer: So that translators can mark a string as requiring RTL treatment without having to go back and make code changes.

Comments (11)
  1. Alexandre Grigoriev says:

    I pity the user who sees an english message box from third-party DLL in a totally RTL application.

  2. SCB says:

    Why not just use MB_RTLREADING with the MessageBox function?

    [Good point. I've updated the article. -Raymond]
  3. Medinoc says:

    What surprises me is that one enables RTL for the whole application by specifying LTR marks.

  4. The New Yorker, Technology Review, and Raymond Chen: the last three bastions of the diæresis.

  5. Alexandre Grigoriev says:

    I hope diæresis doesn't cause diærrhea.

  6. David Walker says:

    Ah, yes.  the New Yorker magazine.  They are fond of using diereses in words like coordinate and cooperate and naive.  I forget how to enter them here; I'll leave them to the reader's imagination!

  7. configurator says:

    @Alexandre: Yeah, poor user. His punctuation will be on the wrong end of the text… What would he do now?

    ?Do you really think it's that bad you need to pity the user

  8. configurator says:

    @Alexandre: Yeah, poor user. His punctuation will be on the wrong end of the text… What would he do now?

    ?Do you really think it's that bad you need to pity the user

  9. Mihai says:

    To complete the picture:

    Dialog resource: you can specify WS_EX_LAYOUTRTL in the .rc

    GDI: SetLayout( hdc, LAYOUT_RTL

    Bitmaps:

    • You can use SetLayout( hdc, LAYOUT_RTL | LAYOUT_BITMAPORIENTATIONPRESERVED )
    • You can use NOMIR_RORBITMAP in bitmap handling APIs (BitBlt, StretchBlt, etc.) if you don't want them affected by the GDI setting

    Image lists: ILC_MIRROR, ILC_PERITEMMIRROR (image lists)

    When mapping coordinates you should always use MapWindowPoints, and never ScreenToClient or ClientToScreen.

  10. prunoki says:

    I think he might use a Hungarian layout, that is simply the letter ö.

  11. Neil says:

    Maybe I just don't get it, but what if I'm writing a DLL that wants to display a message box with LTR layout rules, even if the rest of the application wants RTL?

Comments are closed.