June 11th, 2010

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.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments

Discussion is closed.