Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Writing a Windows Form Application For .NET Framework Using C#

0.00/5 (No votes)
20 Apr 2002 1  
A tutorial on writing Windows Forms application using C#

Sample Image - Image002.jpg

Introduction

This article is a very simple introduction on writing a Windows Form application for the Microsoft.NET framework using C#. The sample application demonstrates how to create and layout controls on a simple form and the handling of mouse click events. The application displays a form showing attributes of a file. This form is similar to the properties dialog box of a file (Right click on a file and Click on Properties menu item). Since attributes of a file will be shown, the sample will show how to use File IO operations in .NET framework.

What is the starting point?

Like every Win32 application source, we will start with the inclusion of some header files. C# does not make use of header files; it uses namespaces to accomplish this purpose. Most of the C# core functionality is implemented in the System namespace. For forms application, the functionality is included in the System.WinForms namespace. Therefore, right at the top of our source file we need to define these namespaces.

using System;
using System.WinForms;

We will need some more namespace definitions, but I will explain them as we go along with this sample application. Like every C# application, Windows Forms application will be defined as a class. Since we will be making use of the Form class, it needs to be derive from it.

public class WinFileInfo : Form

The next thing that needs to be identified is the entry point for the application. Unlike Win32 applications, the method Main (not WinMain) will be the entry point for this application.

public static void Main ()
{
	Application.Run (new WinFileInfo ());
}

The Application class provides static methods to manage an application like running, closing, and managing windows messages. In the method Main of the application we will start running the application using the method Run of the Application class. And later on we will call the method Exit on the Application class to stop the application or in other words close the form.

How do I layout controls on the form?

Since we are writing a GUI application, we need some controls on the form. And because this application has been written using the .Net SDK, no wizard or tools have been used. So how can we put controls on the form and define their location sizes? This is very much like writing a resource file for Win32 application. The System.WinForms namespace contains definitions for all the common controls we will use on forms or Windows Form applications e.g. Button, Checkbox, RadioButton, etc. For more information check the online documentation for .NET SDK. The Control class defines the base class for controls. This class contains the base methods. All the controls override the virtual methods specific to their functionality.

First lets see what the output of this Form application looks like.

The Application does this layout of controls in the method InitForm.

public WinFileInfo ()
{
	InitForm ();
}

Setting the Text property of Form object will set the title of the form.

this.Text = "File Information Application";

The client size of the form is controlled by the ClientSize property of the form.

this.ClientSize = new Size(400, 280);

The controls in the Form application follow a hierarchical pattern i.e. each control acts as a container for other controls. And for complex GUI design, controls can be layered on top of each other and then pushed back or brought forward as needed. In this particular application, Form acts as a container for a Panel, GroupBox and a bunch of other controls like buttons, static text, etc. The GroupBox acts as a container for three checkboxes. The panel acts as a container for an edit control and a static text (in Forms terms, label control). The following code adds the check boxes to the GroupBox control container using the method Add of the Controls collection of the Form.

wndAttribBox.Controls.Add (wndArchiveCheck);
wndAttribBox.Controls.Add (wndReadOnlyCheck);
wndAttribBox.Controls.Add (wndHiddenCheck);

The other method of adding controls to the controls collection is by directly creating an array of control objects and setting the All property of control collection of Form to the array. The following code sets the child controls in the Form container.

this.Controls.All = new Control [] {
   wndPanel,
   wndAttribBox,
   wndFileExistCheck,
   wndLocationLabel,
   wndLocation,
   wndCreateTimeLabel,
   wndLastAccessLabel,
   wndLastWriteLabel,
   wndCreateTime,
   wndLastAccessTime,
   wndLastWriteTime,
   wndFindButton,
   wndCloseButton
};

How do I create controls and set their properties?

Every Control in the .NET Framework is an Object that implements methods, properties and events. An object is created using the new operator in C#. The same concept applies to controls too. I will describe the creation of a Button control, setting its properties like size and location and then event handlers for the click on the button.

First we need to define the control variable for the WinFileInfo class. The following code shows how the various controls have been defined and created.

ButtonwndFindButton= new Button ();
ButtonwndCloseButton= new Button ();
CheckBoxwndFileExistCheck= new CheckBox ();
CheckBoxwndArchiveCheck= new CheckBox ();
CheckBoxwndReadOnlyCheck= new CheckBox ();
CheckBoxwndHiddenCheck= new CheckBox ();

