Using DirectDraw Palettes in Windowed Mode
The IDirectDrawPalette interface methods write directly to the hardware when the display is in exclusive (full-screen) mode. However, when the display is in nonexclusive (windowed) mode, the IDirectDrawPalette interface methods call the GDI's palette handling functions to work cooperatively with other windowed applications. This affects how you use palettes in a windowed DirectDraw application in the following ways:
·You must set the peFlags member of the PALETTEENTRY structure (passed to the IDirectDraw2::CreatePalette and IDirectDrawPalette::SetEntries methods) carefully.
·You should not attempt to alter the Windows static palette entries (indices 0 through 9 and 246 through 255).
The discussion in the following topics assumes that you have created a primary surface and a typical Windows window and that the Windows desktop is in an 8-bit palettized mode.
·Types of Palette Entries in Windowed Mode
·Calling IDirectDraw::CreatePalette in Windowed Mode
·Calling IDirectDrawPalette::SetEntries in Windowed Mode
Types of Palette Entries in Windowed Mode
In nonexclusive (windowed) mode, each type of palette entry must have a different set of peFlags members in the corresponding PALETTEENTRY structure in the array that you pass to the IDirectDraw2::CreatePalette or IDirectDrawPalette::SetEntries methods. In exclusive (full-screen) mode, you do not need to worry about the peFlags member; it is ignored. In nonexclusive (windowed) mode, the entries in your palette are one of the following three types:
·Windows static entries. Typically, Windows reserves entries 0 through 9 and 246 through 255 for itself and will not allow any application to change the color values for those entries. Although an application could build a 256-entry palette that includes these colors by calling the GetSystemPaletteEntries Win32 function, it is more effective for an application to refer to these entries directly. The application can do this by specifying which physical palette index a given entry in the palette table should map to, store the PC_EXPLICIT flag in the peFlags member of the PALETTEENTRY structure, and then set the peRed member equal to the index in the physical palette to which the entry should map. An application could also call the SetSystemPaletteUse Win32 function to force Windows to reserve only entries 0 and 255. In this case, you should set only entries 0 and 255 of your PALETTEENTRY structure to PC_EXPLICIT.
·Animated entries. These are entries your application can change to create palette animation effects. If the application specifies the PC_RESERVED flag for an animated entry, Windows will not allow any other application to map its logical palette entry to that physical entry. This prevents other applications from cycling their colors when your application sets a different color in that entry.
·Non-animated entries. These are entries your application will not change. Non-animated entries are simply filled with the PC_NOCOLLAPSE flag, which tells Windows not to substitute some other already-allocated physical palette entry.
In short, you should define the three types of entries in the PALETTEENTRY structure as follows:
Entry type | peFlags values | peRed, peGreen, and peBlue values |
Windows static (indices 0-9 and 246-255 or 0 and 255) | PC_EXPLICIT | peRed = index, peGreen = 0, and peBlue = 0 |
Animated entries | PC_RESERVED | PC_NOCOLLAPSE | Color values |
Non-animated entries | PC_NOCOLLAPSE | Color values |
Calling IDirectDraw2::CreatePalette in Windowed Mode
The following example illustrates how to create a DirectDraw palette in nonexclusive (windowed) mode. It is vital that you set up every one of the 256 entries in the PALETTEENTRY structure that you submit to the IDirectDraw2::CreatePalette method.
LPDIRECTDRAW lpDD; // Assumed to be initialized previously
PALETTEENTRY pPaletteEntry[256];
int index;
HRESULT ddrval;
LPDIRECTDRAWPALETTE lpDDPal;
// First set up the Windows static entries.
for (index = 0; index < 10 ; index++)
{
// The first 10 static entries:
pPaletteEntry[index].peFlags = PC_EXPLICIT;
pPaletteEntry[index].peRed = index;
pPaletteEntry[index].peGreen = 0;
pPaletteEntry[index].peBlue = 0;
// The last 10 static entries:
pPaletteEntry[index+246].peFlags = PC_EXPLICIT;
pPaletteEntry[index+246].peRed = index+246;
pPaletteEntry[index+246].peGreen = 0;
pPaletteEntry[index+246].peBlue = 0;
}
// Now set up private entries. In this example, the first 16
// available entries are animated.
for (index = 10; index < 26; index ++)
{
pPaletteEntry[index].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
pPaletteEntry[index].peRed = 255;
pPaletteEntry[index].peGreen = 64;
pPaletteEntry[index].peBlue = 32;
}
// Now set up the rest, the non-animated entries.
for (; index < 246; index ++) // Index is set up by previous for loop
{
pPaletteEntry[index].peFlags = PC_NOCOLLAPSE;
pPaletteEntry[index].peRed = 25;
pPaletteEntry[index].peGreen = 6;
pPaletteEntry[index].peBlue = 63;
}
// All 256 entries are filled. Create the palette.
ddrval = lpDD->CreatePalette(DDPCAPS_8BIT, pPaletteEntry,
&lpDDPal,NULL);
Calling IDirectDrawPalette::SetEntries in Windowed Mode
The rules that apply to the PALETTEENTRY structure used with the IDirectDraw2::CreatePalette method also apply to the IDirectDrawPalette::SetEntries method. Typically, you will maintain your own array of PALETTEENTRY structures, so you will not need to rebuild it. When necessary, you can modify the array, and then call IDirectDrawPalette::SetEntries when it is time to update the palette.
In most circumstances, do not attempt to set any of the Windows static entries when in nonexclusive (windowed) mode or you will get unpredictable results. The only exception is when you reset the all 256 entries. For palette animation, you typically change only a small subset of entries in your PALETTEENTRY array. You submit only those entries to IDirectDrawPalette::SetEntries. If you are resetting such a small subset, you must reset only those entries marked with the PC_NOCOLLAPSE and PC_RESERVED flags. Attempting to animate other entries can have unpredictable results.
The following example illustrates palette animation in nonexclusive mode:
LPDIRECTDRAW lpDD; // Assumed to be initialized previously
PALETTEENTRY pPaletteEntry[256]; // Assumed to be initialized previously
LPDIRECTDRAWPALETTE lpDDPal; // Assumed to be initialized previously
int index;
HRESULT ddrval;
PALETTEENTRY temp;
// Animate some entries. Cycle the first 16 available entries.
// They were already animated.
temp = pPaletteEntry[10];
for (index = 10; index < 25; index ++)
{
pPaletteEntry[index] = pPaletteEntry[index+1];
}
pPaletteEntry[25] = temp;
// Set the values. Do not pass a pointer to the entire palette entry
// structure, but only to the changed entries.
ddrval = lpDDPal->SetEntries(
0, // Flags must be zero
10, // First entry
16, // Number of entries
& (pPaletteEntry[10])); // Where to get the data