Your browser doesn't support JavaScript mfc Archives - Page 2 of 3 - Windows Programming

Scrollbar

The most common scrollbar messages are

SB_LINEUP – is sent when the scrollbar moves up one position
SB_LINEDOWN – is sent when the scrollbar moves down one position
SB_PAGEUP – is sent when the scrollbar is moved up one page
SB_PAGEDOWN – is sent when the scrollbar is moved down one page
SB_LINELEFT – is sent when the scrollbar is moved left one position
SB_LINERIGHT – is sent when the scrollbar is moved right one position
SB_PAGELEFT – is sent when the scrollbar is moved one page left
SB_PAGERIGHT – is sent when the scrollbar is moved one page right
SB_THUMBPOSITION – is sent after the thumbbar is dragged to a new position
SB_THUMBTRACK – is sent while the thumbbar is dragged to a new position

The CScrollbar member function SetScrollRange is used to set the minimum and maximum scroll box positions and the GetScrollPos() and SetScrollPos() member functions retrieves/sets the current position of the scroll box (thumb).

Scrollbar information is passed to the parent windows by use of the ON_WM_VSCROLL and ON_WM_HSCROLL message macros

For further reading on the CScrollBar class
https://docs.microsoft.com/en-us/cpp/mfc/reference/cscrollbar-class?view=vs-2019


The following short program demonstrates a horizontal scrollbar control. The scrollbar position is shown in the static class.

#include <afxwin.h>
#define ID_SCROLLBAR   1000
#define ID_STATIC   1001
class CSimpleApp : public CWinApp
{
public:
BOOL InitInstance();
};

class CMainFrame : public CFrameWnd
{
public:
CMainFrame();
afx_msg void SetLabel(int );
afx_msg void OnHScroll(UINT , UINT nPos, CScrollBar* );
DECLARE_MESSAGE_MAP()
CScrollBar wScrollbar;//instantiate scrollbar
CStatic wStatic;
};


BOOL CSimpleApp::InitInstance(){
m_pMainWnd = new CMainFrame();
m_pMainWnd->ShowWindow(m_nCmdShow);
return TRUE;
}

CMainFrame::CMainFrame()
{
Create(NULL, _T("MFC scrollbar example"), WS_OVERLAPPEDWINDOW ,CRect(25,25,450,170));

wStatic.Create(_T(""),WS_CHILD | WS_VISIBLE | WS_BORDER , CRect(25,60,75,90), this, ID_STATIC);
wScrollbar.Create(WS_CHILD | WS_VISIBLE | SBS_HORZ, CRect(10, 10, 410, 50), this, ID_SCROLLBAR );
wScrollbar.SetScrollRange(1,100,true);//set scroll bar range
int p=wScrollbar.GetScrollPos();
SetLabel(p);
}
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
ON_WM_HSCROLL()
END_MESSAGE_MAP()
CSimpleApp MFCApp1;

//deals with scrollbar scrolling
afx_msg void  CMainFrame::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{

int minpos;
int maxpos;
pScrollBar->GetScrollRange(&minpos, &maxpos); 
int curpos = pScrollBar->GetScrollPos();
switch(nSBCode)
{
case SB_LEFT:         //Scrolls to the lower right. 
curpos = minpos;
break;

case SB_RIGHT:         //Scrolls to the lower right.
curpos = maxpos;
break;

case SB_ENDSCROLL:      //Ends scroll. 
break;

case SB_LINEDOWN:       //Scrolls one line down. 
curpos++;
break;

case SB_LINEUP:         //Scrolls one line up.
curpos--;
break;

case SB_PAGEDOWN:       //Scrolls one page down.
curpos+=5;
break;

case SB_PAGEUP:         //Scrolls one page up. 
curpos-=5;
break;

case SB_THUMBPOSITION:  //The user has dragged the scroll box (thumb) and released the mouse button. The nPos parameter indicates the position of the scroll box at the end of the drag operation. 
curpos = nPos;
break;

case SB_THUMBTRACK:     //The user is dragging the scroll box. This message is sent repeatedly until the user releases the mouse button. The nPos parameter indicates the position that the scroll box has been dragged to. 
curpos = nPos;
break;
}

pScrollBar->SetScrollPos(curpos);
SetLabel(curpos);
}

//display value of scollbar in label
afx_msg void CMainFrame::SetLabel(int newvalue)
{
CString conv;
conv.Format(_T("%d"), newvalue);
wStatic.SetWindowText (_T (conv));
}

Listbox

The following short program creates a listbox and then adds a limited number of selectable items. Clicking any list item results in the selected listview value being copied to the static box. Clicking button adds a new record, clicking the amend button amends the selected listview value and clicking the delete button deletes the selected listview item.

The Clist member functions AddString,DeleteString and GetString are used to set the add, delete and get the selected listbox content and the ON_LBN_SELCHANGE maps the combo box change event to the associated function

For further reading on the CListBox class
https://docs.microsoft.com/en-us/cpp/mfc/reference/clistbox-class?view=vs-2019


#include <afxwin.h>
#define ID_ADDBUTTON   1000
#define ID_DELETEBUTTON   1001
#define ID_AMENDBUTTON   1002
#define ID_STATIC   1003
#define ID_EDIT   1004
#define IDC_LIST1 1005
class CSimpleApp : public CWinApp
{
public:
BOOL InitInstance();
};

class CMainFrame : public CFrameWnd
{
public:
CMainFrame();
afx_msg void wAddButtonOnClick();
afx_msg void wDeleteButtonOnClick();
afx_msg void wAmendButtonOnClick();
afx_msg void wListBoxChange();
DECLARE_MESSAGE_MAP()

//instantiate button class;
CButton wAddButton;
CButton wDeleteButton;
CButton wAmendButton;
//instantiate edit class;
CEdit wEdit;
//instantiate listbox class;
CListBox wListBox;

};

BOOL CSimpleApp::InitInstance()
{
m_pMainWnd = new CMainFrame();
m_pMainWnd->ShowWindow(m_nCmdShow);
return TRUE;
}