The best thing about the .NET Framework is that we do not have to worry about releasing the variables allocated on the heap using the new operator. Garbage collection will do its magic (trust MS on this) when the variable is not in use anymore.

The following code shows how the various properties for the Find button have been set. The name of the button's properties are very self-explanatory but I will try to describe them one by one.

// Set some properties for Find Button.

wndFindButton.Text = "Find";
wndFindButton.TabIndex = 0;
wndFindButton.Anchor = AnchorStyles.BottomRight;
wndFindButton.Size = new Size (72, 24);
wndFindButton.Location = new Point (110, 250);
wndFindButton.Click += new EventHandler (this.buttonFind_click);

The Text property is used to set the text that will be displayed on the button. This is like calling the SetWindowText Win32 API call on button control.

The TabIndex sets the index of Tab i.e. where does this control stand in the sequence when a user navigates through the controls using the Tab key. This is like setting TabOrder using Visual Studio control wizard. A TabIndex of 0 indicates that this control will be the first to gain focus when the Tab key is pressed.

The Anchor is a very important property if you want to fix the location of a control with respect to some fixed point of the parent control or container. For example in this case I want the Button to always stay anchored to the Bottom Right corner of the form no matter what. So if user tries to resize the form, the button will reposition itself to stay anchored to the Bottom Right corner of Form.

The Size property fixes the size of a control.

The Location property sets the location of the control with respect to its parent control.

The most important setting is how to handle the event when the user clicks on this control. This is done through adding an event handler to the Click event of the Control object. We create a new event handler using the EventHandler object and pass the function that will handle the event, as an argument to the EventHandler constructor. The EventHandler created is added to the Click event of the Button.

This way we can create controls dynamically and set their properties and event handling methods. After creating all the controls do not forget to add them to the parent container like Form, Panel, GroupBox, and etc.

How do I tweak some properties of the Form?

Like every Win32 control, we can customize the appearance and actions of all the controls. For example, what button should handle the message if the user clicks ENTER? Setting the AcceptButton property of the form can do this.

this.AcceptButton= wndFindButton;

The following code from the InitForm method shows some of the other properties that can be customized.

// We don't need a maximize box for this form.

this.MaximizeBox = false;

// Set the Find button to ACCEPT button for this form.

this.AcceptButton= wndFindButton;

// Set the close button to Cancel operation button.

this.CancelButton = wndCloseButton;

// Set the start position of the form to be center of screen.

this.StartPosition = FormStartPosition.CenterScreen;

//And then activate the Form object.

this.Activated += new EventHandler (this.WinFileInfo_activate);

Can I use Win32 API functions in C#?

Yes, you can do it. For this you need to import Win32 DLLs that implement the functions you need. E.g. for LoadImage, DestroyObject API calls, we need to import User32.dll and Gdi32.dll DLLs. This can be accomplished by using code as shown below.

//-------------------------------------------------

// We need to import the Win32 API calls used to deal with

// image loading.

//-------------------------------------------------

[DllImport("user32.dll")]
public static extern int LoadIcon(int hinst, String name);
[DllImport("user32.dll")]
public static extern int DestroyIcon(int hIcon);
[DllImport("user32.dll")]
public static extern int LoadImage(int hinst, String lpszName,uint uType, 
                                   int cxDesired,int cyDesired, uint fuLoad);
[DllImport("gdi32.dll")]
public static extern int DeleteObject(int hObject);

How do I perform File IO operations?

This application shows the attribute for files. This means we need to do some File IO operations. The .NET Framework provides a File Object for IO operations. We can create a File object by providing a file name as the parameter to constructor.

File myFile = new File(wndFileName.Text);

Then we can make use of the Attributes property of the File Object to get the attributes of file. The attributes of the File are defined as a FileSystemAttributes enumeration object. For all the available enum values look in the documentation.

FileSystemAttributes attribs = myFile.Attributes;

After that, we can do logical operations on the Attributes value to check if a particular file attribute is set or not. For example, to see if a file is of Archive type or not, the following code can be used.

if ((attribs & FileSystemAttributes.Archive) == FileSystemAttributes.Archive)
{
   wndArchiveCheck.Checked = true;
}

One thing that needs to be noticed is that the result of a logical ‘&’ operation on an Enumeration is an Enumeration. It is not a Boolean value. Therefore the resultant value is being compared against an enum value. There is one more gotcha in this operation. If you do not put the logical operation, (attribs & FileSystemAttributes.Archive), in bracket, the compiler will throw an error. Right now I do not know if it is a bug in the compiler or if that is the way it is intended, but for now put the logical operations in brackets.

