Microsoft & .NET .NET Creating a App using JScript .NET and Windows Forms

Creating a App using JScript .NET and Windows Forms

In the second article of this series, I briefly
described how the JScript .NET and the .NET Framework allow
JScript developers to create Windows-style applications using
Windows Forms. Windows Forms is a part of the .NET Framework that
enables developers to take advantage of Windows’ graphical
interface capabilities.

A Windows Form represents a traditional graphical interface
through which users interact with your application. Windows Forms
offers a cohesive programming model that makes it easy to build
forms that have rich capabilities and a high degree of
interactivity. This article walks you through a sample
application written in JScript .NET that implements a Windows
Forms application that features and uses these types of
controls:


  • Main menu
  • Context menu
  • Tab strip control
  • Tree View control
  • Checked List Box control
  • Drop Down menu
  • Progress bar
  • Picture box control
  • Timer
  • Month calendar control

Figure 1 shows the completed application featured in this
article.


Figure 1 – Sample Application

Understanding the Windows Forms Programming Model

As with most other aspects of the programming with the .NET
Framework, a Windows Form is an object that derives from a base
class, which implements most of the form’s behavior. Your job is
to add controls and customize the behavior of the form for your
application. The Windows Forms package primarily resides in the
System.Windows.Forms namespace; however, you’ll also require
access to members of the System.Drawing namespace, which supports
accurate the Windows Forms package by allowing you to accurately
specify control placement and size.

Your application’s form acts as a container for the controls,
like buttons and text boxes, that reside in it. In fact, you must
programmatically add your controls to the form’s Controls collection for them to be visible
at runtime. Whenever a user clicks on a control, or interacts
with it in some way, the control raises events, which give your
application the opportunity to respond to the user’s actions.
When you create a control, you can specify what events a control
responds to and can provide your implementation for the event.
For example, the Stop button at the bottom of the form in Figure
1 stops the progress bar from updating – the code to implement
that behavior resides in the buttons Click event handler.

To create a basic form, you need to import some namespaces and
define a class that represents the form and contains its
controls, as shown in the following listing:



import System;
import System.Drawing;
import System.Windows.Forms;

public class sampleForm extends System.Windows.Forms.Form {

private var btnProgressControl : System.Windows.Forms.Button;

public function sampleForm() {
this.btnProgressControl = new System.Windows.Forms.Button();
this.btnProgressControl.Text = ” Stop “;
this.btnProgressControl.add_Click(btnProgressControl_OnClick);
}

function btnProgressControl_OnClick( source:Object, e: EventArgs )
{
//…
}
}

Application.Run(new sampleForm);

The sampleForm class extends the .NET Class Library’s
Form class, which provides
basic forms support. The class’s constructor initializes a Button object by setting its Text property (the button’s caption)
and defines the button’s Click event handler. The event handler
is a function that takes two arguments, as shown in the listing.
You can name the event handler function anything you want, but
the function’s signature (the function’s argument types) must
appear as shown (you can use any names for the arguments but the
types have to be Object and
EventArgs). Associate the
event handler with the button’s click event by calling the Button object’s add_Click method, passing it the name of
the event handler function. The application starts executing
through the Application
object’s static Run method,
which takes an instance of Windows Form object, makes it visible,
and processes system messages.

Working with Windows Forms Controls

The sample application includes a number of controls, all of
which are easy to work with. When you start the sample
application (you can download the sample’s source code using the
link at the end of this article), the tab strip control starts
with the tree view control visible, as shown in Figure 1. The
tree view control organizes information using a hierarchal
structure – you can access lower-level members by clicking on the
plus symbol next to the root nodes.

When you select a node and click the “Show Current Node”
button, a message box pops (see Figure 2) describing the
currently selected node and its full path. Here’s the code that
handles the button’s click event:



// The following line appears elsewhere in the class…
private var treeView1 : System.Windows.Forms.TreeView;

// This function handles the “Show Current Node”
// button’s click event
function btnCurrentNode_OnClick( source:Object, e: EventArgs )
{
if(treeView1.SelectedNode==null)
MessageBox.Show(“No currently selected nodennPlease
select a node and try again”,
“Note”,
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button1);
else
MessageBox.Show(“Selected “” + treeView1.SelectedNode.Text +
“”nLocated at: “” + treeView1.SelectedNode.FullPath+”””,
“Selected Node”,
MessageBoxButtons.OK,
MessageBoxIcon.Information,
MessageBoxDefaultButton.Button1);
}


Figure 2 – Displaying the currently selected node

If the user does not select a node, the tree view’s SelectedNode is null, otherwise, it refers to TreeNode object that describes the
currently selected node. The current node’s Text property has the display text shown
in the tree view control, while the FullPath property contains the complete
path (starting form the root node) to the currently selected
node. The FullPath property is
useful when you want to, for example, perform an operation on a
particular file in a directory listing. You can add nodes to the
tree view control using its Add or AddRange methods – see the source code for
details.

