| Herd Software Development
DaVinci Graphics Library
DaVinci Documentation Home Search Order

Leonardo: The CreateDIBPalette function

Takes the palette data from a DIB and creates a color palette which reflects the color palette of the DIB.


HDIB Handle of the source DIB.


If successful, the return value is the handle of the newly created palette, otherwise it is NULL. The handle must be released by the application using DeleteObject.

Notes regarding color palettes

While DIBs must store their palette and bitmap data in a single handle, actual display of a DIB in Windows requires two separate handles.

Practically speaking, palette handles are generally only needed when 256 color images need to be displayed, or when TrueColor images need to be optimized for 256 color displays. A 16 color display cannot use custom palettes (not even custom 4, 8 or 16 color palettes) and HiColor/TrueColor display depths don't require a palette to be specified.

What makes palette handles so important is the fact that even by late 1998, 256 color displays were still the norm in Windows. Forcing the user to switch a higher display depth in order to use a specific application, or to see images of reasonable quality, is considered extremely user unfriendly unless the application itself is intended for high-resolution image processing.

Bitmap handles only represent the actual bitmapped data. In 8 bit images, there is no way to determine the color of a pixel without a palette to match the pixel data. If you do not use a palette handle, Windows applies the standard 20 color palette to your image, and the results aren't likely to be very good.

While the handle of an 8 bit bitmap has no inherent value without a palette to go with it, you can always apply the same palette handle to several bitmaps, or "palette match" several 256 color images so that they can all draw their needed colors from the same palette. This may not appear necessary on a HiColor or TrueColor display, but this is generally the only way to create detailed color effects on 8 bit displays, since without palette matching, too many nasty side effects are likely to appear.

Palette handle generation is performed byCreatePalette. In order to connect the created palette with the bitmap which will use it, SelectPalette is used to apply the palette to the device context in which the bitmap data will be used. But palette handles do nothing but store color information. In order to actually apply that palette to the screen, you need to call RealizePalette. RealizePalette will change the actual hardware palette of the video card to match the "selected" palette, and inform all other windows with WS_OVERLAPPED or WS_POPUP styles that a new palette has been applied to the screen.via the WM_PALETTECHANGED. message. Note that child windows do not receive these messages automatically.

Applications that make active use of Windows palette information watch for the WM_PALETTECHANGED message and react accordingly. Most commonly they simply redraw images onscreen to conform to the new system palette. RealizePalette allows Windows to distinguish between foreground and background palettes. The foreground palette is assigned to the currently focussed window. Inactive windows are prevented from implementing the foreground palette, though. This means that "palette shift", or the application of inappropriate colors to pixel data, is a common side effect of using images of one palette in a foreground window and not updating the palettes of background windows which also display 8 bit images.

Foreground palettes differ from background palettes in the following manner:

When the screen's foreground palette is realized, Windows deletes the palette currently assigned to the hardware. Then it applies the new colors to the display and informs other windows through the WM_PALETTECHANGED message. These windows can now use only those colors which have not yet been used in generating the hardware palette. If the hardware palette is full, Windows tries to match onscreen colors to the colors of the hardware palette as best it can.

To insure that foreground windows always get the best display treatment, Windows sends the WM_QUERYNEWPALETTE message when focus is changed. The focussed window of the foreground application should look for this message and apply the new palette to its device context with RealizePalette. at the time it is received. Once the new palette has been applied to the hardware, WM_PALETTECHANGED messages are sent to tell other windows which window actually asked for the new palette. Intercepting WM_PALETTECHANGED might be a useful message to intercept if another application changed the palette, since it offers an opportunity to respond to the new palette, but it's not needed by the window which actually changed the palette.

Note the following important points regarding the palette-change process in Windows:

  1. WM_PALETTECHANGED and WM_QUERYNEWPALETTE only go to main windows. These messages are not received by controls such as buttons or edits, nor by MDI child windows.

  2. Applications that try to implement several color palettes to display as the foreground palette are at risk of nasty infinite-loop errors if message handling isn't coded carefully.

  3. Applications which implement no custom foreground palette on 8 bit displays will, at best, be stuck with the standard Windows 256 color palette; and at worst might be stuck with a custom palette previously applied by another window.

Generally speaking, applications which require palette updating should invoke update routines in at the following times:

  1. After every drawing operation culminating in a WM_PAINT message.

  2. On receipt of the WM_QUERYNEWPALETTE message.

  3. On receipt of WM_PALETTECHANGED messages which were not sent by the window itself.

MDI applications and apps which use custom bitmaps in dialog controls need to handle WM_PALETTECHANGED messages in such a way that all child windows receive notification of the need to perform palette-related routines.

Only the window which currently has focus is allowed to specify FALSE as the third parameter of SelectPalette.