To get file's creation date, use the CreateDate property of the File object. This will return a result in a DateObject. And then you can use the Format method of the DateTime object to get the string representation of the file's creation date. Check the online documentation for the DateTime object to see what are the available format values.

DateTime timeFile = myFile.CreationTime;
wndCreateTime.Text = timeFile.Format ("F", DateTimeFormatInfo.InvariantInfo);

Can I include my own resources in the application?

Yes, you can. Use Visual Studio to generate a resource script file (.RC file). Add the resources you want to it. In this sample application, I have added an icon and a bitmap to the resource file. Then use the command line RC compiler. This will generate a .RES file. For example in this application, WinFileInfo.rc file generates WinFileInfo.res file. Then, using the /win32res compiler option the resources can be embedded in the application. One file that has to be copied into the folder is afxres.h. Otherwise the RC file will not compile.

Can I associate a specific icon to the application?

Yes, it too can be done. There are two ways to accomplish this. One is to use the /win32icon compiler option and specifying the icon's file name. The disadvantage of this approach is that you cannot embed resources in the application using the /win32res compiler option. The other approach is adding the icon in the resource file and then making sure that it has the lowest ID. You can then embed the resource file using the /win32res compiler option. This way you will see your icon associated to the application in an explorer window.

How do I compile the application?

I have used a makefile that is provided with the .NET SDK. I had to make changes in master.mak and makefile so that it will compile only my application, not the whole bunch of sample applications. But I did some extra stuff in the makefile to add some extra information to the output file. Here is how the makefile looks.

!include master.mak

_IMPORTS=$(_IMPORTS) /r:System.WinForms.DLL/r:System.DLL 
                     /r:Microsoft.Win32.Interop.DLL 
                     /r:System.Drawing.DLL /r:System.Net.DLL

_WIN32RES=$(_WIN32RES) /win32res:WinFileInfo.res
#_WIN32ICON=$(_WIN32ICON) /win32icon:FormIcon.ico
_XMLDOC=$(_XMLDOC) /doc:WinFileInfo.xml

all: WinFileInfo.exe

WinFileInfo.exe: WinFileInfo.cs

You must be wondering what that _XMLDOC is. This is a very interesting feature of the C# compiler. This helps you create documentation for the methods of your class. But you have to follow very specific rules for tags and where to place them. I have done this for a couple of methods in this application. You can look for more details in the online documentation. The following code shows how XML documentation is being generated for the method ButtonClose_Click.

///<summary>

///ButtonClose_Click Method:

///<para>

///This method is invoked when Close button on the dialog box is clicked.

///This method closes the application.

///</para>

///</summary>

Last Thought

This is just a very simple Windows Form application. This should give you a starting point to build upon. I am not an expert on C# or Forms application. I am learning too so I thought I will share the experience with you guys. Please do send your comments and suggestions to me. I will try to improve this application and add some more advanced features.

Updating to the final release of .NET

The latest version is now RTM compliant. Here is a brief discussion of the changes.

Some changes in referencing system assemblies during compilation

The application needs to refer to some system assemblies like System.DLL, System.Windows.Forms.DLL, etc. Earlier we had to specify all these assembly references through /reference switch. But now C# compiler looks for CSC.rsp response file in the project directory. If the response file is not found in the project directory, then it looks for the file in the directory from where compiler was invoked. Since we are assuming that you don't have IDE installed, then this compiler will be invoked from "Windows Folder"\Microsoft.NET\"CLR Version" directory. You will find a CSC.rsp file there. Take a look at this file. You will see that it already has added reference to most commonly referenced assemblies. Therefore you don't need to specify them through /reference switch anymore.

If you want compiler to ignore the inclusion of default CSC.rsp file, use /noconfig compilation switch. If you include your own CSC.rsp file in the project folder, then its settings override the settings specified in global CSC.rsp file. For more details, please look in the documentation for this compiler switch. Unfortunately you cannot specify noconfig switch in Visual Studio .Net IDE.

Other changes

There are namespace changes, attribute name and value changes and some method name changes in the new code from the previous version that was written for Beta1. Other than that I did not have to make a whole lot of changes.

What Next?

Next we will try to write an article that will show how an ASP.Net application can be written without the help of IDE. and it will show how ASP.Net references the assemblies at compile time and run time.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here