CMainFrame::CMainFrame()
{
Create(NULL,TEXT("MFC list box example"), WS_OVERLAPPEDWINDOW ,CRect(25,25,410,250));
wListBox.Create(WS_CHILD | WS_VISIBLE | LBS_STANDARD,CRect(10,10,300,110), this, IDC_LIST1);
//add listbox records
wListBox.AddString(TEXT("Apple"));
wListBox.AddString(TEXT("Orange"));
wListBox.AddString(TEXT("Pear"));

wEdit.Create(WS_CHILD | WS_VISIBLE | WS_BORDER , CRect(10,110,300,140), this, ID_EDIT);
wAddButton.Create(TEXT("Add"),BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(10,150,70,180), this, ID_ADDBUTTON);
wDeleteButton.Create(TEXT("Delete"),BS_PUSHBUTTON |WS_CHILD | WS_VISIBLE | WS_BORDER , CRect(80,150,140,180), this, ID_DELETEBUTTON);
wAmendButton.Create(TEXT("Amend"),BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_BORDER , CRect(150,150,210,180), this, ID_AMENDBUTTON);
}

BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
//message map
ON_BN_CLICKED(ID_ADDBUTTON,wAddButtonOnClick)
ON_BN_CLICKED(ID_DELETEBUTTON,wDeleteButtonOnClick)
ON_BN_CLICKED(ID_AMENDBUTTON,wAmendButtonOnClick)
ON_WM_PAINT()
ON_LBN_SELCHANGE(IDC_LIST1,wListBoxChange)
END_MESSAGE_MAP()

CSimpleApp MFCApp1;

//add item to listbox
afx_msg void CMainFrame::wAddButtonOnClick()
{
CString strText;
wEdit.GetWindowText(strText);
if (strText!="")//check textbox is not empty
{
wListBox.AddString(strText);
}

}

//delete selected item from listbox
afx_msg void CMainFrame::wDeleteButtonOnClick()
{
int i = wListBox.GetCurSel(); 
if (i!=-1)//checks listbox item is selected
{
wListBox.DeleteString(i);
wEdit.SetWindowText("");
}
}

//amend listbox item
afx_msg void CMainFrame::wAmendButtonOnClick()
{
CString strText;
wEdit.GetWindowText(strText);
int i = wListBox.GetCurSel(); 
if (strText!="" && i!=-1)//checks textbox is not empty
{
    wListBox.DeleteString(i);
wListBox.AddString(strText);
}
}

//detects for selected listbox change
afx_msg void CMainFrame::wListBoxChange()
{
CString strText;
int i = wListBox.GetCurSel(); 
wListBox.GetText(i, strText);
wEdit.SetWindowText( strText);//sets textbox to selected listbox item
}



Child Windows – Adding Controls

A child window is a window that exists inside and is dependent on a parent window. The child window processes mouse and keyboard messages and notifies the parent window when the child window’s state has changed. A standard control is created by instantiating one of the MFC control classes and calling the associated object’s create member function.

Windows makes the classic controls available to the application programs it hosts by registering six predefined WNDCLASS’s. The control types, their WNDCLASS’s, and the corresponding MFC classes are shown in the following table.

Control TypeWNDCLASSMFC Class
Buttons“BUTTON”CButton
List boxes“LISTBOX”CListBox
Edit controls“EDIT”CEdit
Combo boxes“COMBOBOX”CComboBox
Scroll bars“SCROLLBAR”CScrollBar
Static controls“STATIC”Cstatic

Buttons

MFC’s CButton class encapsulates the Windows button controls. A Button is a simple control used to trigger an action. The appearance and behaviour of a button control are specified when it is created by including the appropriate style flag in the button’s window style. A button can have many different appearances such as a push-button, radio button, or checkbox.

Checkbox

A checkbox is a small square box with an associated descriptive label. Checkboxes function as a toggle switch switch between selected and de-selected. Clicking the box once causes a checkmark to appear; clicking again toggles the checkmark off. The CEdit member functions GetState() and GetState() can be used to check/set the state of a button and ON_BN_CLICKED macro maps the button click function to the button click event.

The following short program uses 3 checkboxes to change the window’s background colour. Selecting combinations of each produces a mixture of red green and blue. The initial default background colour is black while selecting all 3 buttons will produce white.


Download Code

RadioButton

A radio button is a small circular box with an associated descriptive label. Radio buttons normally come in groups that allow the user to choose only one of a predefined set of mutually exclusive options. The following short program uses 3 checkboxes to change the window’s background colour. 


Download Code

For a further reading on the CButton class
https://docs.microsoft.com/en-us/cpp/mfc/reference/cbutton-class?view=vs-2019


Static control

MFC’s CStatic class encapsulates the Windows static control. Static controls are commonly used as labels for other controls. A static control displays text, shapes and pictures such as icons or bitmaps. The static control cannot be selected, accept input from the keyboard or mouse, and does not send WM_COMMAND messages back to the parent window.

For further reading on the CStatic classes
https://docs.microsoft.com/en-us/cpp/mfc/reference/cstatic-class?view=vs-2019


Editbox

MFC’s CEdit class encapsulates the functionality of edit controls. Edit controls are used for text entry and editing and come in two varieties: single-line and multiline,

For further reading on the CEdit class
https://docs.microsoft.com/en-us/cpp/mfc/reference/cedit-class?view=vs-2019

In the following example clicking the button title ‘set button’ changes the contents of the static box to the value of the textbox.


Download Code


ScrollBar

MFC’s CScrollBar class encapsulates scroll bar controls. A scroll bar is an object that allows the user to adjust a particular value, a section of the window or view, by navigating either left and right or up and down. A scroll bar appears as a long bar with a small button at each end. Between these buttons, there is a moveable bar called a thumb. Scrollbars exist in two forms: the standard scroll bar and the scroll bar control. The standard scroll bar is an integral part of a window, whereas the scroll bar control exists as a separate control

For further reading on the CScrollBar class
https://docs.microsoft.com/en-us/cpp/mfc/reference/cscrollbar-class?view=vs-2019

The following short program demonstrates a horizontal scrollbar control. The scrollbar position is shown in the static class.

Download Code


Listbox