The tab strip control contains a Month Calendar control under
the Month Calendar tab. The control allows users to select a date
based on a calendar metaphor that’s easy to use and understand.
The control offers a number of customization features that you
can access using the control’s properties. For example, the month
calendar control has a FirstDayOfWeek property that allows you to
specify the first day of the week (the day of the week that
appears on the left side of each week in the month) – the sample
application sets the FirstDayOfWeek property to Monday.

The last control the tab strip control hosts is the Checked
List Box control, which is similar to a regular List Box control
except that each item has a check box next to it. When the user
clicks the “Checked Items” button, the following event handler
executes, which also causes a message box to pop up (see Figure
3):



function btnCheckedItems_OnClick( source:Object, e: EventArgs )
{
var i:int;
var msg:StringBuilder =
new StringBuilder(“Checked items:n”);

if(checkedListBox1.CheckedItems.Count==0)
msg.Append(“nNone!”);
else
for(i=0;i< checkedListBox1.CheckedItems.Count;i++)
{
msg.Append(“* “);
msg.Append(checkedListBox1.CheckedItems.Item(i).ToString());
msg.Append(“n”);
}
MessageBox.Show(msg.ToString(),
“Checked Items”,
MessageBoxButtons.OK,
MessageBoxIcon.Information,
MessageBoxDefaultButton.Button1);
}


Figure 3 – Displaying checked items

The function uses a StringBuilder object to compose a string
that contains a list of the currently selected items. A StringBuilder (from the System.Text
namespace) is a dynamic string that’s well suited for building
strings, as this function does, at runtime and is recommended
instead of the System.String object, which is considered
to be an immutable object. The only thing you need to watch out
for is that you call the StringBuilder object’s ToString method when you want to refer to
its String representation,
otherwise you’ll get a compile-time error about a type mismatch
whenever a method (like the MessageBox’s Show method) requires a String object as part of its list of
parameters that it accepts.

The checked list box control represents checked items as a
collection, which exposes a Count property making it easy to iterate
over the items the user selects as shown in the listing.

Examining the PictureBox control

A PictureBox control allows you to display images on your
form, as shown on the right side of Figure 1. The control
supports various types of graphic formats, including GIF and JPG.
Load an image into the PictureBox control based on the contents
of an Image object, which (in
this example) manages a Bitmap
object. It sounds complicated, but it’s actually straight-forward
and logical once you see the code, which I’ll present
shortly.

The ComboBox control (drop down menu above the PcitureBox
control) manages the contents of the PictureBox control at
runtime, as shown in Figure 4.


Figure 4 – Selecting a picture to display

Whenever the user selects an item from the ComboBox, an event
handler executes which checks to determine if an image file
exists and then loads the image into the PictureBox control.
Here’s the code:



function cboPicture_OnChanged( source:Object, e: EventArgs ) {
if(cboPicture.SelectedItem.ToString()==””) return;
var fileName_String=new String(cboPicture.SelectedItem.ToString()+”.jpg”);
if(!File.Exists(fileName))
{
MessageBox.Show(“Cannot load picture…”,
“Error”,
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button1);
return;
}

var pic : Bitmap = Bitmap(Image.FromFile(fileName));
pictureBox1.Image = pic;
}

The function composes a file name based on the currently
selected item’s text and a “.jpg” extension. The function uses
the File class’s static Exists method to ensure that the
image file the user selects exists in the same directory as the
sample application. If the file exists, the listing creates an
instance of a Bitmap object
based on the contents of an Image object, which is based on the
contents of an image file. The last action the code takes is to
assign the Bitmap to the
PictureBox’s Image property,
causing the currently selected image to be displayed.

The listing checks if the required image file exists before
attempting to load it because the Image object throws an exception if it
cannot load the file. An exception is a relatively
(computationally) expensive operation, which you should try to
avoid running into to make your code execute as fast as possible.
There are many cases, like this one, where you can anticipate the
exception and take steps to avoid the exception in the first
place, often using less expensive operations.

Working with a Timer

A Timer control is a non-visual control that can raise events
based on a time interval. When you run the sample application, it
appears that the code executes in parallel since the progress bar
at the bottom of Figure 1 updates every two seconds – even when
you interact with other controls on the form.

The Timer class resides in
the System.Timers namespace – set up a timer as shown in the
following listing:



// Appears in the class’s declaration…
private var localTimer : System.Timers.Timer ;

// Appears in the class’s constructor and InitializeComponent function…
localTimer = new System.Timers.Timer();
localTimer.Interval=2000;
localTimer.AutoReset=true
localTimer.add_Elapsed(OnTimer);
localTimer.Enabled=true;

// Elsewhere in the class…
function OnTimer( source:Object, e: ElapsedEventArgs )
{
if(progressBar.Value>=100)
progressBar.Value=0;
progressBar.PerformStep();
}

The listing creates an instance of a new timer and sets its
Interval property (the
frequency at which the timer fires). The AutoReset property, when true, resets the timer to zero after each
Interval – essentially setting
up the timer to fire again. The timer does not start until you
set its Enabled property to
true; the OnTimer function handles the Elapsed event each time it fires (every
2000 milliseconds, or two seconds). The OnTimer function works with the ProgressBar control to update it
every two seconds.

