70.1.3 Color Operations

Windows provides a set palette-manager functions which you can use to alter the colors in the system palette. These functions are designed especially for applications that require realistic colors when displaying bitmapped images.The code which supports these functions is part of a dynamic link library called the display driver. A display driver is a windows dll that converts GDI function calls to corresponding device commands. Not all display drivers support the palette-manager functions. For example, the display driver for the standard VGA does not while the display drivers for most super VGAs do. You should use the GetDeviceCaps function to determine whether or not this support is provided.

The palette-manager functions are powerful but potentially problematic—by altering the colors in the system palette, an application could also change the colors in every window on the desktop. In order to prevent this from happening, Windows provides the following:

An object called a logical palette that is associated with each application's device context

A set of messages that inform an application that changes were made to the system palette

A set of functions that you can use to create, alter, and remove logical palette

A logical palette is an array of colors that an application can use when drawing output. Each device context has a default logical palette which contains 20 entries. Of these 20 entries, 16 of the colors correspond to the colors found on a standard VGA display while the remaining 4 correspond to unique colors used by the window manager. The following table shows the default logical palette and the RGB triplets which are found in each entry:

Red Green Blue Index Value

0x00 0x00 0x00 0
0x80 0x00 0x00 1
0x00 0x80 0x00 2
0x80 0x80 0x00 3
0x00 0x00 0x80 4
0x80 0x00 0x80 5
0x00 0x80 0x80 6
0xC0 0xC0 0xC0 7
0xC0 0xDC 0xC0 8
0xA6 0xCA 0xF0 9
0xFF 0xFB 0xF0 10
0xA0 0xA0 0xA4 11
0x80 0x80 0x80 12
0xFF 0x00 0x00 13
0x00 0xFF 0x00 14
0xFF 0xFF 0x00 15
0x00 0x00 0xFF 16
0xFF 0x00 0xFF 17
0x00 0xFF 0xFF 18
0xFF 0xFF 0xFF 19

The 16 standard VGA colors are found at locations 0–7 and locations 12–19; the nonstandard colors are found at locations 8–11.

If your application creates or displays bitmapped images, it may be necessary to use more than the 20 default colors <and/or> it may be necessary to replace the 20 default colors with colors which are better suited to the image that is created or displayed. Before creating a custom logical palette, an application should determine the number of colors that are supported by the device. This is done by calling the GetDeviceCaps function and passing the NUMCOLORS constant as the second argument.

The colors requested in the logical palette are mapped to the system palette when the application's window is the active window on the desktop and when the application realizes the logical palette by calling the RealizePalette function. (If your application will replace the entire system palette with new colors, it should call the SetSystemPaletteUse function prior to realizing its logical palette.)

You create a logical palette by calling the CreatePalette function and passing a pointer to a LOGPALETTES data structure. You select a logical palette into your application's device context by calling the SelectPalette function. However, before you can draw in the client area of your application's window using the colors specified in your logical palette, you'll need to call the RealizePalette function. If your application's window is currently the active window, the colors requested in your logical palette are stored in the system palette and you can begin drawing. If your application's window is not the current active window, the colors requested in your application's logical palette may not be matched. (Whether or not the match occurs depends on such things as the size of the system palette, the size of your logical palette, the size of the logical palette associated with the active window, and the colors specified in both logical palettes.)

In order to prevent one application from altering the colors in other application's windows, three messages are supported by the Window Manager. If the currently active application realizes a custom palette by calling the RealizePalette function, Windows will send the WM_PALETTEISCHANGING message to all top-level and overlapped windows, indicating that the system palette is about to change. If the function executes successfully, Windows will then send the WM_PALETTECHANGED message to these windows indicating that the system palette has changed. When one of the top-level or overlapped windows is about to be activated, Windows sends the WM_QUERYNEWPALETTE message. Upon receiving this message, the corresponding application should call the RealizePalettefunction to realize its own logical palette.

Once a logical palette is created, an application can change or update its colors by calling the AnimatePalette or the SetPaletteEntries function. If your application's window is the active window on the desktop, you can update the colors on the screen immediately by calling the AnimatePalette function. If you want to update the logical-palette colors but continue displaying the current colors for a period of time, you can call the SetPaletteEntries function to alter the logical palette and then call the RealizePalette function when it is appropriate to actually update the image on the screen.

Your application can use the palette manager and the ChooseColor common dialog box to let a user select a custom color. The common dialog box is displayed by calling the ChooseColor function which returns an RGB triplet that identifies the user's request. You can retrieve the logical-palette index that identifies the closest color in the logical palette by calling the GetNearestPaletteIndex function. You can then use this index to create a pen, brush, or text output with the closest match of the specified color.

The Palette manager and the associated functions, messages, and data structures are designed primarily for applications that display bitmapped graphics—although they can be used to create color pens, brushes, and text, this involves unnecessary overhead. It is actually faster to use an RGB triplet (instead of a Palette index) to set the colors of objects in a device context. Once the ChooseColor function returns an RGB triplet, you can determine the closest match by calling the GetNearestColor function. You can then use the triplet returned by GetNearestColor to create a colored pen (by calling CreatePenIndirect), to create a colored brush (by calling CreateBrushIndirect), or to create colored text (by calling SetTextColor).