MFC’s Clistbox Class encapsulates the Windows listbox control. A listbox displays a list of selectable items in a scrollable box. Users can select or deselect one or more of these items by clicking the appropriate line of text. For further reading on the CListBox class
https://docs.microsoft.com/en-us/cpp/mfc/reference/clistbox-class?view=vs-2019

The following short program creates a listbox and then adds a limited number of selectable items. Clicking any list item results in the selected listview value being copied to the static box. Clicking the ad button adds a new record, clicking the amend button amends the selected listview value, and clicking the delete button deletes the selected listview item.


Download Code


Combo Box

MFC’s CComboBox class encapsulates the functionality of the ComboBox controls. A combo box or drop-down list is a combination of a listbox and editbox, allowing the user to either type a value directly or select a value from the list. The following list outlines possible combo-box styles.

For further reading on the CComboBox class
https://docs.microsoft.com/en-us/cpp/mfc/reference/ccombobox-class?view=vs-2019

The following short program displays a dropdown list or combo box. Items can be added deleted or amended using the textbox and the appropriate button.


Download Code

Adding Menus

In Windows, a menu bar is a horizontal bar most often displayed immediately below the caption bar and usually containing a list of drop-down menu items. These drop-down menus can contain either other menu items or nested sub-menus.

MFC encapsulates menus and all associated actions in the CMenu class. MFC menus are usually created programmatically or from a resource file which can then be loaded into the application at run time.

To create and maintain menus programmatically, the developer will need to instantiate a class CMenu object and then use the following member functions: CreateMenu(), CreatePopupMenu(), and AppendMenu() to create the menu items.

CreateMenu

Is used to create a top-level menu. The prototype of this function is

BOOL CreateMenu( );

Returns nonzero if the menu creation was successful. 0 if menu creation failed

CreatePopupMenu

Creates a pop-up menu and attaches it to the CMenu object. The prototype of this function is

BOOL CreatePopupMenu( );

Return Nonzero if the pop-up menu was successfully created; 0 if menu creation failed

AppendMenu

Appends a new item to the end of a menu. The prototype of this function is

BOOL AppendMenu( UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL); BOOL AppendMenu( UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );

nFlags – Specifies information about the state of the new menu item.
nIDNewItem – Specifies either the command ID of the new menu item or, if nFlags is set to MF_POPUP, the menu handle ( HMENU) of a pop-up menu.
lpszNewItem – Specifies the content of the new menu item.
pBmp – Points to a CBitmap object that will be used as the menu item.

For further detailed reading
https://docs.microsoft.com/en-us/cpp/mfc/reference/cmenu-class?view=vs-2019#appendmenu

The ON_COMMAND macro

The ON_COMMAND macro in the message map links menu messages to a message response function. The prototype for this function is

ON_COMMAND( Id, mFuction )

where
id – is the menu items ID,
mFuction -is the name of the function that will handle that message.

To map a range of menu commands to a single message response use the ON_COMMAND_RANGE macro. The prototype for this macro is

ON_COMMAND_RANGE( id1, id2, mFunction )

where
id1 – Command ID at the beginning of a contiguous range of command IDs.
id2 – Command ID at the end of a contiguous range of command IDs.
mFunction – The name of the message-handler function to which the commands are mapped.

For this type of message mapping to work, the command IDs in the range must be consecutive.

Modifying Menus Programmatically

In addition to creating menus dynamically, menus can all be modified dynamically. The following table lists the CMenu member functions used to add, modify, and delete menu items.

InsertMenu

Inserts an item into a menu at a specified location. The prototype for this function is

BOOL InsertMenu( nPosition, nFlags, nIDNewItem, lpszNewItem ); BOOL InsertMenu( nPosition, nFlags, nIDNewItem, * pBmp );

where
nPosition – Specifies the menu item before the new menu item is inserted.
nFlags – Specifies information about the state of the new menu item
nIDNewItem – Specifies either the command ID of the new menu item or, if nFlags is set to MF_POPUP, the menu handle (HMENU) of the pop-up menu.
lpszNewItem – Specifies the content of the new menu item.
pBmp – Points to a CBitmap object that will be used as the menu item.

Returns nonzero if the function is successful; otherwise 0.
For further reading
https://docs.microsoft.com/en-us/cpp/mfc/reference/cmenu-class?view=vs-2019#insertmenu

ModifyMenu

Changes the command ID, text, or other characteristics of a menu item.

BOOL ModifyMenu( nPosition, nFlags, nIDNewItem, lpszNewItem ); BOOL ModifyMenu( nPosition, nFlags, nIDNewItem, pBmp );

NPosition – Specifies the menu item to be changed.
nFlags, nIDNewItem, lpszNewItem-see insert menu

For further reading
https://docs.microsoft.com/en-us/cpp/mfc/reference/cmenu-class?view=vs-2019#modifymenu

DeleteMenu

Deletes a menu item and the submenu associated with it, if any. The prototype of this function is

BOOL DeleteMenu( UINT nPosition, UINT nFlags );

Where
nPosition – Specifies the menu item that is to be deleted
nFlags – Is used to interpret nPosition

Return nonzero if the function is successful; otherwise 0

For further reading
https://docs.microsoft.com/en-us/cpp/mfc/reference/cmenu-class?view=vs-2019#deletemenu

RemoveMenu

Deletes a menu item

BOOL RemoveMenu( UINT nPosition, UINT nFlags );

where
nPosition – Specifies the menu item to be removed.
nFlags – Specifies how nPosition is interpreted
Return nonzero if the function is successful; otherwise 0.

The difference between RemoveMenu and DeleteMenu is that if the item being removed has a submenu, then deletemenu will remove the item and destroys the submenu, too. RemoveMenu removes the item but leaves the submenu extant in memory.

Before a menu is modified, the developer will need the CMenu pointer referencing the menu. MFC’s CWnd::GetMenu function returns a CMenu pointer for a window’s top-level menu or NULL if the window doesn’t have a top-level menu-

CMenu* pMenu = GetMenu (); pMenu->DeleteMenu (1, MF_BYPOSITION);

The Popup or Context Menu

