2007-05-17
| Table of Contents: |
| Rate This Article: | Add This Article To: |
( Page 1 of 2 )
In this article on GDI+, C# expert Rick Leinecker shows you how to use the .NET graphics capabilities.
I know a lot of very gifted software developers. Many of them are gurus when performing SQL queries and populating form fields. Many of them produce dazzling graphics output. But it's rare to meet someone who does both. If you're in the first category and find it difficult to draw to your applications, this article will get you started.
I've actually met extremely good programmers who have no idea how to draw to a window. I was in crunch mode several years back and a friend of mine said he'd help. This is a person with a long resume, and you would expect he could do just about anything in the software development realm. The next morning he called. "How do you use a device context?" he asked. At this point I realized that it would take less time to finish the project myself than teach him how to use a device context. I don't think he could have drawn a line across the screen. (As you'll learn later in this article, device contexts have been replaced by Graphics objects in the .NET framework.)
This is the first of a series that teaches how to use GDI+ effectively in .NET applications. While this article starts off with the basics, later articles will show you more advanced topics. I'll take my programming experiences and bring you the topics that I deal with most, or have struggled with the most.
As I'm writing these articles, I welcome your suggestions for what you'd like covered. If I can work your requests in, I will. This way, besides relating my own experiences, I'll be answering questions that incorporate your relevant needs.
The Graphics Class
I need to give you some context before we delve into the Graphics class. I started my programming career writing DOS games. There were very few graphics functions available, mostly some simple primitives in the runtime library such as lines and ellipses.
It was a necessity to write my own graphics library in assembly language. This was the only way to create a game (or any other graphically intensive program) that could draw images and primitives with the kind of speed necessary.
In those days, the code directly modified screen memory. There was a reserved section in memory to which the code wrote. And the memory addresses were different depending on the graphics mode. Not only that, some video modes implemented a system of interleaved scanlines. Not a pretty picture.
The Windows operating system solved this dilemma, and instead of writing straight into memory, programmers could draw to what was called a Device Context (DC). These DCs provided a level of abstraction where the operating system took care of all of the issues related to the video mode, resolution, number of colors, and how to store the data into memory. Instead of thinking in terms of storing bytes, programmers could think in terms of drawing lines and ellipses. This was a welcome change.
When Java was introduced, it continued the metaphor and called the draw surface a canvas instead of a device context. This abstraction makes it even clearer to software developers that they must think in terms of drawing to a surface.
I went to the 2000 PDC in Orlando, Florida where .NET and C# were first publicly announced. One of the sessions I attended covered GDI+, the new version of Windows' Graphical Device Interface (GDI) API. To me, the new Graphics class resembled a hybrid of the old Windows DC and the newer Java canvas metaphors. It further abstracts the programmer from the actual video device. The Graphics class provides practically ever possible method and property for drawing that you'll need.
We'll get started learning how to use the Graphics class by creating a simple Windows C# application named GraphicsClass. Once the application project has been created, we'll go to the form properties, click on the events button (the lightning bolt), and add an OnPaint event handler as shown in the figure below:
The default method that is created contains a sender object (which I have never used in this context) and a PaintEventArgs object. The wizard-created method is shown below:
private void OnPaint(object sender, PaintEventArgs e)
{
}
Drawing a Line
One of the members of the PaintEventArgs object is a Graphics object named Graphics. All methods and properties of this Graphics object can be accessed as e.Graphics.SomeGDIMethodCall(). The following example uses the Graphics object to draw a line that can be seen in the figure that follows:
e.Graphics.DrawLine(new Pen(Color.Black), 0, 0, 250, 250);
In the case of a Windows application, there is actually more to the application than the area in which we draw. This might include the caption bar and a menu. But the Graphics object draws to what's known as the client region (which the Form class represents with a Rectangle object named ClientRectangle). All drawing coordinates are in reference to the client region.
The OnPaint method is fired any time there is a need to draw or redraw the client region. This might happen when the window is restored from a minimized state. It might also happen when another window is moved over your application's window.
Forcing a Redraw
There are times when code in your application will want to trigger the OnPaint method. Many times I draw with variables that contain values that change. When the values change, then the OnPaint method needs to be triggered so that the new values will be reflected. Many times my applications need an updated rendering because of mouse movements. There is an example of this later in this section. The following code forces a redraw by invaliding the window's client region with the Invalidate method, and then calling the Update method.
Invalidate(); Update();
![]() |
|


