Colors are always saved as four-byte LONG values. If the high byte is zero, then the low three bytes contain a normal RGB COLORREF. Otherwise, the value of the high byte is used as a bitfield of flags (notice that the values below are the indices of the bits that are set).
typedef enum { msocolorFlagPaletteIndex, // PALETTEINDEX macro msocolorFlagPaletteRGB, // PALETTERGB macro msocolorFlagSystemRGB, // MSOSYSTEMRGB msocolorFlagSchemeIndex, // MSOSCHEMECOLOR msocolorFlagSysIndex, // MSOSYSCOLOR } MSOCOLORINDEX;
Windows defines the first two. The third (SystemRGB) is a flag that it set on an otherwise normal RGB value to indicate to the rendering engine to bypass its normal halftone dithering process and just render the color directly using Windows.
The presence of either of the last two flags indicates that the low three bytes are an index into a predefined array of colors. For SchemeIndex colors, the host application provides the translation to RGB colors when necessary (PowerPoint and Excel both use this). SysIndex colors are indices into colors tracked by Escher itself:
typedef enum { msosyscolorButtonFace, // COLOR_BTNFACE msosyscolorWindowText, // COLOR_WINDOWTEXT msosyscolorMenu, // COLOR_MENU msosyscolorHighlight, // COLOR_HIGHLIGHT msosyscolorHighlightText, // COLOR_HIGHLIGHTTEXT msosyscolorCaptionText, // COLOR_CAPTIONTEXT msosyscolorActiveCaption, // COLOR_ACTIVECAPTION msosyscolorButtonHighlight, // COLOR_BTNHIGHLIGHT msosyscolorButtonShadow, // COLOR_BTNSHADOW msosyscolorButtonText, // COLOR_BTNTEXT msosyscolorGrayText, // COLOR_GRAYTEXT msosyscolorInactiveCaption, // COLOR_INACTIVECAPTION msosyscolorInactiveCaptionText, // COLOR_INACTIVECAPTIONTEXT msosyscolorInfoBackground, // COLOR_INFOBK msosyscolorInfoText, // COLOR_INFOTEXT msosyscolorMenuText, // COLOR_MENUTEXT msosyscolorScrollbar, // COLOR_SCROLLBAR msosyscolorWindow, // COLOR_WINDOW msosyscolorWindowFrame, // COLOR_WINDOWFRAME msosyscolor3DLight, // COLOR_3DLIGHT msosyscolorMax, // Count of system colors msocolorFillColor =0xF0, // Use the fillColor property msocolorLineOrFillColor, // Use the line color only if there is a line msocolorLineColor, // Use the lineColor property msocolorShadowColor, // Use the shadow color msocolorThis, // Use this color (only valid as described below) msocolorFillBackColor, // Use the fillBackColor property msocolorLineBackColor, // Use the lineBackColor property msocolorFillThenLine, // Use the fillColor unless no fill and line msocolorIndexMask =0xFF, // Extract the color index msocolorProcessMask =0xFFFF00, // All the processing bits msocolorModificationMask =0x0F00, // Just the function msocolorModFlagMask =0xF000, // Just the additional flags msocolorDarken =0x0100, // Darken color by parameter/255 msocolorLighten =0x0200, // Lighten color by parameter/255 msocolorAdd =0x0300, // Add grey level RGB(param,param,param) msocolorSubtract =0x0400, // Subtract grey level RGB(p,p,p) msocolorReverseSubtract =0x0500, // Subtract from grey level RGB(p,p,p) /* In the following "black" means maximum component value, white minimum. The operation is per component, to guarantee white combine with msocolorGray */ msocolorBlackWhite =0x0600, // Black if < uParam, else white (>=) msocolorInvert =0x2000, // Invert color (at the *end*) msocolorInvert128 =0x4000, // Invert by toggling the top bit msocolorGray =0x8000, // Make the color gray (before the above!) msocolorBParamMask =0xFF0000, // Parameter used as above msocolorBParamShift =16, // To extract the parameter value } MSOSYSCOLORINDEX;