Popup or context menus are those which generally appear when the user right-clicks. This menu is often referred to as a context menu because the options in the menu relate to what was right-clicked. The popup menu can be loaded from an existing resource or created dynamically with a call to the function CreatePopupMenu().

The cmenu member function TrackPopupMenu() displays a context menu. The function prototype is

BOOL TrackPopupMenu (UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = NULL)

Where
nFlags – Specifies screen-position and mouse-position flags.
Use one of the following flags to specify how the function positions the shortcut menu horizontally.
TPM_CENTERALIGN – Centers the shortcut menu horizontally relative to the coordinate specified by the x parameter.
TPM_LEFTALIGN – Positions the shortcut menu so its left side is aligned with the coordinate specified by the x parameter.
TPM_RIGHTALIGN – Positions the shortcut menu so its right side is aligned with the coordinate specified by the x parameter.
Use one of the following flags to specify how the function positions the shortcut menu vertically.
TPM_BOTTOMALIGN – Positions the shortcut menu so its bottom side is aligned with the coordinate specified by the y parameter.
TPM_TOPALIGN – Positions the shortcut menu so its top side is aligned with the coordinate specified by the y parameter.
TPM_VCENTERALIGN – Centers the shortcut menu vertically relative to the coordinate specified by the y parameter.
x – Specifies the horizontal position in screen coordinates of the pop-up menu.
y – Specifies the vertical position in screen coordinates of the top of the menu on the screen.
pWnd – Identifies the window that owns the pop-up menu.
lpRect – Ignored.

Returns the result of calling TrackPopupMenu

Example

The short program below demonstrates a simple menu structure. Clicking file>new will produce a messagebox and file>exit will close the application. A right-click will produce a context menu containing the same menu items as the main menu.

Download Code

Drawing Lines and Shapes

The CDC object class contains member functions to perform the basic drawing functionality. For a full overview of the CDC class https://docs.microsoft.com/en-us/cpp/mfc/reference/cdc-class?view=vs-2019

A sample of the graphics object functions found in the CDC class is listed below

Displaying Pixels

Single pixels can be drawn on the screen using the member function SetPixel()

COLORREF SetPixel(int x,int y,COLORREF pColour); COLORREF SetPixel(POINT point,COLORREF pColor);


Where
x – Specifies the logical x-coordinate.
y – Specifies the logical y-coordinate.
pColor – specifies the colour used to paint the point.
point – Encapsulates a single (x,y) coordinate.

Returns an RGB value for the colour that is actually painted. This value may be different from pColor if an approximation is used. If the function fails the return value is -1.

MoveTo

The initial starting position for graphics output will be the screen coordinate position 0,0 however this can be set by the application with a call to the member function Moveto(). The prototype for the Moveto function is –

CPoint MoveTo(int x,int y); CPoint MoveTo(POINT point);


where
x – specifies the x-coordinate of the new position, in logical units.
y – specifies the y-coordinate of the new position, in logical units.
point – specifies the new position using either a point structure or a CPoint object.

Drawing Lines

LineTo draws a line from the current position to a specified position and moves the current position to the end of the line –

BOOL LineTo(int x, int y); BOOL LineTo(POINT point);


where
x – Specifies the logical x-coordinate of the new position.
y – Specifies the logical y-coordinate of the new position.
point – Encapsulates a single (x,y) coordinate.

Returns the x and y coordinates of the previous position as a CPoint object.

PolylineTo

Connects a set of points with line segments

BOOL PolylineTo(const POINT* lpPoints,int nCount);

where
lpPoints – Points to an array of POINT data structures that contains the vertices of the line.
nCount – Specifies the number of points in the array.

Returns nonzero if the function is successful; otherwise 0.

Ellipse

The member function Ellipse draws a circle or an ellipse

BOOL Ellipse( int x1, int y1,int x2,int y2); BOOL Ellipse(LPCRECT lpRect);


Where
x1 – Specifies the x-coordinate of the upper-left corner of the ellipse’s bounding rectangle.
y1 – Specifies the y-coordinate of the upper-left corner of the ellipse’s bounding rectangle.
x2 – Specifies the x-coordinate of the lower-right corner of the ellipse’s bounding rectangle.
y2 – Specifies the y-coordinate of the lower-right corner of the ellipse’s bounding rectangle.
lpRect – Encapsulates the ellipse’s bounding rectangle.

Returns non-zero if the function is successful; otherwise 0.

Chord

The member function Chord draws a line segment connecting two points on a curve

BOOL Chord( int x1,int y1,int x2,int y2,int x3, int y3, int x4,int y4); BOOL Chord(LPCRECT lpRect,POINT ptStart,POINT ptEnd);

where
x1 – Specifies the x-coordinate of the upper-left corner of the chord’s bounding rectangle.
y1 – Specifies the y-coordinate of the upper-left corner of the chord’s bounding rectangle.
x2 – Specifies the x-coordinate of the lower-right corner of the chord’s bounding rectangle.
y2 – Specifies the y-coordinate of the lower-right corner of the chord’s bounding rectangle.
x3 – Specifies the x-coordinate of the point that defines the chord’s starting point.
y3 – Specifies the y-coordinate of the point that defines the chord’s starting point.
x4 – Specifies the x-coordinate of the point that defines the chord’s endpoint.
y4 – Specifies the y-coordinate of the point that defines the chord’s endpoint.
lpRect – Encapsulates the bounding rectangle (in logical units).
ptStart – Specifies the x- and y-coordinates of the point that defines the chord’s starting point. This point does not have to lie exactly on the chord. .
ptEnd – Specifies the x- and y-coordinates of the point that defines the chord’s ending point (in logical units). This point does not have to lie exactly on the chord.

Returns non-zero if the function is successful; otherwise 0.

Pie

The member function Pie draws a pie-shaped wedge by drawing an elliptical arc whose center and two endpoints are joined by lines.

BOOL Pie( int x1, int y1,int x2, int y2,int x3, int y3,int x4, int y4); BOOL Pie(LPCRECT lpRect,POINT ptStart,POINT ptEnd);


