Graying Character Strings

Although TextOut and DrawText are the functions used most often to write character strings, Windows has another text output function called GrayString that exists for the express purpose of displaying grayed text. Windows uses grayed text most often to show disabled items in menus and dialog boxes. However, you might also want to use some grayed text within your client area. GrayString is complex and has some limitations. I'll begin by explaining how GrayString generally works and then show you an easier way to use it. Here's the general syntax:

GrayString (hdc, hBrush, lpfnOutputFunction, dwData,

nCount, xStart, yStart, xWidth, yHeight) ;

GrayString uses a call-back function of the form:

BOOL FAR PASCAL OutputFunction (hdc, dwData, nCount)

HDC hdc ;

DWORD dwData ;

short nCount ;

{

[other program lines]

return 1 ;

}

The name of this function must be included in the EXPORTS section of your mod- ule definition (.DEF) file. You must obtain a far pointer to the function by calling MakeProcInstance:

lpfnOutputFunction = MakeProcInstance (hInstance, OutputFunction) ;

This far pointer is the third parameter to GrayString. The dwData and nCount parameters to GrayString are passed as parameters to this call-back function. Most often, dwData is a far pointer (converted to a doubleword) to the text you want to gray, and nCount is set to the number of characters.

Here's what happens when you call GrayString. Windows creates a memory device context and a monochrome bitmap using the xWidth and yHeight parameters to GrayString. It selects the bitmap into the memory device context and passes to the call-back function the memory device context handle and the dwData and nCount parameters.

Within the call-back function, you draw on this memory device context. The text color has been set to black and the background color to white. The drawing you do is relative to the upper left corner of this memory device context rather than the upper left corner of your original device context. The output function returns a 1 if all goes well. Windows then uses the PatBlt function to perform a bitwise OR operation on this memory device context and the 50-percent gray brush. (The ROP code is 0xFA0089.) As a result, the white pixels in the memory device context are unchanged, and half the black pixels become white pixels.

Windows then performs a BitBlt operation on this memory device context and the device context you specified in the GrayString call (probably your client-area device context), starting at the point (xStart, yStart). The ROP code is 0xB8074A, which corresponds to a Boolean operation of:

((Destination ^ Pattern) & Source) ^ Pattern

You may recall this particular ROP code from Chapter 13. The pixels in your original device context (the destination) that correspond to white pixels in the memory device context (the source) are unchanged. The pixels in your original device context that correspond to black pixels in the memory device context are colored with the brush specified in the GrayString call. In other words, every other pixel that you color black in the memory device context is colored with the brush in your original device context.

The GrayString function has certain limitations. Here are the most important ones. GrayString requires the MM_TEXT mapping mode. This is because the xWidth and yHeight parameters to GrayString are treated as device units when Windows creates the bitmap, but they are treated as logical units when PatBlt and BitBlt are called.

The memory device context has default device context attributes when Windows calls the output function. Therefore, if you've selected a non–default font into your device context before calling GrayString, this font will not be selected in the memory device context. You can, however, select the same font into the memory device context within the output function.

Normally, the dwData parameter points to a character string, and nCount is the number of characters, but dwData and nCount can really be anything you want. Be aware of the following:

If nCount is 0, then Windows assumes that dwData is a zero-terminated character string and calculates the number of characters. That calculated value is passed to the call-back function.

If you specify an xWidth or yHeight value of 0, then Windows computes the height and width of the string pointed to by dwData. It uses the memory device context for this calculation, so these heights and widths are based on the height and width of the system font, regardless of the font you eventually use in the call-back function.

If the output function returns 0, then Windows assumes that an error has occurred and doesn't draw anything on your original device context. However, if you set the nCount parameter to -1 and the output function returns 0, then Windows simply transfers the memory device context intact to your original device context without first graying it. In this case, you have to determine the number of characters in the character string yourself, within the call-back function.

If you have a good feel for bitmaps, memory device contexts, and the raster operations, you might want to sidestep these limitations by writing your own text-graying function. Or you might prefer to use the easy GrayString syntax presented below.