Скачиваний:
64
Добавлен:
15.03.2015
Размер:
4.31 Mб
Скачать

Windows Forms

298

PART III

In this chapter, we will be looking at some more of the features of Windows Forms that you will need to be familiar with when writing applications for the .NET framework.

Specifically, we’ll deal with resources, including text, bitmap images, and icons. We’ll also be looking at globalization, the process of making your applications friendly to an international audience.

Resources in .NET

Unlike Win32 and MFC, .NET applications do not rely heavily on resources for dialog and form layout. However, resources are required for localization of applications, integration of images and icons, and for custom data that can be easily modified without needing to recompile an application.

The resource model under .NET is that of a default resource for an application and an optional set of additional resources that provide localization, or more properly internationalization, data for a specific culture. For example, an application might have a default resource culture of US—English but require localization for the UK—English, where the currency symbol would be different, or for French, where the text strings associated with menus and dialogs would be in the correct language.

The default resource is usually contained within the assembly that holds the application code. Other assemblies, called satellite assemblies, have resources that can be loaded and used when needed. This approach is similar to the idea of an application using a resource DLL under Win32 or MFC.

A good “global citizen” application should always be localizable and should always provide a resource for any culture in which that the software is used. It is also true that not every application needs to be a global citizen, so you must choose your level of culture—friendliness— according to your distribution and target audience needs.

Localization Nuts and Bolts

It’s good practice to build your applications with localization in mind. The most important thing you can do to prepare for this is to not embed any strings in your code that the user will see. For example you would never use:

MessageBox.Show(“Hello World!”);

Windows Forms Example Application (Scribble .NET)

CHAPTER 3.4

because it embeds the “Hello World!” string in the source code. To make this program a good global citizen, you would create a default resource where the string was identified by a value. For example,

