Displaying Text


Text can be surprisingly complex. To make the visual display of the text as readable as possible requires the creation and use of fonts, then decisions about mapping modes, kerning, and more.

Using Fonts

Fonts control the display characteristics of text. An X Windows client application can use the XLoadQueryFont() and XSetFont() functions to apply a font to a given graphics context (GC), as shown in the following code:

 #define FONT1 "-*-lucida-medium-r-*-*-12-*-*-*-*-*-*-*" Font           font1; XFontStruct   *font1Info; main() {   Display  *pDisplay;   int       iScreen;   GC        gc;   pDisplay  = XOpenDisplay("myDisplay");   iScreen   = DefaultScreen(pDisplay);   //+   //  get the Graphics Context   //-    gc        = DefaultGC(pDisplay,iScreen);   //+    //  attempt to load the font   //-   font1Info = XLoadQueryFont(pDisplay,FONT1);   font1     = font1Info->fid;   //+   //  Set the font in the GC   //-   XSetFont(pDisplay, gc,  font1);     

A Win32-based application follows much the same logic. That is, it creates or selects a font, retrieves a device context (DC), and then selects the font object to that DC. For example:

 #define FONT1  TEXT("Lucida Console"); HFONT hFont1; void fontDemo(HWND hWnd) {   HDC   hDC;   HFONT hOldFont;   //+   //  get the Device Context   //-   hDC    = GetDC(hWnd);   //+    //  attempt to load the system font   //-   hFont1 = (HFONT)GetStockObject (SYSTEM_FONT);   //+   //  Set the font in the GC   //-   hOldFont = (HFONT)SelectObject(hDC, hFont1); 

Table 11.6 shows how to reference fixed font types.

Table 11.6: Fixed Font References

Font Reference

Font Type

ANSI_FIXED_FONT

Windows fixed-pitch (monospace) system font.

ANSI_VAR_FONT

Windows variable-pitch (proportional space) system font.

DEVICE_DEFAULT_FONT

Microsoft Windows NT , Windows 2000, or Windows XP operating system: Device-dependent font.

DEFAULT_GUI_FONT

Default font for user interface objects such as menus and dialog boxes. This is Microsoft Sans Serif. Compare this with SYSTEM_FONT.

OEM_FIXED_FONT

Original equipment manufacturer (OEM)-dependent fixed-pitch (monospace) font.

SYSTEM_FONT

System font. By default, the system uses the system font to draw menus, dialog box controls, and text. Windows 95/98 or Windows NT: The system font is Microsoft Sans Serif. Windows 2000 or Windows XP: The system font is Tahoma.

SYSTEM_FIXED_FONT

Fixed-pitch (monospace) system font. This stock object is provided only for compatibility with 16-bit Windows earlier than version 3.0.

Note  

Win32 provides several utilities for adding and editing fonts.

The Eudcedit.exe utility, which comes with the operating system, allows the user to create unique characters such as logos and special characters. Eudcedit Help describes how to create, store, and use these characters in the font library.

The Charmap.exe utility, which comes with the operating systems, allows the user to view, find, and copy characters from the Windows, MS-DOS, and Unicode character sets. Charmap Help describes how to do so.

The Fontedit.exe utility, which comes with Visual Studio, allows the user to create and edit raster fonts.

Creating Fonts

