- •Contents
- •What Is C#?
- •C# Versus Other Programming Languages
- •Preparing to Program
- •The Program Development Cycle
- •Your First C# Program
- •Types of C# Programs
- •Summary
- •Workshop
- •C# Applications
- •Basic Parts of a C# Application
- •Structure of a C# Application
- •Analysis of Listing 2.1
- •Object-Oriented Programming (OOP)
- •Displaying Basic Information
- •Summary
- •Workshop
- •Variables
- •Using Variables
- •Understanding Your Computer’s Memory
- •C# Data Types
- •Numeric Variable Types
- •Literals Versus Variables
- •Constants
- •Reference Types
- •Summary
- •Workshop
- •Types of Operators
- •Punctuators
- •The Basic Assignment Operator
- •Mathematical/Arithmetic Operators
- •Relational Operators
- •Logical Bitwise Operators
- •Type Operators
- •The sizeof Operator
- •The Conditional Operator
- •Understanding Operator Precedence
- •Converting Data Types
- •Understanding Operator Promotion
- •For Those Brave Enough
- •Summary
- •Workshop
- •Controlling Program Flow
- •Using Selection Statements
- •Using Iteration Statements
- •Using goto
- •Nesting Flow
- •Summary
- •Workshop
- •Introduction
- •Abstraction and Encapsulation
- •An Interactive Hello World! Program
- •Basic Elements of Hello.cs
- •A Few Fundamental Observations
- •Summary
- •Review Questions
- •Programming Exercises
- •Introduction
- •Essential Elements of SimpleCalculator.cs
- •A Closer Look at SimpleCalculator.cs
- •Simplifying Your Code with Methods
- •Summary
- •Review Questions
- •Programming Exercises
- •Introduction
- •Lexical Structure
- •Some Thoughts on Elevator Simulations
- •Concepts, Goals and Solutions in an Elevator Simulation Program: Collecting Valuable Statistics for Evaluating an Elevator System
- •A Deeper Analysis of SimpleElevatorSimulation.cs
- •Class Relationships and UML
- •Summary
- •Review Questions
- •Programming Exercises
- •The Hello Windows Forms Application
- •Creating and Using an Event Handler
- •Defining the Border Style of the Form
- •Adding a Menu
- •Adding a Menu Shortcut
- •Handling Events from Menus
- •Dialogs
- •Creating Dialogs
- •Using Controls
- •Data Binding Strategies
- •Data Binding Sources
- •Simple Binding
- •Simple Binding to a DataSet
- •Complex Binding of Controls to Data
- •Binding Controls to Databases Using ADO.NET
- •Creating a Database Viewer with Visual Studio and ADO.NET
- •Resources in .NET
- •Localization Nuts and Bolts
- •.NET Resource Management Classes
- •Creating Text Resources
- •Using Visual Studio.NET for Internationalization
- •Image Resources
- •Using Image Lists
- •Programmatic Access to Resources
- •Reading and Writing RESX XML Files
- •The Basic Principles of GDI+
- •The Graphics Object
- •Graphics Coordinates
- •Drawing Lines and Simple Shapes
- •Using Gradient Pens and Brushes
- •Textured Pens and Brushes
- •Tidying up Your Lines with Endcaps
- •Curves and Paths
- •The GraphicsPath Object
- •Clipping with Paths and Regions
- •Transformations
- •Alpha Blending
- •Alpha Blending of Images
- •Other Color Space Manipulations
- •Using the Properties and Property Attributes
- •Demonstration Application: FormPaint.exe
- •Why Use Web Services?
- •Implementing Your First Web Service
- •Testing the Web Service
- •Implementing the Web Service Client
- •Understanding How Web Services Work
- •Summary
- •Workshop
- •How Do Web References Work?
- •What Is UDDI?
- •Summary
- •Workshop
- •Passing Parameters and Web Services
- •Accessing Data with Web Services
- •Summary
- •Workshop
- •Managing State in Web Services
- •Dealing with Slow Services
- •Workshop
- •Creating New Threads
- •Synchronization
- •Summary
- •The String Class
- •The StringBuilder Class
- •String Formatting
- •Regular Expressions
- •Summary
- •Discovering Program Information
- •Dynamically Activating Code
- •Reflection.Emit
- •Summary
- •Simple Debugging
- •Conditional Debugging
- •Runtime Tracing
- •Making Assertions
- •Summary
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.