Open GL Super Bible

Previous Table of Contents Next


TPalette Handling

Our finishing touch for the OWL sample is creating and realizing the RGB palette on devices that use palettes (256-color cards). Instead of maintaining a handle to the palette as in Chapter 8, here we’ll create an OWL object of type TPalette.

We declare a pointer to a TPalette in owlglwnv.h:

TPalette *m_pPalette;   // Logical Palette

and then manually add a member function to TOwlglWindowView that initializes the palette. This code, shown in Listing 22-7, is nearly identical to the function GetOpenGLPalette presented in Chapter 8, except that a TPalette object is constructed instead of a handle to a palette returned.

Listing 22-7 TPalette creation and initialization code

// Create the palette if necessary
void TOwlglWindowView::SetupPalette(HDC hDC)
        {
        PIXELFORMATDESCRIPTOR pfd;       // Pixel format descriptor
        LOGPALETTE *pPal;                // Pointer to memory for logical
                                         // palette
        int nPixelFormat;                // Pixel format index
        int nColors;                     // Number of entries in palette
        int i;                           // Counting variable

        BYTE RedRange,GreenRange,BlueRange;      // Range for each color
        entry
                                                 //   (7,7,and 3)
        // Get the pixel format index and retrieve the pixel format
        description
        nPixelFormat = GetPixelFormat(hDC);
        DescribePixelFormat(hDC, nPixelFormat,
                sizeof(PIXELFORMATDESCRIPTOR), &pfd);

        // Does this pixel format require a palette?  If not, do not
        // create a palette and just return
        if(!(pfd.dwFlags & PFD_NEED_PALETTE))
                return;

        // Number of entries in palette.  8-bit yields 256 entries
        nColors = 1 << pfd.cColorBits;

        // Allocate space for a logical palette structure plus all the
        // palette entries
        pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE)
        +nColors*sizeof(PALETTEENTRY));

        // Fill in palette header
        pPal->palVersion = 0x300;             // Windows 3.0
        pPal->palNumEntries = nColors;        // table size

        // Build mask of all 1's.  This creates a number represented by
        // having the low-order x bits set, where x = pfd.cRedBits,
        pfd.cGreenBits,
        // and pfd.cBlueBits.
        RedRange = (1 << pfd.cRedBits) - 1;
        GreenRange = (1 << pfd.cGreenBits) - 1;
        BlueRange = (1 << pfd.cBlueBits) - 1;

        // Loop through all the palette entries
        for(i = 0; i < nColors; i++)
                {
                // Fill in the 8-bit equivalents for each component
                pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) &
                RedRange;
                pPal->palPalEntry[i].peRed = (unsigned char)(
                         (double) pPal->palPalEntry[i].peRed * 255.0 /
                         RedRange);

                pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) &
                GreenRange;
                pPal->palPalEntry[i].peGreen = (unsigned char)(
                         (double)pPal->palPalEntry[i].peGreen * 255.0/
                         GreenRange);

                pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) &
                BlueRange;
                pPal->palPalEntry[i].peBlue = (unsigned char)(
                         (double)pPal->palPalEntry[i].peBlue * 255.0 /
                         BlueRange);

                pPal->palPalEntry[i].peFlags = (unsigned char) NULL;
                }

        // Create the palette
        m_pPalette = new TPalette(pPal);

        // Go ahead and select and realize the palette for this device
        context
        if(SelectPalette(hDC,m_pPalette->GetHandle(),FALSE) == NULL)
                ::MessageBox(NULL,"Cannot select Palette in Palette
                Creation", "Error",MB_OK);

        if(RealizePalette(hDC) == NULL)
                ::MessageBox(NULL,"Cannot realize Palette in Palette
                Creation", "Error",MB_OK);

        // Free the memory used for the logical palette structure
        free(pPal);
        }

Don’t forget to call this function in the WM_CREATE handler. This should be done before the rendering context is created:

// Set the pixel format for the device context
SetPixelFormat(m_hDC, nPixelFormat, &pfd);

// Create a 3-3-2 palette
SetupPalette(m_hDC);

// Create the rendering context
m_hRC = wglCreateContext(m_hDC);

Having used the ClassExpert to add message-response functions for WM_QUERYNEWPALETTE and WM_PALETTECHANGED, our code to realize the palette is shown in Listing 22-8.


Previous Table of Contents Next