Developers might want to create fonts to use in an application. The short example in this section uses the font specified by SYSTEM_FONT, which duplicates the default, although developers are likely to use something more creative. The Win32 CreateFont() , CreateFontIndirect() , and CreateFontIndirectEx() functions provide the ability to create logical fonts based on the fonts loaded on the system.

 #define MY_FONT_FACE TEXT("Lucida Console") //+ //  fontAttribute Option Bits //- #define fontAttribute_BOLD                      0x01 #define fontAttribute_CROSSED_OUT               0x02 #define fontAttribute_UNDERLINED                0x04 #define fontAttribute_ITALIC                    0x08 typedef struct {   unsigned char   fontSize;   unsigned char   fontStyle;   TCHAR          *fontFace; } tyFONT_ATTRIBUTE; HFONT createFont(tyFONT_ATTRIBUTE *fontAttributeObject) {   HFONT   hFont;   LOGFONT lf;   //+   //  these are completely arbitrary values for this example code.   //  they simply associate a width and height with a   //  font size number found in the tyFONT_ATTRIBUTE struct.   //      //  For example fontSize == 2 (used to index these two arrays)   //  will produce a 12x8 font   //-   int fontHeight[] = {8,8,12,16,16,24,32, 32,48,64,64,96,128,128,192};   int fontWidth [] = {6,8, 8,12,16,16,24, 32,32,48,64,64, 96,128,128};   //+   //  pick a font face   //-   lstrcpy(lf.lfFaceName, fontAttributeObject->fontFace);   //+   //  protect against running out of the arrays above   //  and pick a default behavior of "2"   //-   if (fontAttributeObject->fontSize  > 14)     fontAttributeObject->fontSize = 2;   if (fontAttributeObject->fontStyle & fontAttribute_BOLD)     lf.lfWeight  = FW_MEDIUM;   else     lf.lfWeight  = FW_LIGHT;   lf.lfItalic         = (unsigned char)(fontAttributeObject->fontStyle &                                          fontAttribute_ITALIC);   lf.lfUnderline      = (unsigned char)(fontAttributeObject->fontStyle &                                           fontAttribute_UNDERLINED);   lf.lfStrikeOut      = (unsigned char)(fontAttributeObject->fontStyle &                                          fontAttribute_CROSSED_OUT);   lf.lfEscapement     = 0;   lf.lfOrientation    = 0;   lf.lfCharSet        = ANSI_CHARSET;   lf.lfClipPrecision  = CLIP_DEFAULT_PRECIS;   lf.lfQuality        = DRAFT_QUALITY;   lf.lfPitchAndFamily = FF_MODERN  FIXED_PITCH;   lf.lfHeight         = fontHeight [ fontAttributeObject->fontSize ];   lf.lfWidth          = fontWidth  [ fontAttributeObject->fontSize ];      hFont               = CreateFontIndirect(&lf);   return(hFont); } //+ //  example using createFont() //- void fontDemo(HWND hWnd) {   HDC              hDC;   HFONT            hOldFont;   HFONT            hFont1;   tyFONT_ATTRIBUTE fontAttribute;   //+   //  get the Device Context   //-   hDC    = GetDC(hWnd);   //+    //   attempt to create a font   //-   fontAttribute.fontSize  = 2;   fontAttribute.fontStyle = (fontAttribute_BOLD  fontAttribute_ITALIC);   lstrcpy(fontAttribute.fontFace, MY_FONT_FACE);   hFont1 = createFont(&fontAttribute);   //+   //  Set the font in the GC   //-   hOldFont = (HFONT)SelectObject(hDC, hFont1); 

