In addition to displaying text, most Windows applications make extensive use of graphics to present information visually. The Windows Graphics Device Interface (GDI) provides a comprehensive set of drawing functions that enable applications to render lines, curves, geometric shapes, bitmaps, icons and other graphical objects on the screen, printer or other output devices.
The GDI drawing functions operate using simple geometric primitives. More complex illustrations can be created by combining these primitives, allowing applications to construct everything from simple diagrams and charts to sophisticated user interfaces.
The appearance of graphical objects is determined by the current drawing attributes selected into the device context. In particular, pens define the colour, style and thickness of outlines, while brushes determine the colour and pattern used to fill enclosed shapes. Applications may also select fonts, bitmaps and other graphical objects to customise the appearance of their output.
As with text output, graphical drawing should normally be performed while processing the WM_PAINT message. This ensures that the application's graphical output is automatically restored whenever the window requires repainting.
Windows provides a wide range of graphics functions. Some of the most commonly used functions are described below.
Drawing Pixels
A pixel is the smallest image element that can be represented on screen. To draw a point within the client area of a window, use the API function SetPixel().
COLORREF SetPixel(HDC hdc, int x, int y, COLORREF color);
Where:
- hdc – The device context.
- x – The x-coordinate, in logical units, of the point to be set.
- y – The y-coordinate, in logical units, of the point to be set.
- color – A
COLORREFvalue specifying the colour used to paint the point.
If the specified colour cannot be created on the video display, Windows uses the nearest pure, non-dithered colour and returns that value from the function.
If the function succeeds, the return value is the RGB colour that was actually used. If the function fails, the return value is -1.
Drawing Lines
The LineTo() function draws a line from the current graphics position to a specified endpoint.
BOOL LineTo(HDC hdc, int x, int y);
Where:
- hdc – The device context.
- x – The x-coordinate of the line's ending point.
- y – The y-coordinate of the line's ending point.
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
After the operation, the current drawing position becomes the endpoint of the line.
MoveToEx
The initial starting position for graphics output is normally the logical coordinate position (0,0). The MoveToEx() function is a Win32 GDI function used to set the current drawing position in a device context.
BOOL MoveToEx(HDC hdc, int x, int y, LPPOINT lppt);
Where:
- hdc – A handle to a device context.
- x – The x-coordinate of the new position, in logical units.
- y – The y-coordinate of the new position, in logical units.
- lppt – A pointer to a
POINTstructure that receives the previous current position.
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
For example:
MoveToEx(hdc, 50, 50, NULL);
LineTo(hdc, 200, 100);
This moves the current drawing position to (50,50) and then draws a line to (200,100).
GetCurrentPosition
The GetCurrentPositionEx() function retrieves the current logical graphics position.
BOOL GetCurrentPositionEx(HDC hdc, LPPOINT lppt);
Where:
- hdc – A handle to the device context.
- lppt – A pointer to a
POINTstructure that receives the logical coordinates of the current position.
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
For example:
POINT pt;
GetCurrentPositionEx(hdc, &pt);
After the call, pt.x and pt.y contain the current drawing coordinates.
Drawing Rectangles
The simplest function for drawing rectangles is Rectangle(). It draws a rectangle using the current pen for the outline and the current brush for the interior.
BOOL Rectangle(
HDC hdc,
int left,
int top,
int right,
int bottom
);
Where:
- hdc – A handle to the device context.
- left – The x-coordinate of the upper-left corner.
- top – The y-coordinate of the upper-left corner.
- right – The x-coordinate of the lower-right corner.
- bottom – The y-coordinate of the lower-right corner.
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
RoundRect()
To display rectangles with rounded corners, use the RoundRect() function.
BOOL RoundRect(
HDC hdc,
int left,
int top,
int right,
int bottom,
int width,
int height
);
Where:
- hdc – A handle to the device context.
- left – The x-coordinate of the upper-left corner.
- top – The y-coordinate of the upper-left corner.
- right – The x-coordinate of the lower-right corner.
- bottom – The y-coordinate of the lower-right corner.
- width – The width of the ellipse used to create the rounded corners.
- height – The height of the ellipse used to create the rounded corners.
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
Drawing an Ellipse
To draw an ellipse or circle using the current pen and fill it using the current brush, use the Ellipse() function.
BOOL Ellipse(
HDC hdc,
int left,
int top,
int right,
int bottom
);
Where:
- hdc – A handle to the device context.
- left – The x-coordinate of the upper-left corner of the bounding rectangle.
- top – The y-coordinate of the upper-left corner of the bounding rectangle.
- right – The x-coordinate of the lower-right corner of the bounding rectangle.
- bottom – The y-coordinate of the lower-right corner of the bounding rectangle.
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
To draw a circle, the bounding rectangle must be square. For example, a circle can be drawn using:
Ellipse(hdc, 10, 10, 50, 50);
The dimensions of the bounding rectangle determine the size and position of the circle.
Drawing a Semi-Circular Wedge
To draw a semi-circular wedge using the current pen and fill it with the current brush, use the Pie() function.
BOOL Pie(
HDC hdc,
int left,
int top,
int right,
int bottom,
int xr1,
int yr1,
int xr2,
int yr2
);
Where:
- hdc – A handle to the device context.
- left – The x-coordinate of the upper-left corner of the bounding rectangle.
- top – The y-coordinate of the upper-left corner of the bounding rectangle.
- right – The x-coordinate of the lower-right corner of the bounding rectangle.
- bottom – The y-coordinate of the lower-right corner of the bounding rectangle.
- xr1 – The x-coordinate of the endpoint of the first radial.
- yr1 – The y-coordinate of the endpoint of the first radial.
- xr2 – The x-coordinate of the endpoint of the second radial.
- yr2 – The y-coordinate of the endpoint of the second radial.
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
Drawing a Chord
A chord is a region bounded by an elliptical arc and the straight line joining the arc's start and end points.
To draw a chord using the current pen and fill it using the current brush, use the Chord() function.
BOOL Chord(
HDC hdc,
int x1,
int y1,
int x2,
int y2,
int x3,
int y3,
int x4,
int y4
);
Where:
- x1 – The x-coordinate of the upper-left corner of the bounding rectangle.
- y1 – The y-coordinate of the upper-left corner of the bounding rectangle.
- x2 – The x-coordinate of the lower-right corner of the bounding rectangle.
- y2 – The y-coordinate of the lower-right corner of the bounding rectangle.
- x3 – The x-coordinate of the endpoint of the radial defining the beginning of the chord.
- y3 – The y-coordinate of the endpoint of the radial defining the beginning of the chord.
- x4 – The x-coordinate of the endpoint of the radial defining the end of the chord.
- y4 – The y-coordinate of the endpoint of the radial defining the end of the chord.
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
Drawing Polygons
The Polygon() function draws a closed shape made from multiple connected lines. The interior of the shape is filled using the current brush, while the border is drawn using the current pen.
Unlike Polyline(), Polygon() automatically closes the shape by drawing a line from the final point back to the first point.
BOOL Polygon(
HDC hdc,
const POINT *apt,
int cpt
);
Where:
- hdc – A handle to the device context.
- apt – A pointer to an array of
POINTstructures specifying the vertices of the polygon. - cpt – The number of vertices in the array.
The value of cpt must be greater than or equal to 2.
For example:
POINT points[] = {
{50, 20},
{100, 80},
{20, 80}
};
Polygon(hdc, points, 3);
This example creates a simple triangular polygon.
Bézier Curves
A Bézier curve is a smooth mathematical curve defined by a set of control points. Rather than specifying every point on the curve, the programmer specifies a small number of points. Windows then calculates the smooth curve using the start point, end point and intermediate control points.
The PolyBezier() function draws one or more Bézier curves.
BOOL PolyBezier(
HDC hdc,
const POINT *apt,
DWORD cpt
);
Where:
- hdc – A handle to the device context.
- apt – A pointer to an array of
POINTstructures containing the endpoints and control points of the curves. - cpt – The number of points in the array.
The number of points must be one more than three times the number of curves to be drawn. For example, a single Bézier curve requires four points, while two connected curves require seven points.
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
Example
The following example builds on the basic Windows application to demonstrate several of the GDI graphics functions described above.