Where
x1 Specifies the x-coordinate of the upper-left corner of the bounding rectangle.
y1 Specifies the y-coordinate of the upper-left corner of the bounding rectangle.
x2 Specifies the x-coordinate of the lower-right corner of the bounding rectangle.
y2 Specifies the y-coordinate of the lower-right corner of the bounding rectangle.
x3 Specifies the x-coordinate of the arc’s starting point.
y3 Specifies the y-coordinate of the arc’s starting point.
x4 Specifies the x-coordinate of the arc’s endpoint (in logical units). This point does not have to lie exactly on the arc.
y4 Specifies the y-coordinate of the arc’s endpoint.
lpRect encapsulates the bounding rectangle.
ptStart Specifies the starting point of the arc.
ptEnd Specifies the endpoint of the arc.

Returns non-zero if the function is successful; otherwise 0.

Polygon

The member function Polygon Connects a set of points to form a polygon shape

BOOL Polygon(LPPOINT lpPoints, int nCount);


Where
lpPoints – Points to an array of points that specifies the vertices of the polygon. Each point in the array is a POINT structure or a CPoint object.
nCount – Specifies the number of vertices in the array.

Returns non-zero if the function is successful; otherwise 0.

Rectangle

The member function rectangle draws a 4-sided shape

BOOL Rectangle(int x1,int y1,int x2,int y2); BOOL Rectangle(LPCRECT lpRect);

where
x1 Specifies the x-coordinate of the upper-left corner of the rectangle.
y1 Specifies the y-coordinate of the upper-left corner of the rectangle.
x2 Specifies the x-coordinate of the lower-right corner of the rectangle.
y2 Specifies the y-coordinate of the lower-right corner of the rectangle.
lpRect Specifies the rectangle in logical units. You can either pass a CRect object or a pointer to a RECT structure for this parameter.

Returns non-zero if the function is successful; otherwise 0.

RoundRect

The member function RoundRect draws a rectangle with rounded corners

BOOL RoundRect( int x1, int y1,int x2,int y2, int x3,int y3); BOOL RoundRect(LPCRECT lpRect, POINT point);

where
x1 Specifies the x-coordinate of the upper-left corner of the rectangle.
y1 Specifies the y-coordinate of the upper-left corner of the rectangle.
x2 Specifies the x-coordinate of the lower-right corner of the rectangle.
y2 Specifies the y-coordinate of the lower-right corner of the rectangle.
x3 Specifies the width of the ellipse used to draw the rounded corners.
y3 Specifies the height of the ellipse used to draw the rounded corners.

lpRect encapsulates the bounding rectangle in logical units. You can either pass a CRect object or a pointer to a RECT structure for this parameter.
point – The x-coordinate of a point specifies the width of the ellipse to draw the rounded corners. The y-coordinate of a point specifies the height of the ellipse to draw the rounded corners. You can pass either a POINT structure or a CPoint object for this parameter.

Returns nonzero if the function is successful; otherwise 0.

For full details of Windows drawing capabilities use the following
https://docs.microsoft.com/en-us/cpp/mfc/reference/cdc-class?view=vs-2019

Example

The following short program illustrates some of the windows line and shape drawing capabilities

Download Code

Dealing with Keyboard Input

Keyboard input is passed onto a program’s window procedure in the form of messages. Each time a key is pressed a message is sent to the window with input focus. Since most applications will have more than one window, a particular window must have input focus to receive these messages. 

Pressing keys on the keyboard will generate both a keystroke and a character. Keystrokes represent the physical keypress and characters represent the display symbol or glyphs generated as a result of the keypress.

When a key is pressed or released, a WM_KEYDOWN or WM_KEYUP message is placed in the message queue by Windows. These keystroke messages indicate the pressed key using a virtual key code. The virtual key code is a device-independent integer code that uniquely identifies a key on the keyboard. The corresponding MFC message map macros are ON_WM_KEYDOWNON_WM_KEYUP. The prototype message handler is –

afx_msg void OnMsgName (UINT nFlags, CPoint point)

where
nChar – virtual key code of the key that was pressed or released.
nRepCnt – repeat count—the number of keystrokes.
nFlags – contains the key’s scan code.

In addition to producing keystrokes, character messages are also produced as a result of translating keystroke messages into character codes. The most commonly used character message is WM_CHAR. A WM_CHAR message includes a character code that maps directly to a symbol in the current character set. The ON_WM_CHAR macro entry in a class’s message map routes WM_CHAR messages to the member function OnChar(). The prototype is prototype is as follows:

afx_msg void OnMsgName (UINT nFlags, CPoint point)

where nChar holds the character code and nRepCnt and nFlags have the same meanings as keystroke messages.

Some additional keyboard messages

SYSKEY messages

The WM_SYSKEYDOWN and WM_SYSKEYUP message is generated when the user presses the F10 key (menu bar) or holds down the ALT key and then presses another key. It also occurs when no window currently has the keyboard focus with the message being sent to the active window.

If other keys are pressed while the Alt key is held down Windows will generate a WM_SYSKEYDOWN and WM_SYSKEYUP messages instead of WM_KEYDOWN and WM_KEYUP messages.

The window that receives the message can distinguish between these two contexts by checking the context code in the lParam parameter.

The corresponding message-map macros are ON_WM_KEYDOWNON_WM_KEYUPON_WM_SYSKEYDOWN, and ON_WM_SYSKEYUP.

Handling WM_SYSKEYDOWN and WM_SYSKEYUP messages is generally best left to the system since if these messages don’t find their way to ::DefWindowProc and get returned to Windows then system keyboard commands such as Alt-Tab will stop working.

Dead keys

A dead key is a modifier key that does not generate a character but modifies the character generated by the key pressed immediately after it. Dead keys are typically used to attach a specific diacritic to a base letter.

To process dead-key messages in an MFC application will need an ON_WM_DEADCHAR or ON_WM_SYSDEADCHAR entry in the message map in addition to supplying handling functions named OnDeadChar() and OnSysDeadChar().

Virtual key codes

Windows defines special constants for each key the user can press. These constants, known as virtual key codes, provide hardware and language-independent methods of identifying keyboard keys. These values are listed in the link below

https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

Retrieving a key state

