Right-to-Left Languages and Mirroring


Right-to-left (RTL) languages are languages that read from right to left, as opposed to English, which reads from left to right (LTR). The right-to-left languages recognized by the .NET Framework 1.1 and 2.0 are Arabic, Divehi, Hebrew, Persian (called Farsi in the .NET Framework 1.1), Syriac, and Urdu. Figure 7.2 shows a simple Windows Forms application with a left-to-right TextBox and a right-to-left TextBox. Your experience when using these two TextBoxes depends upon whether you are typing in a left-to-right language or a right-to-left language. Let's start with a left-to-right, such as English. When you type into a left-to-right TextBox, the characters are added to the right of the existing characters and the insertion point or I-beam moves toward the right with each new character. When you type into an RTL TextBox, the characters are added to the right of the existing characters, but the insertion point remains on the rightmost point of the TextBox.

Figure 7.2. Left-to-Right and Right-to-Left TextBoxes


The behavior changes if you type characters from a right-to-left language such as Arabic. You can try this by adding an Arabic keyboard. Open the Regional and Language Options Dialog, select the Languages tab, click the Details... button, click the Add... button, select a right-to-left language (e.g., Arabic (Saudi Arabia)) from the Input language combo box, click OK and click OK again. To use the Arabic keyboard, click the language bar on the taskbar and select "AR" from the list. Your keyboard will now type Arabic characters. When you type into a left-to-right TextBox, the characters are added to the left of the existing characters and the insertion point remains on the left with each new character. When you type into a right-to-left TextBox, the characters are added to the left of the existing characters and the insertion point remains on the leftmost point of the TextBox. The granularity of this behavior is at the word level, not at the control level, so if you write words in both English and Arabic within the same TextBox, you will see the behavior switch back and forth, depending on whether the insertion point is on a left-to-right word or a right-to-left word.

The reading direction doesn't affect only the direction of the text; it also affects the flow of the document. A right-to-left book is read from the rightmost page, perceived as the back of the book by left-to-right readers, to the leftmost page. This flow direction must also be reflected in applications. So the form in Figure 7.3 is unacceptable even if all of the TextBoxes support right-to-left input.

Figure 7.3. Unmirrored Windows Form


For this form to flow correctly, it must be "mirrored." Imagine that you hold up a mirror to the side of the form and look into the mirror; the image in the mirror is what the form should look like to flow correctly. Figure 7.4 shows the same form mirrored. (I have deliberately not translated the form, to allow a clearer comparison between the two forms, but it should be noted that it is very confusing to lay out a form in a right-to-left flow while using a left-to-right language.)

Figure 7.4. Mirrored Windows Form


You can see from the mirrored form that mirroring involves more than just relocating the controls. It also involves changing the appearance of the controls and the appearance of forms. Figure 7.5 shows Windows Explorer running on the Arabic version of Windows XP. In the desktop, notice that the Start menu is on the right and that the taskbar extends from right to left. Also notice the direction of all the arrows. Not only have the controls moved, but the images indicating directions have changed.

Figure 7.5. Windows Explorer on Arabic Windows XP


The concepts of right to left and mirroring are separate, but in practice, you will often find them lumped together because it is rare to use one without the other. This is reinforced in ASP.NET 1.1 and 2.0 applications, where there is usually no distinction. Windows Forms 1.1 applications support right-to-left input but no mirroring. Windows Forms 2.0 applications include support for both righ-to-left and mirroring, and, unlike ASP.NET, make a distinction between the two, as you will see shortly.

Detecting a Right-to-Left Culture

In most applications, you will want to write a single code base and use separate satellite assemblies to support additional languages. In this scenario, your application must determine whether the chosen culture is a left-to-right culture or a right-to-left culture. In the .NET Framework 2.0, this is a simple matter of checking the CultureInfo.TextInfo.IsRightToLeft Boolean property:

 if (System.Threading.Thread.     CurrentThread.CurrentUICulture.TextInfo.IsRightToLeft) 


Not only is this the simplest solution, but it is also the safest solution because it respects custom cultures (see Chapter 11, "Custom Cultures"), whereas a hard-coded dependency upon a known right-to-left culture (e.g., if (cultureInfo.Name. StartsWith ("ar"))) does not.

