Home

GDI Tools - Fonts

Introduction

A font is a list of symbols that can be drawn on a device context to produce a symbol. A font is designed by an artist but usually follows a specific pattern. For example a font designed to produce symbols readable in the English language must be designed by a set of predetermined and agreed upon symbols. These English symbols are grouped in an entity called the English alphabet. When designing such a font, the symbols created must conform to that language. This also implies that one font can be significantly different from another and a font is not necessarily a series of readable symbols.

Just like everything else in the computer, a font must have a name. To accommodate the visual needs, a font is designed to assume different sizes.

Font Selection

Before using a font to draw a symbol on a device, the font must have been installed. Microsoft Windows installs many fonts during setup. To handle its various assignments, the operating system uses a particular font known as the System Font. This is the font used to display the menu items and other labels for resources in applications. If you want to use a different font to draw text in your application, you must select it.

Selecting a font, as well as selecting any other GDI object, is equivalent to specifying the characteristics of a GDI object you want to use. To do this, you must first create the object, unless it exists already. To select an object, pass it as a pointer to the SelectObject() function. The syntax of this function is:

HGDIOBJ SelectObject(HDC hdc, HGDIOBJ hgdiobj);

This function takes as argument the font you want to use, hgdiobj. It returns a pointer to the font that was previously selected. If there was a problem when selecting the font, the function returns NULL. As you can see, you must first have a font you want to select.

Regular Font Creation

A font in Microsoft Windows is stored as an HFONT value.

To Create a font, you can use the CreateFont() function. Its syntax is:

HFONT CreateFont(
  int nHeight,               
  int nWidth,                
  int nEscapement,           
  int nOrientation,          
  int fnWeight,              
  DWORD fdwItalic,           
  DWORD fdwUnderline,        
  DWORD fdwStrikeOut,
  DWORD fdwCharSet,
  DWORD fdwOutputPrecision,
  DWORD fdwClipPrecision,
  DWORD fdwQuality,
  DWORD fdwPitchAndFamily,
  LPCTSTR lpszFace
);

The nHeight argument is the height applied to the text.

The nWidth value is the desired width that will be applied on the text.

The nEscapement is the angle used to orient the text. The angle is calculated as a multiple of 0.1 and oriented counterclockwise.

The nOrientation is the angular orientation of the text with regards to the horizontal axis.

The nWeight is used to attempt to control the font weight of the text because it is affected by the characteristics of the font as set by the designer. It holds values that displays text from thin heavy bold. The possible values are:

Constant  Value
FW_DONTCARE 0
FW_THIN 100
FW_EXTRALIGHT 200
FW_ULTRALIGHT 200
FW_LIGHT 300
FW_NORMAL 400
FW_REGULAR 400
FW_MEDIUM 500
FW_SEMIBOLD 600
FW_DEMIBOLD 600
FW_BOLD 700
FW_EXTRABOLD 800
FW_ULTRABOLD 800
FW_BLACK 900
FW_HEAVY 900

The bItalic specifies whether the font will be italicized (TRUE) or not (FALSE).

The bUnderline is used to underline (TRUE) or not underline (FALSE) the text.

The cStrikeOut is specifies whether the text should be stroke out (TRUE) or not (FALSE) with a line.

The nCharSet, specifies the character set used. The possible values are:

Constant  Value
ANSI_CHARSET 0
DEFAULT_CHARSET 1
SYMBOL_CHARSET 2
SHIFTJIS_CHARSET 128
OEM_CHARSET 255

The nOutPrecision controls the amount precision used to evaluate the numeric values used on this function for the height, the width, and angles. It can have one of the following values: OUT_CHARACTER_PRECIS, OUT_STRING_PRECIS, OUT_DEFAULT_PRECIS, OUT_STROKE_PRECIS, OUT_DEVICE_PRECIS, OUT_TT_PRECIS, OUT_RASTER_PRECIS

If some characters may be drawn outside of the area in which they are intended, the nClipPrecision is used to specify how they may be clipped. The possible value used are CLIP_CHARACTER_PRECIS, CLIP_MASK, CLIP_DEFAULT_PRECIS, CLIP_STROKE_PRECIS, CLIP_ENCAPSULATE, CLIP_TT_ALWAYS, CLIP_LH_ANGLES.

The nQuality specifies how the function will attempt to match the font's characteristics. The possible values are DEFAULT_QUALITY, PROOF_QUALITY, and DRAFT_QUALITY.
The nPitchAndFamily specifies the category of the font used. It combines the pitch and the family the intended font belongs to. The pitch can be specified with DEFAULT_PITCH, VARIABLE_PITCH, or FIXED_PITCH. The pitch is combined using the bitwise OR operator with one of the following values:

Constant  Description
FF_DECORATIVE Used for a decorative or fancy font
FF_DONTCARE Let the compiler specify
FF_MODERN Modern fonts that have a constant width
FF_ROMAN Serif fonts with variable width
FF_SCRIPT Script-like fonts
FF_SWISS Sans serif fonts with variable width