The ::GetKeyState() API function retrieves the status of a specified virtual key. The status specifies whether the key is up, down, or toggled. Since information about the current states of keys such as Shift and Ctrl keys is not included in keyboard messages, the GetKeyState API function allows the developer to determine these key states before deciding on a course of action. The syntax for this function is –

afx_msg void OnMsgName (UINT nFlags, CPoint point)

Where vKey specifies one of 256 possible virtual-key codes.

If the function succeeds, the return value indicates whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. A return value of zero indicates that the current window does not have keyboard focus.

Example

The following code segment illustrates key-down and char-character message handling by displaying the output of the keystroke and character values when a key is pressed.

Download Code

Working with the Mouse

Windows can handle a mouse with up to 3 buttons and a mouse wheel. Mouse messages are generated when the user moves the mouse, presses the mouse buttons or scrolls the mouse wheel, within the client and non-client area. The non-client area is the area of a window consisting of borders, a title bar, a menu bar, a minimize/maximize button and an exit button.

Client Area Mouse Messages

Listed below are some of the more common Windows client area mouse messages together with their MFC macro names and the Message-Map Macro Handling Function

DescriptionMessage map macroHandling function
Left mouse button pressed.ON_WM_LBUTTONDOWNOnLButtonDown
Left mouse button released.ON_WM_LBUTTONUPOnLButtonUp
Left mouse button double-clicked.ON_WM_LBUTTONDBLCLKOnLButtonDblClk
Middle mouse button pressed.ON_WM_MBUTTONDOWNOnMButtonDown
Middle mouse button released.ON_WM_MBUTTONUPOnMButtonUp
Middle mouse button double-clicked.ON_WM_MBUTTONDBLCLKOnMButtonDblClk
Right mouse button pressed.ON_WM_RBUTTONDOWNOnRButtonDown
Right mouse button released.ON_WM_RBUTTONUPOnRButtonUp
Right mouse button double-clicked.ON_WM_RBUTTONDBLCLKOnRButtonDblClk
Cursor moved over client area.ON_WM_MOUSEMOVEOnMouseMove

The message map handler function will be of the following format

afx_msg void OnMsgName (UINT nFlags, CPoint point)

Where
point – contains the cursor location reported in device coordinates relative to the upper left corner of the window’s client area.
nFlags – contains additional information about the mouse state and Shift and Ctrl as detailed below.

MK_LBUTTON – The left mouse button is pressed.
MK_MBUTTON – The middle mouse button is pressed.
MK_RBUTTON – The right mouse button is pressed.
MK_CONTROL – The Ctrl key is pressed.
MK_SHIFT – The Shift key is pressed.

Nonclient-Area Mouse Messages

A nonclient-area message is generated when the mouse is clicked inside or moved over a window’s nonclient area. The table lists below details these nonclient-area mouse messages.

MessageMessage-Map MacroHandling Function
WM_NCLBUTTONDOWNON_WM_NCLBUTTONDOWNOnNcLButtonDown
WM_NCLBUTTONUPON_WM_NCLBUTTONUPOnNcLButtonUp
WM_NCLBUTTONDBLCLKON_WM_NCLBUTTONDBLCLKOnNcLButtonDblClk
WM_NCMBUTTONDOWNON_WM_NCMBUTTONDOWNOnNcMButtonDown
WM_NCMBUTTONUPON_WM_NCMBUTTONUPOnNcMButtonUp
WM_NCMBUTTONDBLCLKON_WM_NCMBUTTONDBLCLKOnNcMButtonDblClk
WM_NCRBUTTONDOWNON_WM_NCRBUTTONDOWNOnNcRButtonDown
WM_NCRBUTTONUPON_WM_NCRBUTTONUPOnNcRButtonUp
WM_NCRBUTTONDBLCLKON_WM_NCRBUTTONDBLCLKOnNcRButtonDblClk
WM_NCMOUSEMOVEON_WM_NCMOUSEMOVEOnNcMouseMove

The message map handler function will be of the following format

afx_msg void OnMsgName (UINT nHitTest, CPoint point)

where
nHitTest – contains a hit-test code that identifies where in the window’s nonclient area the event occurred. A selection of these hit-test codes is shown in the list below.

ValueCorresponding Location
HTCAPTION The title bar
HTCLOSE The close button
HTGROWBOX The restore button (same as HTSIZE)
HTHSCROLL The window’s horizontal scroll bar
HTMENU The menu bar
HTREDUCE The minimize button
HTSIZE The restore button (same as HTGROWBOX)
HTSYSMENU The system menu box
HTVSCROLL The window’s vertical scroll bar
HTZOOM The maximize button

point – specifies the location in the window at which the event occurred however for nonclient-area mouse messages, point.x and point.y contain screen coordinates as opposed to client coordinates. The screen coordinates can be converted to client coordinates with the CWnd member function ScreenToClient().

Miscellaneous Mouse Messages

WM_NCHITTEST

Before a window receives a client-area or nonclient-area mouse message, it receives a WM_NCHITTEST message accompanied by the cursor’s screen coordinates. Windows uses this message to determine whether to send a client-area or nonclient-area mouse message. For more detailed information about the parameters associated with the message use the following

https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-nchittest

The Mouse Wheel

The WM_MOUSEWHEEL message is sent when the mouse wheel is rotated.
MFC’s ON_WM_MOUSEWHEEL macro maps WM_MOUSEWHEEL messages to the message handler OnMouseWheel. The prototype of OnMouseWheel is:

BOOL OnMouseWheel (UINT nFlags, short zDelta, CPoint point)

Where
The nFlags and point parameters are identical to those passed to OnLButtonDown. zDelta is the distance the wheel was rotated. The zDelta value is calibrated in multiples or divisions of WHEEL_DELTA, which is 120. A value less than zero indicates rotating while a value greater than zero indicates rotating forward (away from the user).

Double Clicks

To register a double click, a window must be set up to be notified of a double click event by including the WNDCLASS style CS_DBLCLKS during Windows registration. This is set by default in a frame windows declaration. The MFC Message-Map Macro and associated Handling Function for dealing with a double click are

