![]() |
Languages »
C# »
Beginners
Beginner
Writing a Windows Form Application For .NET Framework Using C#By SoftomatixA tutorial on writing Windows Forms application using C# |
C#, VC7, Windows, .NET 1.0, Visual Studio, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||

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.
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.
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
};
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.
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);
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);
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);
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.
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.
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>
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.
The latest version is now RTM compliant. Here is a brief discussion of the changes.
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.
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.
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.
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 20 Apr 2002 Editor: Chris Maunder |
Copyright 2000 by Softomatix Everything else Copyright © CodeProject, 1999-2009 Web20 | Advertise on the Code Project |