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.
#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(); }