In MFC, the CDC class wraps the Windows device context and the associated GDI member functions for working with the current display into one package. The windows graphics system uses pens and brushes to set the appearance of graphics objects and provides several hundred functions for creating the points, lines, shapes and bitmaps associated with a graphical output. Pens define the style, thickness and colour of the pixels drawn, while a brush determines the fill colour of shapes. When windows creates its first display device context, it comes with a limited number of pens, brushes, fonts and palettes known as stock objects.
If the application requires a change to the device context such as new pen, then this new pen must be created and selected into the device context. Selecting a new graphics object does change any pre-existing display elements but only any new graphic output.
Creating Custom Pens
The default pen draws solid black lines that are 1 pixel wide. The CDC member function CreatePen() deals with the creation of custom pens. The prototype of this function is
BOOL CreatePen( int nPenStyle, int nWidth, COLORREF crColor );
Where.
nPenStyle -can be any one of the following values: PS_SOLID, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL, PS_INSIDEFRAME,
nWidth - Specifies the width of the pen
crColor - Contains an RGB color for the pen. If the function succeeds, the return value is a handle that identifies a logical pen. If the function fails, the return value is NULL.
For further reading https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createpen
Create Custom Brushes
Brushes are used to fill in any closed objects. They have colour, style and can be bitmaps. The CBrush class encapsulates GDI brushes and supplies various member functions to deal with the creation of custom brushes. The prototype for the CreateSolidBrush() function is
BOOL CreateSolidBrush(COLORREF crColor);
where
crColor is a COLORREF structure that specifies the RGB color of the brush. Returns Nonzero if successful; otherwise 0.
For further reading on brush creation https://docs.microsoft.com/en-us/cpp/mfc/reference/cbrush-class?view=vs-2019
Selecting Objects
Before any graphics object can be used it must be ‘selected’ into the current device context (DC) using the CDC member function SelectObject(). The new object will then replace the previous graphic object of the same type. The prototype of the SelectObject function for both a Pen() and a Brush() is
CPen* SelectObject(CPen* pPen);
CBrush* SelectObject(CBrush* pBrush);
Where
pPen - A pointer to a CPen object to be selected.
pBrush - A pointer to a CBrush object to be selected.
SelectObject will return a pointer to the previous graphics objects which may be useful should the application need to use the previous selection
For further reading https://docs.microsoft.com/en-us/cpp/mfc/reference/cdc-class?view=vs-2019#selectobject
Using Stock Objects
When a window creates its first display device context, it comes with a limited number of pre-created graphics objects known as stock objects for changing the display output. These stock objects consist of pens, brushes, fonts, and palettes. The CDC member function SelectStockObject() retrieves a handle to one of these stock objects. The prototype of this function
virtual CGdiObject* SelectStockObject(int nIndex);
Where the parameter nIndex can be one of the following values: BLACK_BRUSH, DKGRAY_BRUSH ,DC_BRUSH ,GRAY_BRUSH ,HOLLOW_BRUSH ,LTGRAY_BRUSH ,NULL_BRUSH ,WHITE_BRUSH ,BLACK_PEN ,DC_PEN ,NULL_PEN ,WHITE_PEN, ANSI_FIXED_FONT ,ANSI_VAR_FONT ,DEVICE_DEFAULT_FONT ,DEFAULT_GUI_FONT ,OEM_FIXED_FONT ,SYSTEM_FONT ,SYSTEM_FIXED_FONT , DEFAULT_PALETTE
If the function succeeds, the return value is a handle to the requested logical object. If the function fails, the return value is NULL
To select a stocking object such as BLACK_PEN into the current device context
SelectObject(GetStockObject(BLACK_PEN));
Since stock objects are pre-created system resources there is no need to delete the object handle once they are no longer required.
For further reading on stock objects https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getstockobject
SaveDC and RestoreDC.
Each time an application requests a device context its attributes are reset to the system default and the default pen and brush will be used. In order to avoid this reinitialisation, the current device context state can be saved and restored with the CDC member functions SaveDC() and RestoreDC().
Deleting GDI Objects
Customs pens and brushes, like other objects created from GDI Object classes are resources that consume space in memory. It is therefore important that they are deleted when no longer required. If a GDI object is created on the stack it will automatically be deleted when it goes out of scope. If however a GDI object is created on the heap it must be explicitly deleted by a call to the object member function DeleteObject(). Stock objects, even if they are “created” with CreateStockObject never need to be deleted. Failure to delete GDI objects leads to "memory leak" and gradual depletion of available system memory.
Dealing with Colour Values
The Windows graphics system normally uses the RGB color model to specify colour values. Each possible color is defined by red, green, and blue parameters using values from 0 through 255 with a higher value representing a brighter colour. The COLORREF type is part of the Windows API that uses a single 32-bit value to specify an RGB color. The GDI contains several macros to combine RGB values into a single 32 big value and to turn a COLORREF data into its RGB components -
//converts rgb to colourref value
COLORREF RGB(BYTE byRed, BYTE byGreen, BYTE byBlue);
//converts colourref value to RGB equivalent
int iRed= GetRValue(COLORREF rgb);
int iGreen =GetGValue(COLORREF rgb);
int iBlue =BYTE GetBValue(COLORREF rgb);
A full description of all the CDC member functions covering graphics output can be found at the following- https://docs.microsoft.com/en-us/cpp/mfc/reference/cdc-class?view=vs-2019