Arabic Windows Forms Applications

This is another article that I wrote earlier about Arabic WinForm applications. I’m republishing it for your reference.

I hope you enjoy it too.

You are sometimes faced with some challenges to develop Arabic applications. Most of these issues are due to the fact that Arabic is a right-to-left (rtl) language, where the letters are written from right-to-left, unlike most scripts, where letter are written from left-to-right.

Windows Forms Controls

Windows Forms controls are the basic elements of a Windows Applications. In more recent controls, such as the TableLayoutPanel , FlowLayoutPanel , SplitContainer , StatusStrip , ToolStrip and MaskedTextBox etc… there is support for rtl. Simply set RightToLeft =Yes and it would set the reading order, alignment and the layout of these controls. While in older common controls, such as treeview , Listview , MonthCalendar etc... You have a new property to add the rtl layout. Simply set both RightToLeftLayout =true and RightToLeft =yes and you get full rtl layout, there may be some limitations but the development experience is easier.

RightToLeft and RightToLeftLayout are highlighted in the properties Window

Let's examine the main property rtl support, RightToLeft . The RightToLeft property specifies three main things:

•  First, the reading order is rtl. This is important to determine how neutral and numbers would behave. For example, if the textbox contains some text ending with a colon (":") it would be on the left of the text in case of RightToLeft=Yes but would be on the right otherwise. The same would happen with other neutral characters parentheses, full stop or brackets.

•  Second, the text alignment is on the opposite side. This means if text is "Left" aligned then it would be "Right" aligned for Arabic. Therefore, the TextAlign property shows the opposite value in case of RightToLeft . If you enforce "right" alignment it would be displayed to the "left" and vice versa. The reason for this behavior is that the TextAlign property is based on the "near" and "far" coordinates rather than absolute "left" or "right".

•  Third, the layout of the control might also be affected. This means the UI elements are displayed from the right edge to the left edge instead of placing controls from the left to right.

New controls in Visual Studio 2005 respect the above aspects of the RightToLeft property. However, in some older controls we added a new property to enforce the rtl layout, through RightToLeftLayout property. For more information about the RightToLeftLayout , check this article What is RightToLeftLayout?

The following topics explain how Windows Forms applications support rtl and specifically Arabic in more details.

Container Controls

Container controls are controls that visually contain other controls. For example Panel , GroupBox When you set RightToLeft=Yes to a Panel , GroupBox , TabPages , you set the reading order to rtl but the layout of the controls doesn't change. This is similar to previous versions of Visual Studio .NET.

The following controls don't have rtl layout, when RightToLeft=yes:

•  Panel

•  GroupBox

•  TabPages

•  SplitContainerPanels

You need to rearrange the items in these controls to flow from RightToLeft manually because these controls don't have rtl layout.

This is an example of rearranging the layout of the controls programmatically at runtime, without changing the Form at design-time:

int NumberOfControls = ParentPanel.Controls.Count;
for ( int i=0; i<NumberOfControls;i++)
{
      ParentPanel.Controls[i].Left = ParentPanel.Width -
      (ParentPanel.Controls[i].Left + ParentPanel.Controls[i].Width);
}

This code iterates into all the controls in the ParentPanel and changes their location to be rtl oriented.

For more complex layout scenarios, Windows Forms 2.0, provides SplitContainer , TableLayoutPanel and FlowLayoutPanel . These controls are similar to panel controls to host other controls. The TableLayoutPanel and FlowLayoutPanel controls supply advanced layout engine to handle more sophisticated layout needs.

TableLayoutPanel is similar to the table in html. It allows you to define rows and columns that you can set the size automatically in three ways: AutoSize , Percent and Absolute . You have to be careful when dealing with an empty cell while the size is set to AutoSize .

The TableLayoutPanel supports rtl. Simply, set RightToLeft=Yes and the columns would rearrange from right-to-left. This means, the first column would start from the right and the next column is on its left.

FlowLayoutPanel is more suitable when you want a Form and its controls to resize according to the display area similar to HTML Web pages. You can specify the direction in which the controls should be moved during form resize by setting its FlowDirection property to one of four values: LeftToRight , TopDown , RightToLeft , or BottomUp . Don't be confused of the RightToLeft direction this is not the same as setting RightToLeft =Yes. Setting RightToLeft =Yes also affects the child controls and set it's property as well as affects the reading order of the text in the controls.

Like the TableLayoutPanel , the FlowLayoutPanel also supports rtl. Simply set RightToLeft =Yes and the items would flow from right-to-left even though the FlowDirection is still set to LeftToRight. Actually the FlowDirection is reversed when RightToLeft =Yes, similar to the TextAlign property we discussed earlier.

