Open GL Super Bible

Previous Table of Contents Next


Listing 21-2 CPalette creation and initialization code

// Initializes the CPalette object
void CMfcglView::InitializePalette(void)
        {
        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(m_hDC);
        DescribePixelFormat(m_hDC, nPixelFormat,
        sizeof(PIXELFORMATDESCRIPTOR), &pfd);

        // Does this pixel format require a palette?  If not, do not
           create a
        // palette and just return NULL
        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_GLPalette.CreatePalette(pPal);

// Go ahead and select and realize the palette for this device context
SelectPalette(m_hDC,(HPALETTE)m_GLPalette,FALSE);
RealizePalette(m_hDC);

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

Using the Class Wizard again to add message response functions for WM_QUERYNEWPALETTE and WM_PALETTECHANGED, our code to realize the palette is shown in Listing 21-3.

Listing 21-3 Code to realize CPalette for the view class

BOOL CMfcglView::OnQueryNewPalette()
        {
        // If the palette was created.
        if((HPALETTE)m_GLPalette)
                {
                int nRet;

                // Selects the palette into the current device context
                SelectPalette(m_hDC, (HPALETTE)m_GLPalette, FALSE);

                // Map entries from the currently selected palette to
                // the system palette.  The return value is the number
                // of palette entries modified.
                nRet = RealizePalette(m_hDC);

                // Repaint, forces remap of palette in current window
                InvalidateRect(NULL,FALSE); 
 
                return nRet;
                }

        return CView::OnQueryNewPalette();
        }

void CMfcglView::OnPaletteChanged(CWnd* pFocusWnd)
        {
        if(((HPALETTE)m_GLPalette != NULL) && (pFocusWnd != this))
               {
               // Select the palette into the device context
        SelectPalette(m_hDC,(HPALETTE)m_GLPalette,FALSE);

        // Map entries to system palette
        RealizePalette(m_hDC);

        // Remap the current colors to the newly realized palette
        UpdateColors(m_hDC);
        return;
        }

CView::OnPaletteChanged(pFocusWnd);
}

This code to realize the palette is very much like that in Chapter 8. Here, though, Windows does not send these messages to the CView-derived class directly, but rather to the application’s CMainFrame class. This is because Windows only sends palette messages to the application’s main window; it is this window’s responsibility to route the messages to any child windows that need to be notified.


Previous Table of Contents Next