The TextInfo.IsRightToLeft property is new in the .NET Framework 2.0. In the .NET Framework 1.1, there is no way to ask a CultureInfo object if it is a right-to-left culture, so a hard-coded solution is needed:

 public static bool CultureInfoIsRightToLeft() {     return CultureInfoIsRightToLeft(CultureInfo.CurrentUICulture); } public static bool CultureInfoIsRightToLeft(CultureInfo cultureInfo) {     if (cultureInfo == null ||         cultureInfo.Equals(CultureInfo.InvariantCulture))         return false;     string cultureInfoLanguage =         cultureInfo.TwoLetterISOLanguageName;     return         cultureInfoLanguage == "ar"  || // Arabic         cultureInfoLanguage == "div" || // Divehi         cultureInfoLanguage == "fa"  || // Farsi         cultureInfoLanguage == "he"  || // Hebrew         cultureInfoLanguage == "syr" || // Syriac         cultureInfoLanguage == "ur";    // Urdu } 


This CultureInfoIsRightToLeft method uses the CultureInfo's TwoLetterISOLanguageName. Remember that this property can return either two or three letters, contrary to what the property name implies, so this approach works just as well with "div" (Divehi) and "syr" (Syriac).

Right-to-Left Languages and Mirroring in Windows Forms Applications

In this section, we look at right-to-left and mirroring issues that are specific to Windows Forms applications. If you are interested in only ASP.NET applications, you can skip this section.

Right-to-left support is controlled by a public virtual property, RightToLeft, in the .NET Framework 1.1 and 2.0, and additionally RightToLeftLayout in the .NET Framework 2.0. We return to RightToLeftLayout shortly. The RightToLeft property is implemented in the Control class, which is consequently surfaced in all controls, including System.Windows.Forms.Form. The Control.RightToLeft property is a RightToLeft enumeration that has the values No, Yes, and Inherit. The behavior of this property can be confusing if you are not familiar with it. By default, all controls inherit their RightToLeft value from their parent control. The ultimate parent is a Form. A control that has no parent defaults its RightToLeft value to No, so by default, Form.RightToLeft is No. If Form.RightToLeft is changed to Yes, all the controls on the form adopt this new setting.

Controls can break their RightToLeft "inheritance" by having an explicit value of either Yes or No. A control can revert to its parent's value by setting a value of Inherit. The potentially confusing part of this relationship is that no control ever reports its RightToLeft value as Inherit. The property always reports what its current state is (after it has adopted its value from its parent and so on). Thus, you can assign Inherit to a RightToLeft property, but it will never be equal to Inherit. You can see this in Visual Studio by setting RightToLeft to Inherit in the Properties Window and observing that it immediately changes to No or Yes. Consequently, there is no way that you can tell in code whether a control has a value because it was explicitly assigned the value or because it is inheriting its value.

The Control.RightToLeft property is related to the TextAlign property, which is implemented in many controls, including TextBox and Label. The TextAlign property is a TextAlign enumeration that has the values Left and Right. The trick to understanding the behavior of the TextAlign property is that the terms left and right are notional and are not absolute; the enumeration values would be better renamed "Nearside" and "Farside," respectively. So when you set RightToLeft to Yes in a TextBox, its TextAlign property does not change from Left to Right. The text in the TextBox is indeed aligned to the right, but the interpretation of the "Left" value is that the text is aligned to the nearside of the control, where the near-side is determined by the RightToLeft property. The upshot of all of this is that the control behaves correctly without you having to change the TextAlign property whenever the RightToLeft property is changed.

RightToLeftLayout

Mirroring is controlled in the .NET Framework 2.0 by the RightToLeftLayout property. Unlike the RightToLeft property, which is implemented in the Control class and, therefore, is present in all controls, the RightToLeftLayout property is implemented by the following controls only: DateTimePicker, Form, ListView, MonthCalendar, PrintPreviewDialog, ProgressBar, TabControl, ToolStripProgressBar, TRackBar, and TReeView. The level of support for mirroring in Windows Forms applications depends on whether you are using the .NET Framework 1.1 or 2.0 and also on the version of Windows that the client is running on; as always, the latest and greatest offers the best support (see Table 7.1).

Table 7.1. Support for Mirroring in Microsoft Windows

Operating System

Mirroring Support

Windows 98 and Me

Available only in the Arabic and Hebrew versions of Windows

Windows 2000 and above

Available in all language versions of Windows


The form in Figure 7.4 is a .NET Framework 2.0 Windows Forms form that has had its Form.RightToLeft property set to Yes and also its Form.RightToLeft-Layout property set to true. The original unmirrored form is shown in Figure 7.3. The RightToLeftLayout property affects the repositioning of the controls and the layout of the form's title bar. First, notice that the form's caption and System Menu have moved from the left to the right, and also that the Close, Maximize, and Minimize buttons have moved from the right to the left. Second, notice that the layout of the Phone TextBoxes and the hyphen Label between them has been preserved, including their respective alignments to the sides of the TextBoxes above them.

Unlike the RightToLeft property, the RightToLeftLayout property is not inherited by child controls, so setting Form.RightToLeftLayout to true does not affect the RightToLeftLayout property of any other controls.

The .NET Framework 2.0 TableLayoutPanel and FlowLayoutPanel container controls illustrated in Chapter 8, "Best Practices," respect the right-to-left setting and perform the same mirroring of the controls contained within them. This makes them ideal for form layout in a scenario in which the size and position of controls change but their relative positions must remain constant.


The operation of the Control.RightToLeft property in the .NET Framework 1.1 is no different than that of the .NET Framework 2.0. However, the Form.RightToLeftLayout property is not present in the .NET Framework 1.1, and there is no equivalent functionality. Figures 7.6, 7.7, and 7.8, respectively, show a .NET Framework 1.1 form with Form.RightToLeft set to false, the same form with Form.RightToLeft set to true, and the same form mirrored in the .NET Framework 2.0, with Form.RightToLeft set to true and Form.RightToLeftLayout.

Figure 7.6. A .NET Framework 1.1 Form with Form.RightToLeft Set to False


Figure 7.7. A .NET Framework 1.1 Form with Form.RightToLeft Set to True


Figure 7.8. A .NET Framework 2.0 Form with Form.RightToLeft Set to True and Form.RightToLeftLayout Set to True


Two differences exist. First, the .NET Framework 1.1 does not move the System Menu, Close, Maximize, and Minimize buttons. Second, the locations of the controls on the form do not change so that sides are not aligned to the right side of other controls. To provide this same relocation behavior, you would have to write the appropriate mirroring behavior and put it into the form's RightToLeftChanged event.

Setting RightToLeft and RightToLeftLayout Across the Application

To support an RTL culture, you need to set the RightToLeft property to Yes and the RightToLeftLayout property to true on every form in the application. Then all the controls will adopt the RightToLeft property and the form will be mirrored. The question remains, "How do you set the RightToLeft property to Yes and the RightToLeftLayout property to true for every form?" Three possibilities exist.

The most flexible solution is to make this problem part of the localization process. The localizer/translator must set the RightToLeft and RightToLeftLayout properties for every form. The benefit of this approach is flexibility, in that it is possible to have some forms or some controls in which RightToLeft is set to No and RightToLeftLayout is false because the values of Yes and false would be incorrect in the given context.

Another solution is to use the StandardPropertiesResourceManager in Chapter 12, "Custom Resource Managers." This resource manager ensures that certain properties (e.g., Font and RightToLeft) are always given the same value across the application. In this scenario, control is moved from the localizer to the developer. The benefits of this approach are that it is easy to make application-wide changes and that it provides a high degree of continuity. The downsides are that it lacks flexibility and that if you weren't planning to use a custom resource manager, you must take additional steps to employ its use throughout your application (see Chapter 12 for more details).

The third solution is to set the RightToLeft and RightToLeftLayout properties in the form's constructor based upon whether the culture is an RTL culture (see the section entitled "Detecting a Right-to-Left Culture"). The simplest way to ensure that all forms use this approach is to create a "base" form from which all forms inherit and place the necessary code in the base form. The base form's constructor would be something like this:

 public BaseForm() {     InitializeComponent();     CheckRightToLeft(); } 


The CheckRightToLeft method is this:

 protected virtual void CheckRightToLeft() {     if (CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft)     {         RightToLeft = RightToLeft.Yes;         RightToLeftLayout = true;     }     else     {         RightToLeft = RightToLeft.No;         RightToLeftLayout = false;     } } 


It is good practice to create a base form from which all forms inherit at the start of a project so that code snippets, such as this one, can be introduced into the application at a later stage without touching every form in the project.

You might occasionally see references to using the Win32 SetProcessDefaultLayout function to set the right-to-left setting for an entire application. This function achieves its result for Win32 GDI applications only; it has no effect on .NET Framework applications because they are based on GDI+.


MessageBox

If you use the .NET Framework MessageBox class in your application, you will need to take additional steps for the MessageBox to display correctly in a right-to-left application. The MessageBox implementation ultimately comes from the operating system, but the default layout is still left to right, regardless of whether the application is running on an RTL version of Windows. In addition, but not surprisingly, your form's RightToLeft property is ignored. Figure 7.9 shows the result of the following call to MessageBox.Show on Arabic Windows XP:

 MessageBox.Show("No MessageBoxOptions", String.Empty,     MessageBoxButtons.OKCancel); 


Figure 7.9. Right-to-Left MessageBox on Arabic Windows XP


(If you can't read Arabic, the button on the left is the OK button and the button on the right is the Cancel button.) The MessageBox.Show method accepts a MessageBoxOptions parameter in which you can specify that the MessageBox should align the text to the right and should be mirrored:

 MessageBox.Show(     "RightAlign and RtlReading MessageBoxOptions",     String.Empty, MessageBoxButtons.OKCancel,     MessageBoxIcon.None,     MessageBoxDefaultButton.Button1,     MessageBoxOptions.RightAlign | MessageBoxOptions.RtlReading     ); 


You can see the result in Figure 7.10. The Close button has moved from the right to the left, the OK and Cancel buttons have been transposed, and, although it cannot be seen when the text is wider than the two buttons, the text is right-aligned instead of left-aligned.

Figure 7.10. Left-to-Right MessageBox on Arabic Windows XP


This presents a minor challenge if you want to use a single code base for all cultures, regardless of whether they are left to right or right to left. For the code to be generic, you would have to surround each call to MessageBox.Show with an if statement:

 if (CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft)     MessageBox.Show(         "Do you get wafers with it ?",         String.Empty, MessageBoxButtons.OKCancel,         MessageBoxIcon.None,         MessageBoxDefaultButton.Button1,         MessageBoxOptions.RightAlign |         MessageBoxOptions.RtlReading         ); else     MessageBox.Show(         "Do you get wafers with it ?",         String.Empty,         MessageBoxButtons.OKCancel,         MessageBoxIcon.None,         MessageBoxDefaultButton.Button1,         (MessageBoxOptions) 0); 


(The second MessageBox.Show casts 0 to a MessageBoxOptions enumeration to pass no MessageBoxOptions for this parameter.) This solves the problem, but it is simply too cumbersome. A better solution is to move the MessageBoxOptions problem off to a utility method, GlobalizationUtilities.RtlMessageBoxOptions, so that the previous code becomes this:

 MessageBox.Show(     "Do you get wafers with it ?",     String.Empty, MessageBoxButtons.OKCancel,     MessageBoxIcon.None,     MessageBoxDefaultButton.Button1,     GlobalizationUtilities.RtlMessageBoxOptions()     ); 


Here, GlobalizationUtilities.RtlMessageBoxOptions is this:

 public static MessageBoxOptions RtlMessageBoxOptions() {     return RtlMessageBoxOptions(CultureInfo.CurrentUICulture); } public static MessageBoxOptions RtlMessageBoxOptions(     CultureInfo cultureInfo) {     if (cultureInfo.TextInfo.IsRightToLeft)         return             MessageBoxOptions.RightAlign |             MessageBoxOptions.RtlReading;     else         return (MessageBoxOptions) 0; } 


If you want to ensure that you always use MessageBoxOptions, take a look at the FxCop rule that exists for this purpose. See Chapter 13, "Testing Internationalization Using FxCop," for more information.

Right-to-Left Languages and Mirroring in ASP.NET Applications

In an ASP.NET application, the concepts of right-to-left reading order and mirroring are handled as one by the HTML dir attribute. The dir attribute, introduced in HTML 4.0 and supported by Internet Explorer 5.0 and Navigator 6.0, can be applied to the HTML and BODY elements and individual HTML controls. The values are "ltr" (left to right, the default) and "rtl" (right to left). For example:

 <HTML dir="rtl"> <body dir="rtl"> <asp:TextBox  runat="server" dir="rtl"> 


Do not confuse the dir attribute with the HTML DIR element for directory listings.


Where no dir attribute is specified, controls inherit their dir attribute from their parent (i.e., DIV, BODY, or HTML), so you can set the dir attribute for an entire page by setting the attribute in the HTML or BODY elements. You can set the dir attribute in the BODY in Visual Studio by selecting the DOCUMENT object and setting the dir property to "rtl" in the Properties Window. This simple approach is probably a little too simple because it sets the direction to right to left regardless of the page's culture. A better approach is to set the dir attribute conditionally. Three solutions exist for this problem:

  • Set the dir attribute programmatically in the HTML element

  • Set the dir attribute programmatically in the BODY element

  • Set the dir attribute using an explicit expression (i.e., set it in a resource)

Setting the dir Attribute in the HTML or BODY Elements

To set the dir attribute programmatically in the form's HTML element, you must add the runat and id attributes to the HTML element. Change to Source view, find the HTML tag, and change it to this:

 <html xmlns=http://www.w3.org/1999/xhtml runat="server" > 


I have given my HTML element the id of "html". Visual Studio 2005 automatically adds a corresponding protected field called "html" to the form class. If you are using Visual Studio 2003, you must add the following declaration manually:

 protected HtmlGenericControl html; 


You now have programmatic access to the form's HTML element. You can set the dir attribute in the Page_Load event:

 void Page_Load(object sender, EventArgs e) {     if (CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft)         html.Attributes["dir"] = "rtl"; } 


This code checks to see if the culture is an RTL culture and, if it is, sets the HTML element's dir attribute to "rtl". Remember that in Visual Studio 2005, the current culture is automatically set to the browser's first language setting if the page has been localized (and, therefore, the Page directive includes UICulture="auto").

You could use the same technique for setting the body's dir attribute (i.e., include the runat and id attributes in the body's element and set the dir attribute in the Page_Load event). Although this is possible, it doesn't achieve quite the same effect as setting the dir attribute in the HTML element because frames and captions do not inherit their dir attribute from the BODY element.

Setting the dir Attribute Using an Explicit Expression

Of course, setting the dir attribute in either the HTML or BODY elements is a pro-grammatic solution and, therefore, places control over this issue in the hands of the developer. An alternative is to place the dir setting in a resource and hand over control to the localizer. Visual Studio 2005 lends itself to this solution in the form of Explicit Expressions. Explicit Expressions enable you to set a value for a property from a resource (see Chapter 5, "ASP.NET Specifics"). The idea is that you add an entry, such as html_dir, to a global resource and, in the HTML element, add a dir attribute that gets its value from the resource.

Let's do an example. If your Web site doesn't already have an App_GlobalRe-sources folder, create one now (right-click the project in Solution Explorer and select Add Folder, App_GlobalResources Folder). Add a new global resource file (right-click the App_GlobalResources folder, select Add New Item..., select Assembly Resource File, enter Global.resx as the Name, and click the Add button). Add a new entry to Global.resx and give it the name "html_dir" and the value "ltr". Now create a new global resource file and call it "Global.ar.resx". This resource will be used for Arabic cultures. Add an entry and give it the name "html_dir" and the value "rtl". Now open the page's Source and add the dir attribute to the HTML element:

 <html xmlns="http://www.w3.org/1999/xhtml"     dir= "<%$ Resources: Global, html_dir %>" /> 


The dir attribute is set to an Explicit Expression. "$Resources" indicates that it is an explicit expression, "Global" is the name of the resource, and "html_dir" is the name of the entry. When the application runs, the resource manager determines whether the "rtl" value is read from Global.ar.resx or the "ltr" value is read from Global.resx.

Setting Right-to-Left Encoding in Internet Explorer

Yet another way to view pages as Right To Left is to set the page encoding in Internet Explorer. Open any page in Internet Explorer, right-click the page, and select Encoding, Right-To-Left Document (see Figure 7.11). (You must install Supplemental Language Support for this option to be present.) Whereas this option is available only to the end user and, therefore, would be tedious and unfeasible to use as a permanent solution, it enables a developer to assess the impact on a Web site of changing the dir attribute without having to perform the work.

Figure 7.11. Setting Right-to-Left Encoding in Internet Explorer


Setting the dir Attribute Across the Application

Having chosen a solution to set the dir attribute, you must apply this solution to the whole Web site. Visual Studio 2005 makes this easy in the form of Master Pages. A Master Page is a page from which other pages in the Web site adopt their layout and characteristics. Consequently, if you are using Visual Studio 2005, you should place your dir solution in your master page. If you are using Visual Studio 2003, you must apply your solution to every page manually or adopt one of the popular Master Page imitations for Visual Studio 2003.

Mirroring and Absolute Positioning

As mentioned previously, the right-to-left reading order and the mirroring of a page are both handled by the same attribute and are, therefore, inseparable. Furthermore, both are handled by the browser. However, the effectiveness of mirroring in a Web application is determined by the way the controls are laid out on the page. In Visual Studio 2003, this is controlled by the form's pageLayout setting, which can be either FlowLayout or GridLayout (the default). FlowLayout lays out a form according to HTML layout rules. GridLayout uses absolute coordinate positioning. By default in Visual Studio 2005, all controls are laid out using what Visual Studio 2003 calls FlowLayout. However, you can change the layout for newly added controls in Tools, Options..., HTML Designer, CSS Positioning, Positioning Options. In addition, you can position individual controls absolutely by right-clicking the control in the designer and selecting Style..., Position, and then selecting "Absolutely position" in the Position Mode combo box (see Figure 7.12).

Figure 7.12. Using the Style Builder to Absolutely Position Controls


So the following HTML is generated from absolutely positioning a Label, TextBox, and Button:

 <asp:label  style="Z-INDEX: 101; LEFT: 16px; POSITION: absolute; TOP: 16px" runat="server">Label</asp:label> <asp:textbox  style="Z-INDEX: 102; LEFT: 16px; POSITION: absolute; TOP: 40px" runat="server"></asp:textbox> <asp:button  style="Z-INDEX: 103; LEFT: 16px; POSITION: absolute; TOP: 72px" runat="server" Text="Button"> </asp:button> 


You can see in the style attributes the TOP and LEFT values determining the absolute position of the controls. One of the problems with absolutely positioning controls is that mirroring has no effect on the controls because they cannot be relocated. The conclusion is simple: If you want your pages to be automatically mirrored, you should use FlowLayout in Visual Studio 2003 or avoid using the Absolutely Position style in Visual Studio 2005. If you want to convert your Visual Studio 2003 GridLayout forms to FlowLayout forms, remember that changing the DOCUMENT's pageLayout property to FlowLayout affects only controls that are added after the change. To change all the existing controls, you must delete the POSITION, TOP, and LEFT style attributes from each control.

In Visual Studio 2003, you can set the pageLayout default to FlowLayout for a project by selecting the project in Solution Explorer, right-clicking and selecting Properties, selecting Designer Defaults in the tree view on the left side, and, on the right side, changing Page Layout from Grid to Flow. Because this is a project-wide setting, it affects only the open project and you must set it again for each new project.


Right-to-Left Cultures and Images

Images are another consideration for right-to-left cultures. Refer back to Figure 7.5, which shows Windows Explorer running on Arabic Windows, and you will see several images. Some images have been reversed, or "flipped," and others have not. For example, notice that the Windows icon on the Start menu, the Recycle Bin, and the folder images are all the same as for left-to-right Windows, whereas any image that indicates a left-to-right or right-to-left direction, such as the Back and Forward buttons in Windows Explorer, has been reversed. You must inspect each image in your application individually and decide whether the image needs to be flipped or, in a worst-case scenario, re-created. As a general rule of thumb, you can apply the following guidelines:

  • Images that indicate a left-to-right or right-to-left direction should be reversed.

  • Images that indicate an up or down direction should not be reversed.

  • Images that include a logo, textual trademark, or flag should not be reversed.

  • Images such as a check mark (a tick) are unidirectional and should not be reversed.

  • Images that include text should be re-created using the translated text.

  • Images that do not indicate a direction should not be reversed.

If your image is used in a ToolStripItem control (i.e., the parent of several ToolStrip controls), you can easily flip images on a case-by-case basis by setting the ToolStripItem.RightToLeftAutoMirrorImage property to true. This property takes effect only when ToolStripItem.RightToLeft is set to Yes.

Programmatic solutions to these issues also exist in GDI+ and HTML. If you use the GDI+ Graphics.DrawString method to draw strings onto a bitmap, you should pass the StringFormatFlags.DirectionRightToLeft flag as the StringFormat parameter (this takes care of the direction of the text but does nothing for the remainder of the image). In an ASP.NET application, you can include "filter:flipH" in the image control's Style attribute to "flip" the image.




.NET Internationalization(c) The Developer's Guide to Building Global Windows and Web Applications
.NET Internationalization: The Developers Guide to Building Global Windows and Web Applications
ISBN: 0321341384
EAN: 2147483647
Year: 2006
Pages: 213

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net