[ Home | Syllabus | Course Notes | Assignments | Search]
Display Technology and Video Drivers.
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?)
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);
Two Messages sent about palettes:
In either case, the normal response is to realize the palette and repaint.
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 ()
};
#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);
}
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);
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;