Accessing a Full Palette Using SYSPAL_NOSTATIC
The Palette Manager usually reserves twenty static colors in the palette for use in drawing captions, menus, text, scroll bars, window frames, and other system elements. These static colors ensure a common color scheme across all applications, but this leaves only 236 palette entries available to each application. A Windows graphics application requiring a full palette of 256 colors has two options, outlined here.
The first option is to incorporate the static colors into the palette at runtime, knowing that the RGB values of the colors may change slightly from display driver to display driver. This means that the palette will vary slightly when the application runs on different platforms, but it ensures the consistent look and feel between the application and coexisting applications in the system.
The static colors are defined as follows:
Index | Color | Index | Color |
0 | Black | 246 | Cream |
1 | Dark Red | 247 | Light Gray |
2 | Dark Green | 248 | Medium Gray |
3 | Dark Yellow | 249 | Red |
4 | Dark Blue | 250 | Green |
5 | Dark Magenta | 251 | Yellow |
6 | Dark Cyan | 252 | Blue |
7 | Light Gray | 253 | Magenta |
8 | Money Green | 254 | Cyan |
9 | Sky Blue | 255 | White |
If you can accept the limitation of including these colors in your palette and determining their exact RGB values at runtime (using GetSystemPaletteEntries), you can skip the rest of this article.
The second option is to tell the Palette Manager to make 18 of the twenty static colors available to the application, with entry 0 remaining black and entry 255 remaining white. However, choosing to control those palette entries means you'll have some more intimate relations with the Palette Manager.
To change the use of the static colors in the system palette, you use the SetSystemPaletteUse API, passing either SYSPAL_STATIC or SYSPAL_NOSTATIC. Setting the palette use to SYSPAL_NOSTATIC gives you access to palette entries 1 through 254. Your palette must map entry 0 to RGB(0, 0, 0) and entry 255 to RGB(255, 255, 255), but black and white are standard in most palettes anyway.
Ordinarily, Windows uses entries 0-9 and 246-255 to draw captions, borders, menus, and text, and it will continue to do so after you've changed the RGB values of those palette entries unless you tell it to do otherwise. If you do not inform the operating system of your changes, your application and all others in the system will become very messy and your application will be condemned by its peers as unfriendly.
You want your application to be friendly to the operating system and to the other active applications. You can handle this in two ways: you can make your application a full-screen window with no controls, thereby taking over the entire screen and the full palette, or you can tell the operating system to use different palette entries to draw its captions, borders, menus, and text so that other visible windows do not appear completely strange. In either case, you must restore the static colors when your application becomes inactive or exits.
The following procedure handles the switch between SYSPAL_STATIC and SYSPAL_NOSTATIC for you, managing the mapping and remapping of the system colors for you through the Windows functions GetSysColor and SetSysColors. It stores the current mapping of the system colors before switching to SYSPAL_NOSTATIC mode and restores them after switching back to SYSPAL_STATIC mode.
To use the AppActivate() function in an application, call AppActivate((BOOL)wParam) in response to a WM_ACTIVATEAPP message and call AppActivate(FALSE) before exiting to restore the system colors. This will set the system palette use and remap the system colors when your application is activated or deactivated.
The PALANIM sample (in the SAMPLES\PALANIM subdirectory of the WinG development kit) uses this function to take over the static colors at run time and clean up before it exits.
Click Here to copy this code sample to the clipboard.
#define NumSysColors (sizeof(SysPalIndex)/sizeof(SysPalIndex[1]))
#define rgbBlack RGB(0,0,0)
#define rgbWhite RGB(255,255,255)
//*** These are the GetSysColor display element identifiers
static int SysPalIndex[] = {
};
//*** This array translates the display elements to black and white
static COLORREF MonoColors[] = {
rgbBlack,
rgbWhite,
rgbWhite,
rgbWhite,
rgbWhite,
rgbBlack,
rgbBlack,
rgbBlack,
rgbBlack,
rgbBlack,
rgbWhite,
rgbWhite,
rgbWhite,
rgbWhite,
rgbBlack,
rgbWhite,
rgbWhite,
rgbBlack,
rgbBlack
};
//*** This array holds the old color mapping so we can restore them
static COLORREF OldColors[NumSysColors];
//*** AppActivate sets the system palette use and
//*** remaps the system colors accordingly.
void AppActivate(BOOL fActive)
{
HDC hdc;
int i;
//*** Just use the screen DC
hdc = GetDC(NULL);
//*** If the app is activating, save the current color mapping
//*** and switch to SYSPAL_NOSTATIC
if (fActive && GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
{
//*** Store the current mapping
for (i=0; i<NumSysColors; i++)
OldColors[i] = GetSysColor(SysPalIndex[i]);
//*** Switch to SYSPAL_NOSTATIC and remap the colors
SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
SetSysColors(NumSysColors, SysPalIndex, MonoColors);
}
else if (!fActive)
{
//*** Switch back to SYSPAL_STATIC and the old mapping
SetSystemPaletteUse(hdc, SYSPAL_STATIC);
SetSysColors(NumSysColors, SysPalIndex, OldColors);
}
//*** Be sure to release the DC!
ReleaseDC(NULL,hdc);
}