MessageBox.Show((String)resources.GetObject(“MyHelloworldResourceString”);

In this line, the actual text of the message is not placed in the code but retrieved from a resource that has a string identified as “MyHelloWorldResourceString”.

If your default culture is US-English, the string would say “Hello World!” If the application needed to be used in France, a satellite assembly with the French resources would have a string with the same “MyHelloWorldResourceString” ID, except that this string would have the value of “Bonjour Le Monde!”

.NET Resource Management Classes

The .NET framework provides a family of classes that are designed to make resource management consistent and easy. These classes are as follows:

ResourceManager is used to manage all resources in an application.

ResourceSet represents a collection of all the resources for a particular culture.

ResourceReader is an implementation class for the IResourceReader interface. This is

used to read resources from a stream.

ResourceWriter is an implementation of the IResourceWriter interface. This are used to write resources to a stream.

Your application must use a ResourceManager to load the resource assemblies and make them available to the rest of the program. The ResourceManager will return a ResourceSet for a given culture.

Got Culture?

Different cultures and languages are identified through the CultureInfo class. This class is a simple information store that contains data about the culture selected by the user when he or she installed the operating system. It contains information about the language, calendar, currency, and other preferences that the user might have chosen. Your software will have access to this information so that it can determine whether it has the ability to offer culture-specific resources or must choose the neutral default value.

299

3.4

INDOWSWEA FXAMPLEPPLICATION ORMS

Windows Forms

300

PART III

Being culture specific might be very important in the message you are trying to deliver. There is an anecdote that illustrates why.

A Little Bit of Culture

A large soap manufacturer created a printed advertisement for display on billboards that showed dirty clothes being loaded into a washing machine. A second picture showed the washing powder being poured into the machine and a third image depicted these clothes being taken out of the washer all clean and fresh. They could- n’t understand why the sales of the product dropped dramatically in certain countries until it was pointed out that the places that had low sales were right-to-left reading cultures. Their advertisement, created by American’s, had shown clean clothes washed in this soap powder emerging all dirty and stained from the machine. Never underestimate the power of assumption.

Culture information about languages is provided by a two-letter code and an optional region identifier that accompanies the two letter code. For example, the neutral English language is represented by the two letter code en, but the different flavors of English—English from England, Canada, the United States and other places—is identified by the sub-codes GB, CA, US, and so on.

Listing 3.4.1 shows a program that will get the CultureInfo for your computer and display the language and region that applies to your computer. It also shows the full name of the culture and which calendar your current culture is using.

LISTING 3.4.1 culture.cs: Displaying the Current Culture Information

1:namespace Sams

2:{

3:using System;

4:using System.Drawing;

5:using System.Collections;

6:using System.ComponentModel;

7:using System.Globalization;

8:using System.Windows.Forms;

9:using System.Data;

10:

11:class CultureInfoTest : Form

12:{

13:

14:public CultureInfoTest()

15:{

Windows Forms Example Application (Scribble .NET)

CHAPTER 3.4

LISTING 3.4.1 Continued

16: this.Size = new Size(300,200); 17:

18:Label l = new Label();

19:l.Location = new Point(3,5);

20:l.Size = new Size(294,190);

22: InputLanguage inL = InputLanguage.CurrentInputLanguage; 23:

24: CultureInfo info = inL.Culture; 25:

26:l.Text = String.Format(“Culture identifier = {0}\n”+

27:

“Display name = {1}\n”+

28:

“Calender = {2}\n”,

29:

info.ToString(),

30:

info.DisplayName,

31:

info.Calendar.ToString());

32:

this.Controls.Add(l);

33:

 

34:}

35:static void Main()

36:{

37:Application.Run(new CultureInfoTest());

38:}

39:}

40: 41: }

Creating Text Resources

There are several ways you can create text resources for your programs. The simplest is by creating a text file that has a set of name-value pairs. These specify a name that you can use in your code to find the resource and the text to associate with that name.

When you’ve finished making your basic string resource file, you must turn it into a .resx or

.resource file using the .NET tool RESGEN.EXE. The following example shows this process.

The String Resource Text

301

3.4

INDOWSWEA FXAMPLEPPLICATION ORMS

The following simple text file shows a set of name/-value pairs for a resource that will be used to provide the default strings for an application. Note that quotation marks are not required on strings. If you use quotes, they will be embedded in the resource string.

Windows Forms

302

PART III

#Default culture resources

WindowText = Internationalization example LabelText = Hello World!!!

The text file can be converted into one of two forms—an XML-based form that is stored as a

.resx file or directly to its compiled .resource form. The .resx file is an XML dataset that is used to serialize resource information during development. Conversion of resources from one form to another is accomplished using the Resgen utility. Type in the previous simple resource text and save it as firstresource.txt, and then create a .resx file using the following command line:

resgen firstresource.txt firstresource.resx

The utility will compile the file and tell you that two resources have been converted. Listing 3.4.2 shows the resulting XML file.

LISTING 3.4.2 firstresource.resx: The Converted Resource File in XML Form

<?xml version=”1.0” encoding=”utf-8”?> <root>

<xsd:schema id=”root” targetNamespace=”” xmlns=””xmlns:xsd=”http://www.w3.org/2001/XMLSchema”xmlns:msdata=”urn:schemas-microsoft-com:xml-msdata”>

<xsd:element name=”root” msdata:IsDataSet=”true”> <xsd:complexType>

<xsd:choice maxOccurs=”unbounded”> <xsd:element name=”data”>

<xsd:complexType>

<xsd:sequence>

<xsd:element name=”value” type=”xsd:string” minOccurs=”0”msdata:Ordinal=”1” />

<xsd:element name=”comment” type=”xsd:string” minOccurs=”0”msdata:Ordinal=”2” />

</xsd:sequence>

<xsd:attribute name=”name” type=”xsd:string” /> <xsd:attribute name=”type” type=”xsd:string” /> <xsd:attribute name=”mimetype” type=”xsd:string” />

</xsd:complexType>

</xsd:element>

<xsd:element name=”resheader”> <xsd:complexType>

<xsd:sequence>

<xsd:element name=”value” type=”xsd:string” minOccurs=”0”msdata:Ordinal=”1” />

Windows Forms Example Application (Scribble .NET)

CHAPTER 3.4

LISTING 3.4.2 Continued

</xsd:sequence>

<xsd:attribute name=”name” type=”xsd:string” use=”required” /> </xsd:complexType>

</xsd:element>

</xsd:choice>

</xsd:complexType>

</xsd:element>

</xsd:schema>

<data name=”WindowText”> <value>Internationalization example</value>

</data>

<data name=”LabelText”> <value>Hello World!!!</value>

</data>

<resheader name=”ResMimeType”> <value>text/microsoft-resx</value>

</resheader>

<resheader name=”Version”> <value>1.0.0.0</value>

</resheader>

<resheader name=”Reader”> <value>System.Resources.ResXResourceReader</value>

</resheader>

<resheader name=”Writer”> <value>System.Resources.ResXResourceWriter</value>

</resheader>

</root>

You can see from Listing 3.4.2 that this is probably not a file you will want to type in by hand. The first part of the file is the schema that defines XML content of the file. Each element is contained within an XML node tagged <data name=”some-name”>. If you look through the file, you will see the two resources that were specified in the text file and their respective values. It is this .resx form of the resources that Visual Studio maintains when you create resources in your applications.

To use the resource file in a sample program, you will need to convert it to its compiled form. You can do this from either the text format or the XML format by using one of the following command lines:

Resgen firstresource.txt firstresource.resources

or

303

3.4

INDOWSWEA FXAMPLEPPLICATION ORMS

Resgen firstresource.resx firstresource.resources

Windows Forms

304

PART III

A Simple Winforms Application That Relies on a Resource

To test the resource file shown in Listing 3.4.2, you can create a simple “Hello World”-type application as shown in Listing 3.4.3. This program relies on the firstresource.resources file created previously to provide the text for the label and the window title bar.

LISTING 3.4.3 hellores.cs: Using Simple String Resources

1:namespace Sams

2:{

3:using System;

4:using System.Drawing;

5:using System.Collections;

6:using System.ComponentModel;

7:using System.Globalization;

8:using System.Windows.Forms;

9:using System.Data;

10:using System.Resources;

11:

12:class hellores: Form

13:{

14:

15:public hellores()

16:{

17:ResourceManager rm=new ResourceManager(“firstresource”,this.GetType().Assembly);

18:

19:this.Size = new Size(400,100);

20:this.Text=rm.GetString(“WindowText”);

22:Label l = new Label();

23:l.Location = new Point(3,5);

24:l.Size = new Size(394,90);

25:l.Font = new Font(“Tahoma”,36F,FontStyle.Bold);

26:l.Text=rm.GetString(“LabelText”);

27:this.Controls.Add(l);

28:

29: } 30:

31:static void Main()

32:{

33:Application.Run(new hellores());

34:}

35:}

36: 37: }

Windows Forms Example Application (Scribble .NET)

305

CHAPTER 3.4

The code in Listing 3.4.3 is a good global citizen application. It embeds no strings, and draws all of its text from the resource set provided. Line 17 of the listing shows how a resource manager is created, and lines 20 and 26 show how the named strings are retrieved from the resources in the assembly and applied to the Windows Forms elements.

To build this file and run it, you will need to use the following command line:

csc /out:hellores.exe /t:winexe /res:firstresource.resources hellores.cs

Notice how the command line option /res: is used to embed the compiled form of the resources created earlier.

Running the program now will produce the result shown in Figure 3.4.1.

FIGURE 3.4.1

The hellores program in operation.

Creating and Using a Satellite Assembly

The globalization example is not much use without an alternative resource set from which to draw. In the following example, we’ll add a satellite assembly containing a French resource set.

NOTE

A satellite assembly is a DLL, containing code or data, that is used by an application’s main assembly.

A satellite assembly, in this case, is analogous to a resource-only DLL. Satellite assemblies for localization are normally private to a particular application. They are stored in a specially named subdirectory below the main application directory. In this case, you’ll need to create a directory called fr so that the resource manager can find it.

First, create the resource text using the same names but different values for every string that needs to be displayed. Notice that only the label text changes here. This will be explained shortly.

#Version Francaise.

LabelText = Bonjour le monde!!!

3.4

INDOWSWEA FXAMPLEPPLICATION ORMS

Windows Forms

306

PART III

Call this file firstresource.fr.txt. After this file is complete, you can create the satellite assembly using the following command lines:

resgen firstresource.fr.txt firstresource.fr.resources

al /out:fr/hellores2.Resources.DLL /c:fr /embed:firstresource.fr.resources

The utility program invoked in the second line is the Assembly Linker (AL). AL can be used for creating assemblies of all sorts, but here we’re only interested in its resource packaging abilities. Notice that the /out: command line option places the assembly DLL into the fr directory.

Now you can build the hellores2.exe program. It’s very similar to the original but has a command line option that allows you to select the culture by typing in the culture identification string. Listing 3.4.4 shows the source.

LISTING 3.4.4 hellores2.cs: The Localized Hello World Example

1:namespace Sams

2:{

3:using System;

4:using System.Drawing;

5:using System.Collections;

6:using System.ComponentModel;

7:using System.Globalization;

8:using System.Windows.Forms;

9:using System.Data;

10:using System.Resources;

11:using System.Threading;

12:

13:class hellores: Form

14:{

15:

16:private Label l;

17:private ResourceManager rm;

20:public hellores(string culture)

21:{

22:Thread.CurrentThread.CurrentUICulture =new CultureInfo(culture);

23:

24: rm=new ResourceManager(“firstresource”,this.GetType().Assembly);

25:

26:this.Size = new Size(400,100);

27:this.Text=rm.GetString(“WindowText”);

Windows Forms Example Application (Scribble .NET)

CHAPTER 3.4

LISTING 3.4.4 Continued

28:

29:l = new Label();

30:l.Location = new Point(3,5);

31:l.Size = new Size(394,90);

32:l.Font = new Font(“Tahoma”,36F,FontStyle.Bold);

33:l.Text=rm.GetString(“LabelText”);

34:l.Anchor = (AnchorStyles.Top |

35:

AnchorStyles.Left |

36:

AnchorStyles.Bottom |

37:

AnchorStyles.Right);

38:

this.Controls.Add(l);

39:

 

40:

}

41:

 

42:static void Main(string[] args)

43:{

44:string culture =””;

45:if(args.Length == 1)

46:culture = args[0];

47:Application.Run(new hellores(culture));

48:}

49:}

50: 51: }

There are a few simple changes to the program in Listing 3.4.4. Line 22 forces a setting for the current user interface culture based on the input from the command line. The properties of the label are modified on lines 34–37 so that the label changes size with the form. In this example, you will need to resize the form to see the whole label text. This shows another aspect of internationalization that you have to contend with, the possibility that physical resource sizes might be different across cultures. It is possible to store the size and placement information of your resources in the satellite assembly also. Visual Studio does this for you, and we’ll look at that in a moment. Otherwise, the use of the string resources is identical.

The application can be compiled with the following command line:

csc /out:hellores2.exe /t:winexe /res:firstresource.resources hellores2.cs

Now the program can be run and an fr culture selected by invoking it as follows:

hellores2 fr

307

3.4

INDOWSWEA FXAMPLEPPLICATION ORMS

In this circumstance, you’ll see the application displaying the French resource string, as shown in Figure 3.4.2.