The ProgressBar control’s
PerformStep method increments
the position of the bar’s progress indicator, as defined by the
bar’s Step property. The
ProgressBar control has a number of properties that you can set
to customize its behavior and appearance – see the sample code
for details.

Working with Menus

Most modern applications implement a system of menus and
shortcut keys that make it easier for novice and advanced users
to take advantage of the application’s functionality. Menus make
an application’s functionality apparent to novice users, while
shortcut keys appeal to more advanced users that prefer not to
use a mouse for common tasks or frequently used application
functionality.

The sample application features two types of menus: a main
menu (a ‘traditional’ menu that runs across, just under the
application’s title bar) and a context menu (a menu that pops up
when a user right-clicks on the form), as shown in figures 5 and
6.


Figure 5 – Main Menu


Figure 6 – Context Menu

Whether you’re working on creating a context menu or a main
menu, the tasks you perform are the same – the only thing that
changes are the names of the objects. The following listing shows
how code the application’s main menu (under the application’s
title bar):



private var mnuMain : System.Windows.Forms.MainMenu;
private var mnuHelp : System.Windows.Forms.MenuItem;
private var mnuHelpAbout : System.Windows.Forms.MenuItem;

// mnuHelpAbout
mnuHelpAbout = new System.Windows.Forms.MenuItem
mnuHelpAbout.add_Click(mnuHelpAbout_Click)
mnuHelpAbout.Text = “&About”
mnuHelpAbout.Shortcut = Shortcut.CtrlA;
mnuHelpAbout.ShowShortcut = true;

// mnuHelp
mnuHelp = new System.Windows.Forms.MenuItem
mnuHelp.MenuItems.Add(mnuHelpAbout)
mnuHelp.Text = “&Help”
mnuHelp.ShowShortcut = false;

// mnuMainMenu
mnuMain = new System.Windows.Forms.MainMenu
mnuMain.MenuItems.Add(mnuHelp)
// *** Assign the main menu to the form…
this.Menu = mnuMain;

The listing creates three objects: a MainMenu, and two MenuItem objects – configure the MenuItem objects before you add them
to the MainMenu object, as
shown in the listing.

MenuItem objects have a
number of properties that make it easy to configure
application-wide shortcut keys for an option, in addition to
making keyboard based navigation possible. For example, you can
access the Help menu by pressing Alt+H, and then A; alternately,
you can also directly invoke the About menu by pressing Ctrl-A.
See the listing for details on how to configure the menu and the
shortcut keys.

Resizing Controls when the Form’s Size Changes

A trait that most advanced graphical applications have a
professional finish that comes from a very basic feature of
Windows applications – the ability to resize a Window. When you
resize a Window, like Internet Explorer’s window, there are some
controls that resize to match the proportions of the new window
(instead of having a fixed size or staying in place as you resize
the window).

Resizing controls based on the size of a containing window was
a problem in the past, which often required a lot of extra code.
The problem is so pervasive the Windows Forms includes automatic
support for resizing controls through control anchors.
For example, if you start the sample application and drag it’s
bottom right corner out and down, you’ll see the text box,
progress bar, and their associated buttons move along with the
form’s border as you resize it.

You can anchor a control using its Anchor property, which can have any or all
values in the AnchorStyles
enumeration. For example, the following line anchors the
ProgressBar to the bottom, left and right of the form:



progressBar.Anchor = AnchorStyles.Bottom | AnchorStyles.Right | AnchorStyles.Left;

When you resize the form, the ProgressBar stays at the bottom
of the form, and resizes along with changes in the forms left and
right borders. The button beside the ProgressBar does not change
size but moves with the form’s right side border because it’s
anchored to the bottom right of the form, as shown:



btnProgressControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Right ;

If you anchor the button to the Left as well, it ends up
resizing along with the form, which is an unusual visual behavior
for a button control. As a result, the button’s anchor has it
move only with the bottom and right borders such that it
maintains the same relative position as the form resizes.

Working with the sample code

The sample code works with .NET version 1.0 only. Download the ZIP file, extract its
contents into a new folder, and build the sample using the build command at a command prompt.
You can run the application by typing controls at the command prompt while
you’re in the same directory that you build the application
with.

Summary

The Windows Forms package offers a cohesive programming model
that makes it easy to build forms that have rich capabilities and
a high degree of interactivity. Most classes you’ll require to
build Windows Forms applications reside in the System.Windows.Forms and System.Drawing namespaces. Windows Forms
controls can be customized by programmatically manipulating their
properties and methods. The next article in this series goes
through the process of creating a Web Service and consuming it
from a Windows Forms application, ASP.NET application, and
directly from Internet Explorer.



Essam Ahmed is the author of “< a href="http://books.internet.com/books/0764548689" target="new">JScript .NET Programming”
(ISBN 0764548689, Published by Hungry Minds September 2001), many
articles (including some at CodeGuru.com) and book reviews (also
available at CodeGuru.com).
Contact Essam at [email protected],
or at his Web site

# # #

Latest Posts

Related Stories