The lpszFacename is the name of the font used.

Once you have created a font, you can select it into the device context and use it it for example to draw text. After using a font, you should delete it to reclaim the memory space its variable was using. This is done by calling the DeleteObject() function.

 



Here is an example:

#include <windows.h>

LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX  WndCls;
    static char szAppName[] = "ExoFont";
    MSG         Msg;

    WndCls.cbSize        = sizeof(WndCls);
    WndCls.style         = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
    WndCls.lpfnWndProc   = WindProcedure;
    WndCls.cbClsExtra    = 0;
    WndCls.cbWndExtra    = 0;
    WndCls.hInstance     = hInstance;
    WndCls.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    WndCls.hCursor       = LoadCursor(NULL, IDC_ARROW);
    WndCls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    WndCls.lpszMenuName  = NULL;
    WndCls.lpszClassName = szAppName;
    WndCls.hIconSm       = LoadIcon(hInstance, IDI_APPLICATION);
    RegisterClassEx(&WndCls);

    CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
                   szAppName, "Fonts Fundamentals",
                   WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                   CW_USEDEFAULT, CW_USEDEFAULT, 450, 220,
                   NULL, NULL, hInstance, NULL);

    while( GetMessage(&Msg, NULL, 0, 0) )
    {
        TranslateMessage(&Msg);
        DispatchMessage( &Msg);
    }

    return static_cast<int>(Msg.wParam);
}

LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg,
                               WPARAM wParam, LPARAM lParam)
{
    HDC         hDC;
    PAINTSTRUCT Ps;
    HFONT	    font;

    switch(Msg)
    {
    case WM_PAINT:
	hDC = BeginPaint(hWnd, &Ps);
		
         font = CreateFont(46, 28, 215, 0,
                           FW_NORMAL, FALSE, FALSE, FALSE,
                           ANSI_CHARSET, OUT_DEFAULT_PRECIS,
		         CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
		         DEFAULT_PITCH | FF_ROMAN,
			"Times New Roman");

        SelectObject(hDC, font);
        TextOut(hDC, 20, 128, "Euzhan Palcy", 12);
        DeleteObject(font);

	EndPaint(hWnd, &Ps);
	break;
    case WM_DESTROY:
	PostQuitMessage(WM_QUIT);
	break;
    default:
	return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    return 0;
}

Remember that once an object such as a font has been selected, it remains in the device context until further notice. For example, if you have created and selected a font, any text you draw would follow the characteristics of that font. If you want another font, you must change the previously selected font.

The computer uses the default black color to draw the text. If you want to draw text with a different color, you can first call the SetTextColor() function and specify the color of your choice.

Logical Font Creation

The CreateFont() function is used to specify all characteristics of a font in one step. Alternatively, if you want to specify each font property, you can declare a LOGFONT variable and initialize it. It is defined as follows:

typedef struct tagLOGFONT { 
LONG lfHeight; 
LONG lfWidth; 
LONG lfEscapement; 
LONG lfOrientation; 
LONG lfWeight; 
BYTE lfItalic; 
BYTE lfUnderline; 
BYTE lfStrikeOut; 
BYTE lfCharSet; 
BYTE lfOutPrecision; 
BYTE lfClipPrecision; 
BYTE lfQuality; 
BYTE lfPitchAndFamily; 
TCHAR lfFaceName[LF_FACESIZE]; 
} LOGFONT, *PLOGFONT;

This time, you do not have to provide a value for each member of the structure and even if you do, you can supply values in the order of your choice. For any member whose value is not specified, the compiler would use a default value but you may not like some the result. Therefore, you should specify as many values as possible.

After initializing the LOGFONT variable, call the CreateFontIndirect() function. Its syntax is:

BOOL CreateFontIndirect(const LOGFONT* lpLogFont);

When calling this member function, pass the LOGFONT variable as a pointer, lpLogFont.

To select the newly created font, call the SelectObject() function. Once done, you can use the new font as you see fit. Here is an example:

LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg,
                               WPARAM wParam, LPARAM lParam)
{
    HDC         hDC;
    PAINTSTRUCT Ps;
    HFONT	    font;
    LOGFONT LogFont;

    switch(Msg)
    {
    case WM_PAINT:
	hDC = BeginPaint(hWnd, &Ps);
		        
        LogFont.lfStrikeOut = 0;
        LogFont.lfUnderline = 0;
        LogFont.lfHeight = 42;
        LogFont.lfEscapement = 0;
        LogFont.lfItalic = TRUE;

        font = CreateFontIndirect(&LogFont);
        SelectObject(hDC, font);
        TextOut(hDC, 20, 18, "James Kolowski", 14);

        DeleteObject(font);

	EndPaint(hWnd, &Ps);
	break;
    case WM_DESTROY:
	PostQuitMessage(WM_QUIT);
	break;
    default:
	return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    return 0;
}

Font Retrieval

If some text is displaying and you want to get the font properties of that text, you can call the GetObject() function. Its syntax is:

int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
 

Previous Copyright © 2003-2015, FunctionX, Inc. Next