This article explains how to:
- Display .NET framework supported image types (JPG, JPEG, GIF, PNG, TIF...) into a form.
In addition, the code covers:
- Accessing the Registry (creating, writing, retrieving registry key values).
- Using WinForm controls like StatusBar, ToolBar, MainMenu, ImageList, Timer and, OpenFileDialog.
- Processing command-line arguments.
- To obtain the list of files in a directory.
- To create a Windows Application setup project
You always need to access images for some reason or the other. When you have the .NET framework SDK with you, you needn't bother to buy other applications for that job - develop one for yourself! With the supremely rich .NET framework, manipulating images is very simple. This article places emphasis only on how to display images. The code on the other hand, involves a lot of other stuff including a setup, which were used to implement a number of standard features seen in popular applications. They are quite straight forward; so you could understand them by yourself.
Apart from the usual set, this application uses the following namespaces too:
System.Drawing - For displaying images
System.Drawing.Drawing2D - For displaying images
Microsoft.Win32 - For accessing the registry
The code explained
To load images (technically 'draw'), you use any one of the 30 overloads of:
As is evident,
DrawImage() is a method of the
Graphics class. So, before using
DrawImage() straightaway, you need to create a
Graphics object. This
Graphics object would be of the form you are going to draw the image onto. Typically, you create this object in the Paint Handler of the form. An example for a Paint Handler is:
private void MainForm_Paint(object sender,
When someone calls a form's paint handler, some data regarding the form's graphics stuff is passed to it. This data is held in the
object, in this case, the object e. This object has a property
- and that's exactly what we want. You just use it to initialize your own
object, like this:
Graphics g = e.Graphics;
So, now that you have a
Graphics object, you could call the
DrawImage() method. But wait, what about the arguments? That's what we are going to see. The overload I will discuss here is:
public void DrawImage(
This method draws the specified
Image object (
System.Drawing.Image), at the specified location and with the specified size (passed implicitly through the
RectangleF object - rect). An
Image object holds the actual image data that is to be drawn. And with little thinking, you could easily understand that with a
RectangleF object you could define both the size and position of the image.
So how do we develop these arguments?
System.Drawing.Image is an abstract class, designed to act as the base for
System.Drawing.Imaging.Metafile. What we are interested in is
System.Drawing.Bitmap. We create an
Image object using the
Bitmap class, like this:
MyBitmap = new Bitmap(...);
There are 12 overloads for the
constructor. The one I will discuss here is:
You just need to pass the path to the image file you want to load. And then, you have the initialized
Image object. What remains is the
RectangleF object which you could initialize as you wish. Once done, call the
DrawImage() method, and there you are, you have done it!
An example code listing for the actions discussed above:
private void MainForm_Paint(object sender,
Graphics g = e.Graphics;
MyBitmap = new Bitmap("c:\\image.bmp");
g.DrawImage( MyBitmap, new RectangleF(MyPoint.X, MyPoint.Y,
MyBitmap.Width*(fScale), MyBitmap.Height*(fScale)) );
Code for the additional features
This section discusses the way the rest of the application is designed. Since an exhaustive explanation would be beyond the scope of this article, I would only give you a brief description of the regions used. Read the code, read this description; and you would understand (hopefully). Here goes:
My Vars Declaration region declares all the variables that are used. These variables are sub-divided according to their functionality. Some of these are initialized to their default values in the declaration itself.
App Main Entry region encapsulates the application
Main function as well as the main form constructors. When the app is executed, the
Main function determines whether there are any command-line arguments [file to be displayed], and invokes the required overloaded main form constructor, passing the argument if necessary. The main form constructor, would then set the current directory to that of the argument in case there exists one. It also sets the
szRequestedFile variable to the argument value.
Main Form Load region consists of the main form load function, which calls the
GetRegistrySettings function to retrieve values from the current user's registry, makes sure that the timer is not on, initializes the
FileTypes ArrayList, sets all the from controls to the registry values by calling the
SetControlsToRegistrySettings function, processes the current folder by calling the
ProcessDirectory function, and displays the image if necessary in either the normal mode or the slide show mode.
Main Form Paint Handler region comprises of the most complicated and used function in the app - the paint function. This function starts by setting the status bar text to
Working..., proceeds to initialize a
Graphics object, sees whether the 'size to fit' option is true or false, determines the position where the image is to displayed, draws it, and finally sets the status bar text to
Main Form Paint Handler region consists of a number of functions designed for different activities.
GetRegistrySettings gets the current user's registry settings from the registry and initializes the registry variables.
SetControlsToRegistrySettings resets the form controls so as to set it to the current user's settings.
SetSize resizes the form according to the current Image's size.
ProcessDirectory finds out all the images within the current folder and initializes
GetFilePath get's the currently selected file's path from
SetPicture sets variables to the selected file's attributes and invokes the paint handler.
EventHandlers region consists of handlers for the menu events, toolbar events, mouse move event, form resize event as well as the timer elapsed event. Each of these events call the
DoAction function to carry out the required function if appropriate.
DoAction function lies within the
Do Action Handler region. This function incorporates all the possible actions that would be invoked within this app. This function was developed in order to reduce redundant code that would have to be coded for both the toolbar as well as the main menu. Plus this model reduces complexity.
For the experimentalist: in case you ever want to add more features, follow these simple steps:
- In the
My Vars Declaration region, add the required variables in the specific section. This is to make matters organized.
- Expand the
Do Action Handler region. Within the list of existing cases, add a new one defining the action to be carried out.
- When an event occurs where the new action is to be executed, call
DoAction passing the name of the action just defined.
This is a very simple application with a simple design and simple architecture. But it works! And that's exactly what we want.