For more information about creating and using logical fonts in a Win32-based application, search the MSDN Web site ( http://msdn.microsoft.com/ ) for the article The Logical Font.

Device vs. Design Units

An application can retrieve font metrics for a physical font only after the font has been selected in a device context. When a user selects a font in a device context, the system scales the font for the device. The font metrics specific to the device are known as device units .

Portable metrics in fonts are known as design units . To apply them to a specified device, convert design units to device units by using the following formula:

DeviceUnits = ( DesignUnits / unitsPerEm ) * ( PointSize /72) * DeviceResolution

For a full explanation of device units, design units, and pixels, see the operating system Help or search the MSDN Web site ( http://msdn.microsoft.com/ ).

Windows Character Data Types

Table 11.7 lists the Windows character types. Most of the pointer-type names begin with a prefix of P or LP. For more information about character sets used by fonts, see the operating system Help or search the MSDN Web site ( http://msdn.microsoft.com/ ).

Table 11.7: Windows Character Types

Reference

Character Type

CHAR

An 8-bit Windows (ANSI) character.

LPCSTR

Pointer to a constant null- terminated string of 8-bit Windows (ANSI) characters.

LPCTSTR

LPCWSTR if UNICODE is defined, LPCSTR otherwise .

LPCWSTR

Pointer to a constant null-terminated string of 16-bit Unicode characters.

LPSTR

Pointer to a null-terminated string of 8-bit Windows (ANSI) characters.

LPTSTR

LPWSTR if UNICODE is defined, LPSTR otherwise.

PCHAR

Pointer to CHAR.

PCSTR

Pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters.

PCTSTR

PCWSTR if UNICODE is defined, PCSTR otherwise.

PCWCH

Pointer to a constant WCHAR.

PCWSTR

Pointer to a constant null-terminated string of 16-bit Unicode characters.

PSTR

Pointer to a null-terminated string of 8-bit Windows (ANSI) characters.

PTCHAR

Pointer to TCHAR.

PTSTR

PWSTR if UNICODE is defined, PSTR otherwise.

PWSTR

Pointer to a null-terminated string of 16-bit Unicode characters.

TBYTE

WCHAR if UNICODE is defined, CHAR otherwise.

TCHAR

WCHAR if UNICODE is defined, CHAR otherwise.

WCHAR

A 16-bit Unicode character.

A best practice with characters is to declare all characters and strings as TCHAR and use the TEXT() macro to declare static strings. For example:

 TCHAR myString[255]; wsprintf(myString,            TEXT("This is a good example %d is a %s \n"),            1950,            TEXT("Year")); 

For more information about wsprintf() and the rest of the string functions, see the operating system Help or search the MSDN Web site ( http://msdn.microsoft.com/ ).

Drawing Text

Drawing text can be simple or complicated. Because simple is often better, this discussion starts with the X Windows XDrawString() function and the Win32 TextOut() function. Both functions require a context to draw on, the x and y coordinates, the string, and the string length in characters. The examples in this section draw the string Hello World in the current font and colors at the specified coordinates.

It is often desirable to set a particular font or color before writing the text. These examples show how the two systems perform these tasks .

A programmer can code font and text display in Win32 as follows:

 #define rgbBlack (COLORREF)RGB(0x00,0x00,0x00) #define rgbWhite (COLORREF)RGB(0xFF,0xFF,0xFF) font = (HFONT)GetStockObject(OEM_FIXED_FONT); oldFont = (HFONT)SelectObject(hdc, font); // save old font SetTextColor (hdc, rgbBlack); SetBkColor   (hdc, rgbWhite); TextOut(hdc, x, y, "Hello World", 11); 

The preceding Win32 code example uses the COLORREF type, the RGB() macro, and the GetStockObject() function as follows:

  • The COLORREF value specifies an RGB color and is defined as shown here:

     typedef DWORD COLORREF; typedef DWORD *LPCOLORREF; 
  • The RGB macro selects a red, green, blue (RGB) color based on the arguments supplied and the color capabilities of the output device, as shown here:

     COLORREF RGB(BYTE  byRed  ,    // red component of color   BYTE  byGreen  ,  // green component of color   BYTE  byBlue  // blue component of color); 
  • The GetStockObject(int objectType) function retrieves a handle to one of the stock pens, brushes, fonts, or palettes. The return value must be cast to the expected type, as shown here:

     void foo() { HFONT hFont; HBRUSH hBrush;   hfont   = (HFONT)GetStockObject(DEFAULT_GUI_FONT);   hBrush  = (HBRUSH)GetStockObject(BLACK_BRUSH); } 

A programmer can code font and text display in X Windows as follows:

 font = XLoadQueryFont (display, "fixed"); XSetFont (display, gc, font->fid); XSetBackground(display, gc, WhitePixel(display, screen));  XSetForeground(display, gc, BlackPixel(display, screen));  XDrawString(display, d, gc, x, y, "Hello World", 11); 

X Windows provides explicit definitions of 8-bit and 16-bit character functions with XDrawString() and XDrawString16() . Likewise, Win32 provides TextOutA() for A SCII (8-bit characters) and TextOutW() for Wide Char (16-bit UNICODE characters). The TextOut() function is actually a macro that resolves correctly to TextOutA() or TextOutW() based on the status of the UNICODE definition, as follows:

 #define UNICODE #define _UNICODE TextOut()  // this will result in TextOutW()  #undef UNICODE #undef _UNICODE TextOut()  // this will result in TextOutA() 

One drawback of using XDrawString() and TextOut() is that nothing is done about erasing the background. Continually outputting strings to the same x and y coordinates results in a jumble of unreadable text strings, one upon the other. The X Windows library provides the DrawImageString() function, which calculates a rectangle containing the string and fills it with the background pixel color before drawing the text in the foreground pixel color. Win32 supports the ExtTextOut() function to provide this capability. Using the Win32 ExtTextOut() function requires the bounding rectangle to be calculated and passed into the function. This requires knowledge about the current font and logical display units.

Calculating Text Metrics

The X Windows programmer can rely on XTextWidth() to get the length of a character string in pixels. The Win32 programmer must work a little harder to get this number.

Understanding Mapping Mode

First, it is necessary to understand mapping mode. The mapping mode defines the unit of measure used to transform page-space units into device-space units. It also defines the orientation of the device s x and y axes.

A mapping mode is a scaling transformation that specifies the size of the units used for drawing operations. The mapping mode can also perform translation. In some cases, the mapping mode alters the orientation of the x and y axes in device space.

The default mapping mode is MM_TEXT. One logical unit equals one pixel. Positive x is to the right, and positive y is down. This mode maps directly to the device s coordinate system.

The Win32 SetMapMode function sets the mapping mode of the specified device context, as shown in the following code:

 int SetMapMode(HDC hdc,        // handle to device context   int fnMapMode   // new mapping mode); 

Ultimately, to calculate the size of a string in pixels it is necessary for the current mapping mode to be MM_TEXT. The Win32 programmer can either assume the current mapping mode is the default MM_TEXT, set it to MM_TEXT by calling SetMapMode() , or make sure it is MM_TEXT by using GetMapMode() to retrieve it. (For more information, search for MM_TEXT on the MSDN Web site, http://msdn.microsoft.com/ .)

Calculating Character Size and String Length

The Win32 GetTextExtentPoint32() function returns the width and height of a string of text in logical units, as shown in the follwoing code. (Recall that setting the mapping mode to MM_TEXT returns logical units as pixels.)

 BOOL GetTextExtentPoint32(HDC     hdc,       // handle to DC   LPCTSTR lpString,  // text string   int     cbString,  // characters in string   LPSIZE  lpSize     // string size); 

The size structure looks like the following and is defined in Windef.h:

 typedef struct tagSIZE {    LONG cx;    LONG cy;  } SIZE, *PSIZE, *LPSIZE; 

The Win32 GetTextMetrics() function fills a TEXTMETRIC structure with all the information about the device context s currently selected font, as shown in the following code. The programmer can use this information to perform any number of scaling or text size calculations.

 BOOL GetTextMetrics(HDC          hdc,   // handle to DC   LPTEXTMETRIC lptm   // text metrics); 

The TEXTMETRIC structure contains basic information about a physical font, as shown in the following example. All sizes are specified in logical units; that is, they depend on the current mapping mode of the display context.

 typedef struct tagTEXTMETRIC {    LONG  tmHeight;    LONG  tmAscent;    LONG  tmDescent;    LONG  tmInternalLeading;    LONG  tmExternalLeading;    LONG  tmAveCharWidth;    LONG  tmMaxCharWidth;    LONG  tmWeight;    LONG  tmOverhang;    LONG  tmDigitizedAspectX;    LONG  tmDigitizedAspectY;    TCHAR tmFirstChar;    TCHAR tmLastChar;    TCHAR tmDefaultChar;    TCHAR tmBreakChar;    BYTE  tmItalic;    BYTE  tmUnderlined;    BYTE  tmStruckOut;    BYTE  tmPitchAndFamily;    BYTE  tmCharSet;  } TEXTMETRIC, *PTEXTMETRIC; 

More Win32 Text Functions

The following Win32 functions are also useful for working with text:

  • DrawText()

  • CreateSolidBrush()

  • GetSysColor()

  • SetTextColor()

  • GrayString()

This section discusses these functions and shows examples of their use.

The DrawText() function draws formatted text in the specified rectangle, as shown in the following example. It formats the text according to the specified method, expanding tabs, justifying characters, breaking lines, and so forth.

 int DrawText(HDC     hDC,      // handle to DC   LPCTSTR lpString, // text to draw   int     nCount,   // text length   LPRECT  lpRect,   // formatting dimensions   UINT    uFormat   // text-drawing options); 

The CreateSolidBrush() function creates a logical brush that has the specified solid color, as shown in the following example:

 HBRUSH CreateSolidBrush(COLORREF crColor // brush color value); 

The GetSysColor() function retrieves the current color of the specified display element, as shown in the following example. Display elements are the parts of a window and the Windows display that appear on the system display screen.

 DWORD GetSysColor(int nIndex); 

The SetTextColor() function sets the text color for the specified device context to the specified color, as shown in the following example:

 COLORREF SetTextColor(HDC      hdc,           // handle to DC   COLORREF crColor        // text color); 

The following example incorporates the use of DrawText() , CreateSolidBrush() , GetSysColor() , and SetTextColor() :

 RECT myRectangle; //+ //   create a brush //- HBRUSH myBackgroundBrush =    CreateSolidBrush(GetSysColor(COLOR_BACKGROUND) // color of system background); //+ //  set the text color to the systems button text color //- SetTextColor(hdc,    GetSysColor(COLOR_BTNTEXT) //color of text on buttons); // calculate myRectangle //+ //  fill in (erase) the area inside the rectangle with the  //  systems background color //- FillRect(hdc, &myRectangle, myBackgroundBrush); //+ //  The DrawText function uses the device contexts selected font, text  //  color, and background color to draw the text. Unless the DT_NOCLIP  //  format is used, DrawText clips the text so that it does not appear  //  outside the specified rectangle.  //- DrawText(hdc,            myString,            _tcsclen(myString), // use _tcsclen() vs. strlen()           &myRectangle,            (DT_CENTER  DT_SINGLELINE)); 

The GrayString() function draws gray text at the specified location, as shown in the following example. The function draws the text by copying it into a memory bitmap, graying the bitmap, and then copying the bitmap to the screen. The function grays the text regardless of the selected brush and background. GrayString() uses the font currently selected for the specified device context.

 BOOL GrayString(HDC             hDC,           // handle to DC   HBRUSH          hBrush,        // handle to the brush   GRAYSTRINGPROC  lpOutputFunc,  // callback function   LPARAM          lpData,        // application-defined data   int             nCount,        // number of characters   int             X,             // horizontal position   int             Y,             // vertical position   int             nWidth,        // width   int             nHeight        // height); 

Text Widgets and Controls

A text widget or control is used to display, enter, and edit text. The exact functionality of a text widget or control depends upon how its resources are set.

In X Windows, the widget functionality is set as shown in the following example:

 text = XtVaCreateManagedWidget ("myTextWidget",                                   asciiTextWidgetClass,                                   parentWidget,                                  XtNfromHoriz,                                   quit,                                   XtNresize,                                  XawtextResizeBoth,                                   XtNresizable,                                   True,                                   NULL); 

In Motif, the widget functionality is set as shown in the following example:

 main (int argc, char *argv[]) {   Widget       mainWidget;   Widget       textWidget;   XtAppContext appContext;   mainWidget =      XtVaOpenApplication (&appContext,                            "TextExample",                            NULL,                            0,                            &argc,                            argv,                            NULL,                            sessionShellWidgetClass,                            NULL); (   )      textWidget =      XmCreateText (mainWidget,"textWidget",NULL,0); ()   XtAppMainLoop(appContext); } 

In Win32 and GDI, the control functionality is set as shown in the following example:

 //+ // Create an edit Control. //- HWND handleToThisEditControl; handleToThisEditControl =    CreateWindow(TEXT("EDIT"),      // the type of control                 TEXT("Some Text"), // edit control text                 (WS_CHILD                      WS_VISIBLE                        ES_READONLY                         ES_LEFT                             ES_UPPERCASE), // the control style                 XpositionInParent,                  yPositionInnParent,                  CONTROL_WIDTH_IN_DEVICE_UNITS,                 CONTROL_HEIGHT_IN_DEVICE_UNITS,                  handleOfParentWindow, // parent window                 (HMENU)NUMBER_USED_TO_ID_THIS_EDIT_CONTROL,                 appContext,                  NULL); //+ //  Turn off Read Only //- SendMessage(handleToThisEditControl ,              EM_SETREADOINLY,              (WPARAM)FALSE,   // set read only false              (LPARAM)NULL);                                            //+ //  set the edit controls text //- SetWindowText(handleToThisEditControl, TEXT("Some New Text")); //+ //  retrieve the edit controls text as text //- GetWindowText(handleToThisEditControl,                myStringBuffer,                myStringBufferMaxSize); //+ //  retrieve the edit controls text as an integer //- myIntegerValue =    GetDlgItemInt(handleOfParentWindow,                  NUMBER_USED_TO_ID_THIS_EDIT_CONTROL,                  &resultFlag,   // did the translation succeed ?                  FALSE);       // no this is an unsigned number 



UNIX Application Migration Guide
Unix Application Migration Guide (Patterns & Practices)
ISBN: 0735618380
EAN: 2147483647
Year: 2003
Pages: 134

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net