Windows NT Systems Programming: Spring 1999

[ Home | Syllabus | Course Notes | Assignments | Search]


Palettes, Bitmaps (Chapter 12)


BitMapped Displays

Display Technology and Video Drivers.


The Color Dimension


Color Palettes


Mapping onto the Palette.

Pens: Map COLORREF to nearest static color

Brushes: COLORREF is dithered using static colors

How to Access the other 236 colors? (Given that it is shared among all applications?)


Logical Palettes


Creating Custom Logical Palettes

First fill in the LOGPALETTE data structures.

typedef struct tagLOGPALETTE {
    WORD         palVersion; 
    WORD         palNumEntries; 
    PALETTEENTRY palPalEntry[1];
    // doesn't really allocate just one - use fact that array entries are consecutive
    // and allocate extra elements right after a LOGPALETTE Data type (see below)
} LOGPALETTE; 
and
typedef struct tagPALETTEENTRY { // pe 
    BYTE peRed; 
    BYTE peGreen; 
    BYTE peBlue; 
    BYTE peFlags; 
} PALETTEENTRY;
struct {
   LOGPALETTE lp;
   PALETTEENTRY ape[31];
   // since this array appears right after LOGPALETTE data object it effectively is added to
   // palPalEntry - so there will be 32 items in the array.
} pal;
LOGPALETTE* pLP = (LOGPALETTE*) &pal;
pLP->palVersion = 0x300; // always use this value
pLP->palNumEntries = 32;
// would allocate 32 colors in this palette
// after setting values for all 32 entries, create a palette with
m_palette.CreatePalette(pLP);

Realizing a Palette


Drawing with a Logical Palette


WM_QUERYPALETTE and WM_PALETTECHANGED

Two Messages sent about palettes:

In either case, the normal response is to realize the palette and repaint.


Palette Demo

class CMainWindow : public CFrameWnd
{
private:
    CPalette m_palette;

    void DoGradientFill (CDC*, CRect*);
    void DoDrawText (CDC*, CRect*);

public:
    CMainWindow ();

protected:
    afx_msg int OnCreate (LPCREATESTRUCT);
    afx_msg BOOL OnEraseBkgnd (CDC*);
    afx_msg void OnPaint ();
    afx_msg BOOL OnQueryNewPalette ();
    afx_msg void OnPaletteChanged (CWnd*);

    DECLARE_MESSAGE_MAP ()
};

rainbow.gif (2243 bytes)


Implementation

 


#define FONTHEIGHT 72

int CMainWindow::OnCreate (LPCREATESTRUCT lpcs)
{
    if (CFrameWnd::OnCreate (lpcs) == -1)
        return -1;

    CClientDC dc (this);
    if (dc.GetDeviceCaps (RASTERCAPS) & RC_PALETTE) {
        struct {
            LOGPALETTE lp;
            PALETTEENTRY ape[63]; // 64 shades of blue
        } pal;

        LOGPALETTE* pLP = (LOGPALETTE*) &pal;
        pLP->palVersion = 0x300;
        pLP->palNumEntries = 64;

        for (int i=0; i<64; i++) {
            pLP->palPalEntry[i].peRed = 0;
            pLP->palPalEntry[i].peGreen = 0;
            pLP->palPalEntry[i].peBlue = 255 - (i * 4); // From Black to Blue
            pLP->palPalEntry[i].peFlags = 0;
        }
        m_palette.CreatePalette (pLP); // Create this blue palette
    }
    return 0;
}

BOOL CMainWindow::OnEraseBkgnd (CDC* pDC)
{
    CRect rect;
    GetClientRect (&rect);
// return true; // this returns without painting a new background - so you get a transparent window - try it
    CPalette* pOldPalette;
    if ((HPALETTE) m_palette != NULL) {
        pOldPalette = pDC->SelectPalette (&m_palette, FALSE);
        pDC->RealizePalette ();
    }

    DoGradientFill (pDC, &rect);

    if ((HPALETTE) m_palette != NULL)
        pDC->SelectPalette (pOldPalette, FALSE);
    return TRUE;
}