The SplitContainer provides two panels separated by a movable bar. It is designed to replace the Splitter control and give a richer design-time and run-time experience. In the case of vertical panels, when you set the SplitContainer.RightToLeft=Yes. The Panels are reversed. The First panel is place on the right while the second panel is placed on the left. However, the contents of each panel don't flow from right-to-left. To achieve this you can dock a TableLayoutPanel or a FlowLayoutPanel into these SplitContainer's panels.

This shows the SplitConatiner while RightToLeft=Yes:

The Form

Let's examine the Form. The Form is the main element in your application, which contains your controls. You can add rtl support to your Form by simply setting RightToLeft but you will get a better behavior when you set RightToLeftLayout too, it depends on your needs.

There are simple forms and multiple document interface (MDI) parent form but let's start with the simple Form.

First, check this simple Form, before we add rtl to it.

The original form, before rtl.

Second, let's set RightToLeft to Yes and examine the form:

The Form, when RightToLeft is yes

The result is that the title is aligned to the right but the control boxes are still in the same location as when rtl= no. The containing controls inherit RightToLeft=Yes, if they were set to inherit , which is the default.

Third, let's give it a more advanced rtl look and set RightToLeftLayout to true:

The Form, when RightToLeft is yes and RightToLeftLayout =true

The result is that the title is aligned to the right and the control boxes are displayed in an rtl fashion. In addition to the child's controls are laid from the right to left. However, the containing controls don't inherit the RightToLeftLayout value.

Everyone agrees that the title is much better once you set RightToLeftLayout too but some people may not accept the reordering of the controls. This would depend on your application.

There is a simple workaround to keep your layout and still get an rtl title. You can fill the Form's client area with a Panel, so that it is your controls' parent and so the control's layout would not be affected by setting the RightToLeftLayout property.

This would be final result for your Form:

The Form, When RightToLeft is Yes and RightToLeftLayout =true and a docked Panel containing the controls.

Note: If you added the controls on the Form before the Panel, you may need to manually change the control's parent to the Panel instead of the Form.

Now let's examine the MDI Form. The MDI Form contains child Forms and these Forms are cascaded from left to right by default. To cascade child Forms from the right corner to the left of the parent's form you need to set RightToLeftLayout =true for the child forms too. However, this doesn't mean that the child Forms will inherit the RightToLeftLayout , you need to set this property individually to child Forms.

Note. If you need to set the MDI background image, it's recommended not to set RightToLeftLayout=true .

The figure below shows an MDI Parent form with RightToLeftLayout=true:

Strip Controls

When I talk about Strip controls, I am actually referring to MenuStrip , ToolStrip , StatusStrip , and ContextMenuStrip controls. These replace the troubled MainMenu , ToolBar , StatusBar , and ContextMenu . These controls had numerous problems with rtl support so it's great news you got the new strip controls. Even though MainMenu , ToolBar , StatusBar , and ContextMenu are not included by default in the Visual Studio Toolbox, they are still included in the .NET Framework, primarily for backwards compatibility.

The Strip controls provide a contemporary look of Office 2003 and Windows themes. They all share the same code base and thus provide the same handling to all the Strip controls. In addition to the improved design-time experience and ability to host a rich set of child controls, such as dropdownlists , textboxes and more.

And the main benefit is that they support proper RTL.

When you set RightToLeft=Yes, your strip control items are automatically rearranged from right-to- left. Even more, there is an additional property for the rtl images. RightToLeftAutoMirrorImage resolves common issues with rtl users, who use directional images, an example of directional images are the arrows with next \previous images. In this specific case, you need your image to be mirrored too. This property mirrors automatically the ToolStripItem image when the RightToLeft property is set to Yes . Otherwise it doesn't have an affect on your item.

The ToolStripProgressBar also has the RightToLeftLayout property to se the progress layout properly.

Below is a screenshot of a mirrored Question Mark, after setting RightToLeftAutoMirrorImage = True, while RightToLeft=Yes.

This is the code snippet to mirror the Help image:

// helpToolStripButton
//

this .helpToolStripButton.DisplayStyle = System.Windows.Forms. ToolStripItemDisplayStyle .Image;
this .helpToolStripButton.Image = ((System.Drawing. Image )(resources.GetObject( "helpToolStripButton.Image" )));
this .helpToolStripButton.RightToLeftAutoMirrorImage = true ;
this .helpToolStripButton.Text = "He&lp" ;