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 Nonzero if the function is successful; otherwise 0.

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 is able to draw text using a pre-selected font, known as the system Font. 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

In order 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 font.
nEscapement – Angle of 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 indentifier
nOutPrecision – Defines how closely the output must match match the requested font attributes
nClipPrecision – Defines how to clip characters that are 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 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 more detailed reading of the CreateFont member function
https://docs.microsoft.com/en-us/cpp/mfc/reference/cfont-class?view=vs-2019#createfont

For more 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. Its 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 however 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 “memory leak” and gradual depletion of available system memory.

Setting text colour.

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

settextcolor(colorref color);

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

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 color.
Returns the previous background color as an RGB color 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 colors on before drawing text. To set the way that 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 color before the text, hatched brush, or pen is drawn. This is the default background mode.
  • transparent – Background is not changed before drawing.

Return the previous background mode.

Textmetric

The textmetric structure is used to describe 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

In order for an application to output consecutive lines of text, the length of a string will need to be known in order that any following lines of text will appear in the correct location. This is necessary because, in common with windows minimal support for text output, there is no built-in capability to 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 functions 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.


The following short program demonstrates the various text manipulation function.

mfc text output

#include <afxwin.h>
class CSimpleApp : public CWinApp
{
public:
BOOL InitInstance();
};
class CMainFrame : public CFrameWnd
{
public:
CMainFrame();
DECLARE_MESSAGE_MAP()
afx_msg void OnPaint();
};
 
 
BOOL CSimpleApp::InitInstance(){
m_pMainWnd = new CMainFrame();
m_pMainWnd->ShowWindow(m_nCmdShow);
return TRUE;
}
 
CMainFrame::CMainFrame()
{
Create(NULL, "MFC Text Output");
}
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
CSimpleApp MFCApp1;
 
 
afx_msg void CMainFrame::OnPaint()
{
CPaintDC dc(this);
TEXTMETRIC tm;
SIZE textWidth;
int xpos=0;//holds x position of text
int ypos=0;//holds y position of test
int hDCLast=dc.SaveDC();//save current font textmetric
dc.TextOut(xpos,ypos,"stock font");
 
dc.GetTextMetrics(&tm);
ypos=ypos+tm.tmHeight;//new y coordinate based on heigth of existing font
 
//selects new stock font and outputs text
CFont newfont;
newfont.CreateStockObject(ANSI_FIXED_FONT);
dc.SelectObject(newfont);
dc.TextOut(xpos,ypos,TEXT("ANSI_FIXED_FONT"));
ypos=ypos+tm.tmHeight;
 
//select new font colour and outputs text
COLORREF newtextcolour=COLORREF RGB(255, 0, 0);
dc.SetTextColor(newtextcolour);
dc.TextOut(xpos,ypos,TEXT("ANSI_FIXED_FONT, colour red"));
ypos=ypos+tm.tmHeight;
 
//sets new background color and outputs text
dc.SetBkColor(RGB(0, 0, 255));
dc.TextOut(xpos,ypos,TEXT("ANSI_FIXED_FONT, colour red, blue background"));
ypos=ypos+tm.tmHeight;
 
//sets new background mode and outputs text
dc.SetBkMode(TRANSPARENT);
dc.TextOut(xpos,ypos,TEXT("ANSI_FIXED_FONT, colour red, transparent back ground"));
ypos=ypos+tm.tmHeight;
 
//creates new font and outputs text
CFont newfontarial;
newfontarial.CreateFont(23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Ariel");
dc.SelectObject(newfontarial);
dc.GetTextMetrics(&tm);
dc.TextOut(xpos,ypos,TEXT("ANSI_FIXED_FONT, colour red, transparent background, arial 20"));
ypos=ypos+tm.tmHeight;
newfontarial.DeleteObject();
 
//restores original stock font and outputs text
dc.RestoreDC(hDCLast);
dc.GetTextMetrics(&tm);
dc.TextOut(0,ypos,"stock font restored using SaveDC/RestoreDC");
ypos=ypos+tm.tmHeight;
 
//creates 3 new fonts
CFont newfonttimes,newfontcourier,newfontariel;
newfonttimes.CreateFont(30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
newfontcourier.CreateFont(20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New");
newfontariel.CreateFont(15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Ariel");
 
//selects 1st new font and outputs text
dc.SelectObject(newfonttimes);
dc.GetTextMetrics(&tm);
int baseline=tm.tmAscent;
textWidth=dc.GetTextExtent("times new roman 30 statement 1");
dc.TextOut(xpos,ypos,TEXT("times new roman 30 statement 1"));
xpos=xpos+textWidth.cx;
 
//selects 2nd new font and outputs text
dc.SelectObject(newfontcourier);
dc.GetTextMetrics(&tm);
int baselinecourier=baseline-tm.tmAscent;//calculates text baseline
textWidth=dc.GetTextExtent("courier 20 statement 2");//calculates width of text
dc.TextOut(xpos,ypos+baselinecourier,TEXT("courier 20 statement 2"));
xpos=xpos+textWidth.cx;
 
//selects 3rd new font and outputs text
dc.SelectObject(newfontariel);
dc.GetTextMetrics(&tm);
int baselineariel=baseline-tm.tmAscent;
dc.TextOut(xpos,ypos+baselineariel,TEXT("ariel 10 statement 3"));
 
newfonttimes.DeleteObject();
newfontcourier.DeleteObject();
newfontariel.DeleteObject();
}

 

Download