void CMainWindow::OnPaint ()
{
    CRect rect;
    GetClientRect (&rect);

    CPaintDC dc (this);
    DoDrawText (&dc, &rect);
}

BOOL CMainWindow::OnQueryNewPalette ()
{
    if ((HPALETTE) m_palette == NULL)   // Shouldn't happen, but
        return 0;                       // let's be sure

    CClientDC dc (this);
    CPalette* pOldPalette = dc.SelectPalette (&m_palette, FALSE);

    UINT nCount;
    if (nCount = dc.RealizePalette ())
        Invalidate ();

    dc.SelectPalette (pOldPalette, FALSE);
    return nCount;
}

void CMainWindow::OnPaletteChanged (CWnd* pFocusWnd)
{
    if ((HPALETTE) m_palette == NULL)   // Shouldn't happen, but
        return;                         // let's be sure

    if (pFocusWnd != this) {
        CClientDC dc (this);
        CPalette* pOldPalette = dc.SelectPalette (&m_palette, FALSE);
        if (dc.RealizePalette ())
            Invalidate ();
        dc.SelectPalette (pOldPalette, FALSE);
    }
}

void CMainWindow::DoGradientFill (CDC* pDC, CRect* pRect)
{
    CBrush* pBrush[64];
    for (int i=0; i<64; i++) // Create 64 blue brushes
        pBrush[i] = new CBrush (PALETTERGB (0, 0, 255 - (i * 4)));
// This requests many shades of blue brushes, but logical palette created before must have them assigned

    int nWidth = pRect->Width ();
    int nHeight = pRect->Height ();
    CRect rect;

    for (i=0; i<nHeight; i++) {
        rect.SetRect (0, i, nWidth, i + 1); // rectangle = one line
        pDC->FillRect (&rect, pBrush[(i * 63) / nHeight]); // fill with nearest blue brush
    }

    for (i=0; i<64; i++)
        delete pBrush[i]; // prevent memory leaks
}

void CMainWindow::DoDrawText (CDC* pDC, CRect* pRect)
{
    CFont font;
    int nHeight = -((pDC->GetDeviceCaps (LOGPIXELSY) * FONTHEIGHT) / 72);

    font.CreateFont (nHeight, 0, 0, 0, FW_BOLD, TRUE, 0, 0,
        DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
        DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Times New Roman");

    pDC->SetBkMode (TRANSPARENT);
	//pDC->SetBkColor(RGB(255,0,255)); // use this to change background around text object
    pDC->SetTextColor (RGB (255, 255, 255)); // Display white text
	
    CFont* pOldFont = pDC->SelectObject (&font);
    pDC->DrawText ("Hello, MFC", -1, pRect, DT_SINGLELINE | DT_CENTER |
        DT_VCENTER);

    pDC->SelectObject (pOldFont);
}

rainbow.gif (2243 bytes)


BitMaps

 


DDB and CBitmap Class

CClientDC dcScreen (this);
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dcScreen, 100, 100);
CDC dcMem;
dcMem.CreateCompatibleDC(&dcScreen);
CBrush brush(RGB(0,0,255));
CBitmap* pOldBitmap = dcMem.SelectObject(&bitmap);
dcMem.FillRect(CRect(0,0,100,100), &brush);
dcMem.SelectObject(pOldBitmap);

 

rainbow.gif (2243 bytes)


BLITting

Need to block transfer bitmaps
Can't simply select a bit map into a screen (nonmemory) DC

Can get properties of a bitmap by calling the GetObject function.

typedef struct tagBITMAP {
	LONG bmType;	// always 0
	LONG bmWidth;	// in PIXELs
	LONG bmHeight;
	LONG bmWidthBytes; // length in bytes of one line
	WORD bmPlanes;  // number of color planes
	WORD bmBitsPixel; // number of bits for each color
	LPVOID bmBits;	// pointer to actual bits NULL if DDB
} BITMAP;

Loading Bitmap Resources


Copyright chris wild 1999.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: April 11, 1999.