We have already mentioned the first and
major difference between the two versions: Whereas GDI+ exposes its
functionality as both managed and unmanaged classes (through the System.Drawing
namespace), GDI is unmanaged only. Beside this major difference, some of the
important changes in GDI+ are as follows:
- No handles or device contexts
- Object-oriented approach
- Graphics object independence
- Methods overloading
- Separate methods for draw and fill
- Regions and their styles
Elimination of Handles and Device Contexts
As a GDI programmer, you must be familiar
with the device context. A device context is a structure that stores information
about a particular display device, such as a printer or monitor. This structure
specifies how the graphics objects will be drawn on the output device. The
device context also stores information about the properties of graphics objects,
such as the quality of rendering and so on. To draw an object on a device, first
an application needs to get a handle to the device context (HDC), which is used
by GDI to send information to the device.
In GDI+, the concept of device context and handle to the device context is
replaced by the Graphics object. The Graphics class provides methods and
properties to draw various graphics objects; these methods and properties are
very easy to use compared to the earlier device context-based programming model.
Suppose that you need to draw a line from point (20,20) to point (200,200). In
GDI, first an application creates and HDC using the BeginPaint function, which
takes a window handle and a PAINTSTRUCT structure. Alternatively, you can call
the GetDC function. To draw a line the application must create a pen object and
draw a line using this pen. An application can obtain a pen object by making a
call to the CreatePen function, which returns a handle to the pen.
Before starting to draw, the application needs to call the SelectObject
function, which takes the device context and pen handle as arguments. Now the
application can draw any graphics object. The application calls the EndPaint
function to end the drawing process. For example, the code snippet in Listing
1.1 draws a line using the MoveToEx and LineTo Functions.
LISTING : C++ code to draw a line
LRESULT APIENTRY MainWndProc (HWND hwnd, UINT message, WPARAM, wParam, LPARAM
1Param)
{
PAINTSTRUCT ps;
Switch (message)
{
case WM-PAINT:
HDC handle;
PAINTSTRUCT pstruct;
HPEN Pen;
handle=BeginPaint (hWnd, &pstruct);
hpen=CreatePen (PS_SOLID, 5,
RGB (255,255,0));
SelectObject (handle, hPen);
MoveToEx (handle,20,20,NULL);
LineTo (handle, 200,200);
EndPaint (hWnd, &pstruct);
}
}
Now let's see the same example in GDI+: First you need a Graphics object
associated with a form, which is usually available on the form's Form_Paint
event or OnPaint method. Once you've got the Graphics object associated with a
form, you can call its draw and fill methods to draw and fill various graphics
objects, such as lines, rectangles, and curves. For example, the code written in
Listing 1.2 is the form's paint method. As this code shows, first we get a
Graphics object associated with the form by using PaintEventArgs. Graphics.
After that we create a Pen object and pass it as an argument to the DrawLine
method. The DrawLine method takes a Pen object and the starting and ending
points of a line, and draws a line on the form. Notice also in Listing 1.2 that
there is no MoveTo call.
LISTING: GDI+ code in VB to draw a line
Private
Sub Form1_Paint(ByVal
sender As
Object,
ByVal e
As
System.Windows.Forms.PaintEventArgs)
Dim g
As Graphics = e.Graphics
Dim pn
As
New Pen(Color.Red, 3)
g.DrawLine(pn, 20, 20, 200, 200)
End
Sub
Object-Oriented Approach
If you compare Listing 1.1 and 1.2, it's easy to see that the GDI+ model is more
flexible, easier to use, and more object-oriented. GDI provides functions to
draw graphics objects; GDI+ provides objects. Each graphics primitive is an
object. For example, in GDI+, a pen is represented by a Pen object, as opposed
to the HPEN structure in GDI.
Graphics Object Independence
In GDI, first you select a brush, path, image, or font and pass this object a
device context. Then you use the device context handle to draw a graphics
object, which means all the objects drawn using that device context will have
the same effects.
Unlike GDI, GDI+ provides an object-independent model, which means that pens,
brushes, images, or fonts can be created and used independently and can be
changed at any time. In addition, an application can even use different pens to
draw different graphics objects on the same form, which is not true in the case
of a device context.
Method Overloading
GDI+ methods provide many overloaded forms to provide more flexibility to
developers. For example, the DrawRectangle method has three overloaded forms:
Public
Sub
DrawRectangle(pen
As
Pen, rect
As
Rectangle)
Public
Sub
DrawRectangle(pen
As
Pen, x
As
Integer,
y As
Integer,
width
As
Integer,
height
As
Integer)
Public
Sub
DrawRectangle(pen
As
Pen, x
As
Single,
y As
Single,
width
As
Single,
height
As
Single)
These forms allow developers to draw a rectangle from a rectangle object, four
integer values, or floating point values. The DrawRectangle method draws a
rectangle specified by a coordinate pair, a width, and a height. The DrawImage
method, used to draw images, has no fewer than 30 overloaded forms.
Draw and Fill Methods
Drawing and filling are analogous to writing and painting. When you write, you
use a pen to "draw" symbols made up of lines and curves. Painting means you take
a brush, dip it into a color, and fill in areas with the color.
In GDI, both actions (fill and draw) are done in one step. For example, consider
drawing and filling a rectangle. First an application creates a pen and a brush
and calls SelectObject to select that pen and brush. Then the application calls
the Rectangle method, which draws and fills the rectangle. Listing 1.3 shows a
code snippet that draws and fills a rectangle.
LISTING: GDI code to draw and fill a rectangle
hBrush = CreateHatchBrush(HS_CROSS, RGB(255, 0, 0));
hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
SelectObject(HDC, hBrush);
SelectObject(hdc, hpen);
Rectangle(hdc, 20, 20, 200, 200);
In GDI+, the Graphics class provides separate draw and fill methods. Fox
example, the DrawRectangle method takes a Pen object and draws an outline of a
rectangle, and the FillRectangle method takes a Brush object and fills the
rectangle with the specified brush, as Listing 1.4 shows.
LISTING: GDI+ code to draw and fill a rectangle
Dim
g As Graphics = e.Graphics
Dim pn As
New Pen(Color.Red, 3)
Dim htchBrush
As New
HatchBrush(HatchStyle.Cross, Color.Red, Color.Blue)
g.DrawRectangle(pn, 50, 50, 100, 100)
g.FillRectangle(htchBrush, 20, 20, 200, 200)
Regions and Their Styles
Regions are another area where a GDI developer may find minor changes in GDI+.
GDI+ provides several functions for creating elliptical, round and polygonal
regions. As a GDI programmer, you are probably familiar with the CreatRectRgn,
CreateEllipticRgn, CreateRoundRectRgn, CreatPolygonRgn, and CreatePolyPolygonRgn
functions.
In GDI+, the Region class represents a region. The Region class constructor
takes an argument of type GraphicsPath, which can have a polygon, a circle, or
an ellipse to create a polygonal, round, or elliptical region, respectively.
Conclusion
Hope this article would have helped you in
understanding GDI+ from a GDI Perspective. See my other articles on the website
on GDI+ which are in continuation of this article.