Windows 3.11 Paintbrush Custom Palette Processing

In Microsoft Windows 3.11, Paintbrush handled custom color palette selection by combining user input from an RGB slider interface with the underlying Win16 Graphics Device Interface (GDI) palette manager. This process relied on querying display hardware capabilities, generating a 24-bit logical palette, and using GDI functions to map or dither those colors into the physical hardware palette of the era's 16-color or 256-color display adapters.

User Selection via the Edit Colors Interface

Custom color creation in Paintbrush began by double-clicking any swatch in the bottom palette bar or selecting "Edit Colors" from the Options menu. This triggered a modal dialog box containing three sliders representing Red, Green, and Blue channels. Each channel accepted integer values ranging from 0 to 255, effectively allowing the user to define a theoretical color from an 8-bit-per-channel (24-bit true color) space containing over 16.7 million variations.

Logical Palette Construction

Once a user confirmed a color choice, Paintbrush did not send raw RGB values straight to the screen memory. Instead, it updated an internal logical palette structure:

  1. LOGPALETTE Allocation: Paintbrush created or updated a Win16 LOGPALETTE memory structure, which included a version identifier, the count of entries (typically 28 default swatches), and an array of PALETTEENTRY structures.
  2. Flag Assignment: Each PALETTEENTRY stored the chosen 8-bit Red, Green, and Blue values, alongside specific flag bytes (such as peFlags = 0 for standard matching, or PC_RESERVED when attempting to prevent identity palette sharing).

Hardware Capability Check and GDI Interaction

Before attempting to display the chosen color, Paintbrush evaluated the video driver's capabilities via the GDI function GetDeviceCaps using the RASTERCAPS index:

  • Palettized Displays (Typically 256 Colors): If the display driver returned the RC_PALETTE flag, the video hardware used an indexed palette controlled by DAC (Digital-to-Analog Converter) registers. In this scenario, Paintbrush called CreatePalette to generate an HPALETTE handle, followed by SelectPalette to associate it with the application’s Device Context (DC). Finally, calling RealizePalette forced the GDI to reconcile the logical palette with the system's 256-color physical hardware palette. If space permitted, the video card updated its hardware lookup table to match the custom RGB mix exactly.
  • Non-Palettized Displays (Standard 16-Color VGA): Standard VGA modes were strictly limited to a fixed 16-color IRGB hardware scheme that did not support dynamic palette realization through the driver. When running in these modes, Paintbrush and GDI bypassed hardware palette modification. Instead, GDI calculated the Euclidean distance between the requested RGB triple and the 16 static system colors to pick the nearest solid match, or it generated a dithered pattern (an alternating grid of two or more solid colors) across an 8x8 pixel brush pattern.

Window Focus and Palette Conflict Resolution

Because Windows 3.11 operated as a cooperative multitasking operating system, multiple running applications shared a single physical hardware palette. Paintbrush responded to two essential Windows messages to manage custom palette priority:

  • WM_QUERYNEWPALETTE: Sent when Paintbrush gained active focus. Paintbrush realized its logical palette as the foreground palette, taking priority over hardware palette slots.
  • WM_PALETTECHANGED: Sent when another program altered the system palette. Paintbrush re-realized its colors in the background, updating its swatch indicators to map to the closest available physical colors without resetting the user's underlying RGB values.

Palette File Serialization

Paintbrush also allowed custom palettes to be exported and imported using .PAL files. When saving, Paintbrush serialized the active array of RGB entries to disk. Upon loading, Paintbrush read the file, updated the active LOGPALETTE structure, and immediately re-executed SelectPalette and RealizePalette to refresh the on-screen palette interface and canvas elements.