Lab 8: Creating a Localized Form with Print Support
In this lab, you will create an application for international use. The application will be a simple forms-based application that accepts orders from the user and adds them to a list box. You will implement globalization for your form and create a localized version for use in Italy. You will also add print support to your form. The solution to this lab is available on the Supplemental Course Materials CD-ROM in the \Labs\Ch08\Solution folder.Before You Begin
There are no prerequisites to completing this lab.
Estimated lesson time: 60 minutes
Exercise 8.1: Creating the FormBusiness is booming! In this exercise, you will create an application to handle orders. The application will allow users to enter values for quantity and price, and add a summary of the order to a list box.
To create the form
Create a new Windows Forms project. Add the controls listed in Table 8.4 to the form, and set the properties as indicated.
Control | Property | Value |
Label1 | Name | lblQuantity |
Text | Quantity | |
Label2 | Name | lblPrice |
Text | Price | |
Label3 | Name | lblTotal |
Text | Total | |
TextBox1 | Name | txtQuantity |
Text | (empty) | |
TextBox2 | Name | txtPrice |
Text | (empty) | |
TextBox3 | Name | txtTotal |
Text | (empty) | |
ReadOnly | True | |
Button1 | Name | btnAdd |
Text | Add Order | |
Button2 | Name | btnClear |
Text | Clear Order | |
Button3 | Name | btnClearAll |
Text | Clear All Orders | |
Button4 | Name | btnPrint |
Text | ||
ListBox1 | Name | lstOrder |
After adding controls, your form should look Figure 8.10.
Figure 8-10. Lab Form1.
Using the Events window in the designer (for Visual C#) or the drop-down boxes in the code window (for Visual Basic .NET), implement handlers for the KeyPress events of txtPrice and txtQuantity. They should verify that the keystroke represents a number. The following code example demonstrates an appropriate event handler for txtPrice:
Visual Basic .NET
Private Sub txtPrice_KeyPress(ByVal sender As Object, ByVal e As _ System.Windows.Forms.KeyPressEventArgs) Handles txtPrice.KeyPress If Char.IsNumber(e.KeyChar) = False Then e.Handled = True End If End Sub
Visual C#
private void txtPrice_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { if (char.IsNumber(e.KeyChar) == false) e.Handled = true; }
Add a method to handle the Click event of btnAdd by double-clicking btnAdd in the designer and adding code. This method should multiply the values in txtQuantity and txtPrice and display the product in currency format in txtTotal. It should add a string representation of quantity, price, and total to lstOrder. An example follows:
Visual Basic .NET
Private Sub btnAdd_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnAdd.Click Dim Total As Single Total = Single.Parse(txtQuantity.Text) * _ Single.Parse(txtPrice.Text) txtTotal.Text = Format(Total, "Currency") Dim TotalString As String TotalString = txtQuantity.Text & " x " & txtPrice.Text & " = " _ & txtTotal.Text lstOrders.Items.Add(TotalString) End Sub
Visual C#
private void btnAdd_Click(object sender, System.EventArgs e) { float Total; Total = float.Parse(txtQuantity.Text) * float.Parse(txtPrice.Text); txtTotal.Text = Total.ToString("C"); string TotalString; TotalString = txtQuantity.Text + " x " + txtPrice.Text + " = " + txtTotal.Text; lstOrders.Items.Add(TotalString); }
By double-clicking the appropriate buttons in the designer, create methods to handle the events of btnClear and btnClearAll. The btnClear method should clear the three text boxes, and the btnClearAll method should clear the text boxes and the list box as well. For example:
Visual Basic .NET
Private Sub btnClear_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnClear.Click txtQuantity.Text = "0" txtPrice.Text = "0" txtTotal.Text = Format(0, "Currency") End Sub Private Sub btnClearAll_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnClearAll.Click txtQuantity.Text = "0" txtPrice.Text = "0" txtTotal.Text = Format(0, "Currency") lstOrders.Items.Clear() End Sub
Visual C#
private void btnClear_Click(object sender, System.EventArgs e) { txtQuantity.Text = "0"; txtPrice.Text = "0"; txtTotal.Text = 0.ToString("C"); } private void btnClearAll_Click(object sender, System.EventArgs e) { txtQuantity.Text = "0"; txtPrice.Text = "0"; txtTotal.Text = 0.ToString("C"); lstOrders.Items.Clear(); }
Save and test your work. Your form should carry out a simple adding function and add members to the list box at the bottom.
Now that your business is a success, you re going global! In this exercise, you will localize your form to provide the user interface in Italian. You will also implement functionality to allow the user to choose the locale before the application begins.
To localize the form
In the designer, select Form1. In the Properties window, set Localizable to true. Notice that the Language property is set to (Default). The current UI properties will be used to format the display when the default language is chosen.
In the Properties window, change the value of the Language property from (Default) to Italian (Italy).
Using the Properties window, set the properties listed in Table 8.5 to their corresponding values.
Property | Value |
lblQuantity.Text | Quantit |
lblPrice.Text | Prezzo |
lblTotal.Text | Totale |
btnAdd.Text | Aggiungi ordine |
btnClear.Text | Rimuovi ordine |
btnClearAll.Text | Rimuovi tutti gli ordini |
btnPrint.Text | Stampa |
You can generate the character by holding down the Alt key and typing 0224. You can also insert the character using the character map tool found in Windows XP. To access the character map tool, click Start, All Programs, Accessories, System Tools.
NOTE
You might need to adjust the size of some of your controls or your form to accommodate localized content.
In the Properties window, set the Language property of Form1 to (Default). Note that the control texts have reverted to their original settings.
From the Project menu, choose Add Windows Form. Name this form frmLanguage, and click Open.
In the designer, add a combo box to this form. Set the control properties as shown in Table 8.6.
Control | Property | Value |
frmLanguage | Text | Choose your locale. |
ComboBox1 | Name | cmbLocale |
Text | Please select a locale. | |
Items (add) | United States | |
Items (add) | Great Britain | |
Items (add) | Italy |
In the code editor for frmLanguage, add an event handler for the SelectedIndexChanged event of cmbLocale. This method should set the current culture and the current UI culture to the appropriate culture and close the form. For example:
Visual Basic .NET
Private Sub cmbLocale_SelectedIndexChanged(ByVal sender As _ System.Object, ByVal e As System.EventArgs) Handles _ cmbLocale.SelectedIndexChanged Dim aString As String aString = CType(cmbLocale.SelectedItem, String) Select Case aString Case "United States" ' Since the default locale is already the United States, no ' action is necessary. ' action is necessary. Me.Close() Case "Great Britain" System.Threading.Thread.CurrentThread.CurrentCulture = _ New System.Globalization.CultureInfo("en-GB") System.Threading.Thread.CurrentThread.CurrentUICulture _ = New System.Globalization.CultureInfo("en-GB") Me.Close() Case "Italy" System.Threading.Thread.CurrentThread.CurrentCulture = _ New System.Globalization.CultureInfo("it-IT") System.Threading.Thread.CurrentThread.CurrentUICulture _ = New System.Globalization.CultureInfo("it-IT") Me.Close() End Select End Sub
Visual C#
private void cmbLocale_SelectedIndexChanged(object sender, System.EventArgs e) { string aString; aString = (string)cmbLocale.SelectedItem; switch (aString) { case "United States": // Since the default locale is already the United States, no // action is necessary. this.Close(); break; case "Great Britain": System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-GB"); System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-GB"); this.Close(); break; case "Italy": System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("it-IT"); System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("it-IT"); this.Close(); break; } }
In the code editor for Form1, locate the constructor. Add the following lines of code immediately after the call to the base class constructor (MyBase.New()) in Visual Basic .NET or as the first line of the constructor in Visual C# (before the call to InitializeComponent):
Visual Basic .NET
Dim aForm As New frmLanguage() aForm.ShowDialog()
Visual C#
frmLanguage aForm = new frmLanguage(); aForm.ShowDialog();
NOTE
In Visual Basic, you might have to expand the box labeled Windows Form Designer Generated Code in the code editor to locate the constructor.
Save and test your application. Choose United States for your locale in the initial form and test the application. Note that currency is formatted using the dollar sign ($). Next close the application and restart, choosing Great Britain as the locale. Currency is now formatted using the pound sign ( ). Close the application and restart it one more time, choosing Italy as the locale. Note that the localized version of the form is used and that the appropriate captions are displayed. Currency is formatted using the Euro sign and is formatted in the European style, using the comma (,) as a decimal separator and the period (.) as a thousand separator.
In this exercise, you will add print support to your application. You will add a print document and write code to handle the PrintPage event. This code will render text to the printer and include support for multipage documents.
To add print support to your application
In the designer for Form1, drag an instance of PrintDocument from the Toolbox to the form. An instance of PrintDocument appears in the component tray.
Double-click PrintDocument1 (printDocument1) to open the default event handler for the PrintPage method. In the default event handler, add the following code to render the contents of lstOrders to the printer:
Visual Basic .NET
Dim LeftMargin As Single = e.MarginBounds.Left Dim TopMargin As Single = e.MarginBounds.Top Dim MyLines As Single = 0 Dim YPosition As Single = 0 Dim Counter As Integer = 0 Dim CurrentLine As String Dim myFont As New Font("Times New Roman", 16, FontStyle.Regular, _ GraphicsUnit.Pixel) ' Calculate the number of lines per page. MyLines = e.MarginBounds.Height / myFont.GetHeight(e.Graphics) ' Prints each line of the file, but stops at the end of a page While Counter < MyLines And ItemCounter <= lstOrders.Items.Count 1 CurrentLine = CType(lstOrders.Items(ItemCounter), String) YPosition = TopMargin + Counter * myFont.GetHeight(e.Graphics) e.Graphics.DrawString(CurrentLine, myFont, Brushes.Black, _ LeftMargin, YPosition, New StringFormat()) Counter += 1 ItemCounter += 1 End While ' If more lines exist, print another page. If Not (ItemCounter = lstOrders.Items.Count) Then e.HasMorePages = True Else e.HasMorePages = False End If
Visual C#
float LeftMargin = e.MarginBounds.Left; float TopMargin = e.MarginBounds.Top; float MyLines = 0; float YPosition = 0; int Counter = 0; string CurrentLine; Font myFont = new Font("Times New Roman", 16, FontStyle.Regular, GraphicsUnit.Pixel); // Calculate the number of lines per page. MyLines = e.MarginBounds.Height / myFont.GetHeight(e.Graphics); // Prints each line of the file, but stops at the end of a page while (Counter < MyLines && ItemCounter <= lstOrders.Items.Count 1) { CurrentLine = (string)lstOrders.Items[ItemCounter]; YPosition = TopMargin + Counter * myFont.GetHeight(e.Graphics); e.Graphics.DrawString(CurrentLine, myFont, Brushes.Black, LeftMargin, YPosition, new StringFormat()); Counter += 1; ItemCounter += 1; } // If more lines exist, print another page. if (!(ItemCounter == lstOrders.Items.Count)) e.HasMorePages = true; else e.HasMorePages = false;
Immediately outside of the method declaration, add the ItemCounter variable to keep track of the printed items:
Visual Basic .NET
Dim ItemCounter As Integer
Visual C#
int ItemCounter;
In the designer for Form1, double-click btnPrint. As shown in the code example to follow, call the PrintDocument.Print method to render your content to the printer. Set the ItemCounter variable to 0 so that it prints the entire list each time:
Visual Basic .NET
ItemCounter = 0 printDocument1.Print()
Visual C#
ItemCounter = 0; printDocument1.Print();
Save and test your work. Click the Print button to see the order list printed.