MFC Graphics and Drawing

This section provides comprehensive guidance on leveraging the Microsoft Foundation Classes (MFC) for graphics and drawing operations within your Windows applications. MFC offers a powerful abstraction layer over the Windows GDI (Graphics Device Interface), simplifying the process of creating visual elements, manipulating images, and rendering complex graphics.

Understanding the Device Context (DC)

The cornerstone of graphics programming in Windows and MFC is the Device Context (DC). A DC is a structure that contains information about the drawing attributes of a device, such as the screen or a printer. In MFC, the CDC class represents a device context.

Key aspects of the DC include:

Working with CDC Objects

You'll typically obtain a CDC object within the OnDraw method of your view class or when handling a WM_PAINT message. For temporary drawing operations, you can create CPaintDC or CClientDC objects.


void CMyView::OnDraw(CDC* pDC)
{
    // Get the client area rectangle
    CRect rectClient;
    GetClientRect(&rectClient);

    // Set a pen for drawing lines
    CPen pen(PS_SOLID, 2, RGB(255, 0, 0)); // 2-pixel wide solid red pen
    CPen* pOldPen = pDC->SelectObject(&pen);

    // Draw a line from (10, 10) to (100, 100)
    pDC->MoveTo(10, 10);
    pDC->LineTo(100, 100);

    // Set a brush for filling shapes
    CBrush brush(RGB(0, 255, 0)); // Green brush
    CBrush* pOldBrush = pDC->SelectObject(&brush);

    // Draw a rectangle
    pDC->Rectangle(150, 50, 250, 150);

    // Restore the original pen and brush
    pDC->SelectObject(pOldPen);
    pDC->SelectObject(pOldBrush);
}
        

Drawing Primitives

MFC provides member functions in the CDC class for drawing basic shapes:

Text Rendering

Displaying text is a common requirement. MFC's CDC class offers functions to draw text with specified fonts, colors, and alignment.

Working with Fonts

Use the CFont class to create and manage font objects. You can specify font characteristics like face name, height, width, weight, and italic style.


void CMyView::OnDraw(CDC* pDC)
{
    // Create a new font
    CFont font;
    font.CreateFont(
        24,             // nHeight
        0,              // nWidth
        0,              // nEscapement
        0,              // nOrientation
        FW_BOLD,        // nWeight
        FALSE,          // bItalic
        FALSE,          // bUnderline
        0,              // cStrikeOut
        ANSI_CHARSET,   // nCharSet
        OUT_DEFAULT_PRECIS, // nOutPrecision
        CLIP_DEFAULT_PRECIS, // nClipPrecision
        DEFAULT_QUALITY,   // nQuality
        DEFAULT_PITCH | FF_SWISS); // nPitchAndFamily

    CFont* pOldFont = pDC->SelectObject(&font);

    pDC->TextOut(50, 200, _T("Hello, MFC Graphics!"));

    pDC->SelectObject(pOldFont); // Restore original font
}
        

Bitmaps and Images

MFC simplifies the process of loading, displaying, and manipulating bitmap images. The CBitmap class is used to represent bitmap data.

For more advanced image manipulation, consider using the GDI+ API available through MFC, which offers object-oriented graphics capabilities.

GDI Objects and Best Practices

When working with GDI objects like pens, brushes, and fonts, it's crucial to manage their lifecycle correctly. Always select your custom GDI objects into the device context and then select the original object back out before it's destroyed. Failure to do so can lead to resource leaks.


// Correct way to use a GDI object
CPen myPen;
myPen.CreatePen(PS_SOLID, 1, RGB(0,0,255));
CPen* pOldPen = pDC->SelectObject(&myPen);

// ... draw with myPen ...

pDC->SelectObject(pOldPen); // Always restore
// myPen is automatically destroyed when it goes out of scope
        

Never delete a GDI object that has been selected into a CDC. Always restore the previous object first.

Further Reading