Working with Device Contexts in MFC

If you are new to MFC and interested in graphic operations, you probably need a structured tutorial to teach you how do to at least basic operations. This article, although not a complete MFC graphics tutorial, is intended to provide you with the core information to allow you to do (at least) simple painting operations.

Device Contexts

Any window has an associated device context that is used for painting. Such a device context is an object that on one hand defines a set of other graphic objects, together with their attributes; and on the other hand, defines the graphic modes that affect the output. The set of graphic objects that I mentioned include:

  • a pen: Used to draw lines
  • a brush: Used to paint and fill
  • a bitmap: Used to copy or scroll parts of the screen
  • a font: Used to draw text
  • a palette: Used to define the set of available colors
  • a region: Used for clipping and other operations
  • a path: Used for painting and drawing operations

You can think of this device context as a physical canvas on which you draw lines, shapes, or you write text. This “canvas” can hold one object of a type at a time. If you want to draw a line, you use the pen you want (solid red). If you want to draw a circle, you need a brush; select it before you draw the circle. Until a new selection is made, the last selected object (pen, brush, bitmap, font, and so forth) remains valid and all consecutive operations requiring an object of that type use it. Because of that, you should always use them like this:

  1. Select the object you need for the current operation and save the old selected object.
  2. Perform the operation.
  3. Select back the old object.

MFC provides a class called CDC that encapsulates a HDC, which is a handle to a Windows device context object. All operations with a device context should be made through such such a CDC object. This class provides functions for selecting objects, drawing lines, shapes (ellipses, polygons, rectangles), setting drawing attributes, working with regions, clipping, drawing texts, and so on.

In addition, MFC also provides several specialized classes, derived from CDC for handling device contexts:

  • CPaintDC: Handles the calls to BeginPaint() (in constructor) and EndPaint() (in destructor); when you handle the WM_PAINT message and need to paint a window, you have to call BeginPaint() to prepare the window for painting and filling a structure with information about the painting, and EndPaint() when painting is done. Basically, you need to do this:

    void CSomeWindow::OnPaint()
    {
       PAINTSTRUCT ps;
       CDC* pDC = BeginPaint(&ps);
    
       // do the painting with pDC
    
       EndPaint(&ps);
    }
    

    With CPaintDC, all you have to do is this:

    void CSomeWindow::OnPaint()
    {
       CPaintDC dc(this);
    
       // do the painting with dc
    }
    
  • CClientDC: Handles the device context associated with the client area of a window, by calling GetDC() in the constructor and ReleaseDC() in the destructor. If you want to draw in the client area, you have to call those functions like this:

    void CSomeWindow::DrawClient()
    {
       // acquire the device context associated with the
       // client area
       CDC* pDC = GetDC();
    
       // draw on the client area
    
       // release the client area
       ReleaseDC(pDC);
    }
    

    You must make sure to call ReleaseDC() for each call to GetDC(). To simplify the operations, you can use CClientDC:

    void CSomeWindow::DrawClient()
    {
       CClientDC dc(this);
    
       // draw on the client area
    }
    
  • CWindowDC: Manages a display context associated with an entire window, including its frame and controls. It calls GetWindowDC() in the constructor (to retreive a device context for the entire window) and ReleaseDC() in the destructor.

  • CMetaFileDC: Associates a device context with a metafile.

In this tutorial, you will use only CPaintDC.

Graphic Objects

MFC also provides a hierarchy of GDI (graphical device interface) objects: bitmaps, palletes, brushes, pens, regions, and fonts. CGdiObject, an abstract class, is the base of this hierarchy. It encapsulates a HANDLE that contains an attached object of type HBITMAP, HPALETTE, HBRUSH, HPEN, HRGN, or HFONT. The classes derived from this base class are:

  • CBitmap: Manipulates bitmaps
  • CPallete: Encapsulates a Windows pallete
  • CBrush: Encapsulates a brush; used for painting and filling
  • CPen: Encapsulates a pen; used for drawing lines
  • CRgn: Encapsulates a region (elliptical or polygonal area within a window); used for clipping
  • CFont: Encapsulates a font; used for drawing text

In the following pages, you will see how to use pens, brushes, bitmaps, and fonts to draw lines, shapes, images, or text.

More by Author

Must Read