ON_WM_LBUTTONDBLCLK – OnLButtonDblClk(UINT, CPoint)
ON_WM_RBUTTONDBLCLK – OnRButtonDblClk(UINT, CPoint)
ON_WM_MBUTTONDBLCLK – OnMButtonDblClk(UINT, CPoint)

Capturing the Mouse

A window procedure normally receives mouse messages only when the mouse cursor is positioned over the client or nonclient area of the window however a program might need to receive mouse messages when the mouse is outside the window. For example, if a mouse button is clicked inside a window but the mouse moves outside the window’s client area before releasing that button then the window will not receive the button-up event. To remedy this problem, windows allows the application to ‘capture’ the mouse and continue to receive mouse messages when a cursor moves outside the application window. Windows will then continue to receive messages until the button is released or the capture is cancelled. The mouse is captured with CWnd member function SetCapture() and released with CWnd member function ReleaseCapture(). These functions are normally executed in the button-down and button-up handlers

The Hourglass Cursor

When an application undertakes a lengthy processing task the usual procedure is to display an hourglass to indicate that the application is “busy.” The CWaitCursor class allows any application to display a wait cursor. To display a WaitCursor instantiate a CWaitCursor object variable before the code that performs the lengthy operation, the object’s constructor will automatically cause the wait cursor to be displayed. When the object goes out of scope its destructor will set the cursor to the previous cursor.

void LengthyFunction( ) {   CWaitCursor wait; // display wait cursor   //lengthy process } // wait cursor removed when function goes out of scope

Changing the Mouse Icon

The CButton member function SetCursor() allows an application to change the mouse cursor. The syntax for this function is

HCURSOR SetCursor(HCURSOR hCursor);

Where hCursor is a handle to the cursor. The cursor can be created by the CreateCursor() function or loaded by the LoadCursor() or LoadImage() function. If this parameter is NULL, the cursor is removed from the screen.
The return value is the handle to the previous cursor or NULL if there was no previous cursor.

For further information about setting the cursor icon go to the following link
https://support.microsoft.com/en-gb/help/131991/how-to-change-the-mouse-pointer-for-a-window-in-mfc-by-using-visual-c

Example

The following short program demonstrates how Windows handles messages from both the client and non-client areas of the screen, together with the ALT and CTRL keys. Output describing the area clicked and the coordinate of the area clicked is displayed in the main window.

Download Code

Dealing with Text Output

Displaying Text

The two most popular functions for displaying text are the CDC member functions TextOut() and DrawText(). All CDC text functions use the font that is currently selected into the device context The syntax for these two member functions are –

virtual BOOL TextOut(int x,int y,LPCTSTR lpszString,int nCount); BOOL TextOut(int x,int y,const CString& str);

Where
x – Specifies the vertical position of the starting point of the text.
y – Specifies the horizontal position of the starting point of the text.
lpszString – Points to the character string to be drawn.
nCount – Specifies the number of characters in the string.
str – A CString object that contains the characters to be drawn.

Returns non-zero if the function is successful; otherwise zero.

virtual int DrawText(LPCTSTR lpszString,int nCount,LPRECT lpRect,UINT nFormat); int DrawText(const CString& str, LPRECT lpRect,UINT nFormat);

where
pszString – Points to the string to be drawn.
nCount – Specifies the number of chars in the string.
lpRect – Points to a RECT structure or CRect object that contains the text to be formatted.
str – A CString object that contains the specified characters to be drawn.
nFormat – Specifies the method of formatting the text.

The function returns the height of the text if the function is successful.

Fonts

In MFC, the CFont class is used to create and manipulate fonts. By default, the CDC text output class can draw text using a pre-selected system. MFC supports 7 built-in fonts. These are

ANSI_FIXED_FONT
ANSI_VAR_FONT
DEVICE_DEFAULT_FONT
DEFAULT_GUI FONT
OEM_FIXED_FONT
SYSTEM_FONT
SYSTEM_FIXED_FONT

To select one of these stock fonts into the current device context first create a CFont object and then call the object member function CreateStockObject() using one of the custom font names above. The CFont object can then be selected into the current device context by calling the SelectObject() member function as below –

CFont newfont; Newfont.CreateStockObject(ANSI_FIXED_FONT); paintDC.SelectObject(newfont);

Custom Fonts

The CFont object class supplies 4 member functions for creating and initialising a font before use: CreateFont()CreateFontIndirect()CreatePointFont(), and CreatePointFontIndirect(). Use CreateFont or CreateFontIndirect to specify the font size in pixels, and CreatePointFont and CreatePointFontIndirect to specify the font size in points. The syntax for the CreateFont member function is

BOOL CreateFont( int nHeight, int nWidth,int nEscapement, int nOrientation,int nWeight,BYTE bItalic, BYTE bUnderline,BYTE bStrikeOut,BYTE nCharSet,BYTE nOutPrecision,BYTE nClipPrecision, BYTE nQuality,BYTE nPitchAndFamily, LPCTSTR lpszFacename);

where
nHeight – The height, in logical units, of the font.
nWidth – The average, in logical units, of the font.
nEscapement – Angle of the escapement.
nOrientation – Base-line orientation angle
nWeight – Font weight ( 0 – 1000)
bItalic – Specifies an italic font.
bUnderline – Specifies an underlined font.
bStrikeOut – A strikeout font if set to TRUE.
nCharSet – Character set identifier
nOutPrecision – Defines how closely the output must match the requested font attributes
nClipPrecision – Defines how to clip characters partially outside the clipping region.
nQuality – Defines how carefully GDI must attempt to match the logical font attributes to those of an actual physical font.
nPitchAndFamily -The two low-order bits specify the pitch of the font
pszFaceName – Is a pointer to a null-terminated string that specifies the typeface name of the font

If the function succeeds, the return value is a handle to a logical font. If the function fails, the return value is NULL.

For further detailed reading of the CreateFont member function
https://docs.microsoft.com/en-us/cpp/mfc/reference/cfont-class?view=vs-2019#createfont

For further detailed reading on the CFont MFC class
https://docs.microsoft.com/en-us/cpp/mfc/reference/cfont-class?view=vs-2019

Deleting GDI Objects

Fonts 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 CFont object is created on the stack it will automatically be deleted when it goes out of scope. If a CFont 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 a “memory leak” and gradual depletion of available system memory.

Setting Text Colour.

The cdc member function SetTextColor() sets the text colour to the specified colour. The syntax for this function is –

settextcolor(colorref color);

Where color specifies the colour of the text as an RGB colour value.
Returns an RGB value for the previous text colour.

Setting the Text Background Colour

The cdc member function SetTextColor sets the text background to the specified colour. The syntax for this function is

virtual COLORREF SetBkColor(COLORREF colour);

Where colour specifies the new background colour.
Returns the previous background colour as an RGB colour value. If an error occurs, the return value is 0x80000000.

Setting the Text Background Display Mode

The background mode defines whether the system removes existing background colours before drawing text. To set the way text is displayed against its background use the cdc function SetBkMode(). The device context text background can be set to opaque or transparent. The prototype for this function is

SetBkMode(int nBkMode)

where
nBKMode – Specifies the mode to be set. This parameter can be either of the following values:

  • opaque – Background is filled with the current background colour before the text, hatched brush, or pen is drawn. This is the default background mode.
  • transparent – Background is not changed before drawing.

Returns the previous background mode.

Textmetric

The textmetric structure describes the attributes of a given font and enables an application to work with text with different font attributes. Knowing the structure of a particular font is necessary because Windows only provides minimal support for text processing. Attributes such as character height and distance between lines must be factored into any application supporting text output. The MFC member function used to obtain the text metric of the existing font is the CDC member function GetTextMetrics(). The syntax for this function is

BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const;

Where lpMetrics points to the TEXTMETRIC structure that receives the metrics.

For detailed reading on the textmetric structure use the following resource
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-textmetricw

Character Spacing

For an application to output consecutive lines of text, the length of a string will need to be known so that any following lines of text will appear in the correct location. This is necessary because Windows does not keep track of the current text output location. Since the length of a string will not be consistent in a non-monospaced typeface, MFC includes the cdc member function GetTextEntent(). This function enables an application to keep track of the horizontal space taken up by the currently selected device context font.

The syntax of this function is

CSize GetTextEntent( LPCTSTR lpszString, int nCount ) const; CSize GetTextExtent( const CString& str ) const;

Where
lpszString – Points to a string of characters.
nCount – Specifies the number of characters in the string.
str – A CString object that contains the specified characters.

Returns the dimensions of the string in a CSize object.

Example

The following short program demonstrates the various text manipulation functions.

Download Code

Working with Graphics

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 a new pen, then this new pen must be created and selected into the device context. Selecting a new graphics object does not 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 creating custom pens. The prototype of this function is

BOOL CreatePen( int nPenStyle, int nWidth, COLORREF crColor );

Were.
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 colour 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://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdicreatepen

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 colour of the brush. Return 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

The CDC member function SelectStockObject() retrieves a handle to a 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 stock 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. To avoid this reinitialisaton, 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 consuming 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 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 a “memory leak” and gradual depletion of available system memory.

Dealing with Colour Values

The Windows graphics system uses the RGB colour 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 colour. 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

Device Context

In Windows, the graphics device interface (GDI) displays graphics and formatted text on both the screen and the printer. A device context is a Windows data structure containing information about the drawing attributes of the output device. Writing text and drawing images to the screen is known as ‘painting’.

System Generated Repaint Requests

Windows does not keep a record of the application window content so if by some action, a part of this client area is overwritten then widows will inform the application that this client area needs to be ‘repainted’ by posting a WM_PAINT message to the application window. The region of the application client that needs updating is known as an “invalid area”. Windows maintains the size and coordinates of this region for each Window.

Before an application can ‘repaint’ the screen it must obtain a device context for the Windows client area. Windows then fills the device context structure with the attribute values of the device being written to. In MFC, the CDC class wraps a Windows device context and the associated GDI member function for working with the ON_WM_PAINT() handler into one package CPaintDC. The constructor function for CPaintDC is

CPaintDC(CWND *window)

Where window is a pointer to the window whose client area the device context object will access. To get a DC for the invoking windows use the ‘this’ pointer

To respond to the WM_PAINT message, an MFC function will need a ON_WM_PAINT() entry in the applications message map and then write an associated OnPaint() message handler.

Other Useful Device Context-Related Functions

In addition to repainting the screen in response to an ON_WM_PAINT message, the application can also request a device context due to some action performed by the user that does not result in the generation of the On_Paint message.

CClientDC

Creates a client-area device context that is not associated with OnPaint. The constructor function for the CClientDC() is

CClientDC (CWND *window)

Where window is a pointer to the window from which the device context is obtained. To invoke a DC for the invoking windows use this as a parameter. To access the entire screen use a NULL pointer.

CWindowDC

Provides a DC to the entire window, including its client and nonclient area. The nonclient area covers the Windows borders, title bar, menu bar, minimize/maximize button, and exit button. The Non-client area is generally under the control of the operating system. The constructor function for CWindowDC() is

CWindowDC (CWND *Window)

Where window is a pointer to the window from which the device context is obtained. To gain access to the entire screen use the NULL character.

InvalidateRect

Allows an application to invalidate a Windows region manually and tells Windows it needs to repaint that region. The prototype for this function is

void InvalidateRect(LPCRECT lpRect,BOOL bErase = TRUE);

where
lpRect – is a pointer to a RECT structure that contains the update region client coordinates. If this parameter is NULL, the entire client area is set for update.
bErase – Specifies whether the background within the update region is to be erased when the update region is processed. If this parameter is TRUE, the background is erased when the BeginPaint function is called. If this parameter is FALSE, the background remains unchanged.

ValidateRect

Allows an application to validate a Windows region manually. The prototype for this function is

void ValidateRect(LPCRECT lpRect);

Where lpRect is a pointer to a RECT structure that contains the client coordinates of the rectangle to be removed from the update region. If the RECT structure is NULL the entire client area is removed from the update rectangle.

Example

The following short program demonstrates the OnPaint() message by keeping a running total of the times the client area has been repainted. The repaint request can be generated by dragging another window over the application window or by clicking the minimise and maximise icon

Download Code