This article was contributed by chensu.
Have you seen an installation program that has a gradient color background? Yes, you have. How do you paint such a background?
First, you need to create a gradient color palette (CGradpalWnd::CreateGradPalette()). Then, you can paint the background with the colors in the palette (CGradpalWnd::PaintGradiantRect()).
This program allows you to paint with four directions
m_nPaintDir:
GPD_TTOB – top to bottom,
GPD_BTOT – bottom to top,
GPD_LTOR – left to right,
GPD_RTOL – right to left
and seven colors
m_nPaintRGB:
GPC_RED – Red
GPC_GREEN – Green
GPC_BLUE – Blue
GPC_RED | GPC_GREEN – Yellow
GPC_RED | GPC_BLUE – Purple
GPC_GREEN | GPC_BLUE – Cyan
GPC_RED | GPC_GREEN | GPC_BLUE – Grey
And specify m_nPaintSteps with the number of steps it takes to paint.
Source:
// GRADPAL.H
// Written by chensu
// m_nPaintDir:
// GPD_TTOB - top to bottom,
// GPD_BTOT - bottom to top,
// GPD_LTOR - left to right,
// GPD_RTOL - right to left
#define GPD_TTOB 0
#define GPD_BTOT 1
#define GPD_LTOR 2
#define GPD_RTOL 3
// m_nPaintRGB: a combination of one or more of the following values
// i.e.:
// GPC_RED - Red
// GPC_GREEN - Green
// GPC_BLUE - Blue
// GPC_RED | GPC_GREEN - Yellow
// GPC_RED | GPC_BLUE - Purple
// GPC_GREEN | GPC_BLUE - Cyan
// GPC_RED | GPC_GREEN | GPC_BLUE - Grey
#define GPC_RED 0x0001
#define GPC_GREEN 0x0002
#define GPC_BLUE 0x0004
//-----------------------------------------------------------------------------
class CGradpalApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class CGradpalWnd : public CFrameWnd
{
public:
CGradpalWnd();
inline BOOL CreateWnd();
protected:
afx_msg BOOL OnQueryNewPalette();
afx_msg void OnPaletteChanged(CWnd *pFocusWnd);
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
private:
const int m_nPaintSteps, m_nPaintDir;
const UINT m_nPaintRGB;
CPalette m_Pal;
void PaintGradiantRect(CDC *pDC, const RECT &rect) const;
BOOL CreateGradPalette();
};
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline BOOL CGradpalWnd::CreateWnd()
{
return this->Create(NULL, _T("Gradient Palette"));
}
//-----------------------------------------------------------------------------
// End of GRADPAL.H
// GRADPAL.CPP
// Written by chensu
#include <afxwin.h>
#include "gradpal.h"
//*****************************************************************************
//-----------------------------------------------------------------------------
CGradpalApp GradpalApp;
//-----------------------------------------------------------------------------
//*****************************************************************************
//*****************************************************************************
//-----------------------------------------------------------------------------
BOOL CGradpalApp::InitInstance()
{
CGradpalWnd *pMainFrame = new CGradpalWnd();
if (!pMainFrame->CreateWnd())
return FALSE;
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
m_pMainWnd = pMainFrame;
return TRUE;
}
//-----------------------------------------------------------------------------
//*****************************************************************************
//*****************************************************************************
//-----------------------------------------------------------------------------
CGradpalWnd::CGradpalWnd() :
m_nPaintSteps(236), // the number of steps
m_nPaintDir(GPD_BTOT), // the direction
m_nPaintRGB(GPC_BLUE) // the color
{
VERIFY(this->CreateGradPalette());
}
//-----------------------------------------------------------------------------
BEGIN_MESSAGE_MAP(CGradpalWnd, CFrameWnd)
ON_WM_QUERYNEWPALETTE()
ON_WM_PALETTECHANGED()
ON_WM_PAINT()
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------
BOOL CGradpalWnd::OnQueryNewPalette()
{
CClientDC dc(this);
CPalette *pPalOld = dc.SelectPalette(&m_Pal, FALSE);
BOOL bRet = dc.RealizePalette();
dc.SelectPalette(pPalOld, FALSE);
if (bRet)
// some colors changed
this->Invalidate();
return bRet;
}
//-----------------------------------------------------------------------------
void CGradpalWnd::OnPaletteChanged(CWnd *pFocusWnd)
{
if (pFocusWnd != this)
this->OnQueryNewPalette();
}
//-----------------------------------------------------------------------------
void CGradpalWnd::OnPaint()
{
CPaintDC dc(this);
CPalette *pPalOld = dc.SelectPalette(&m_Pal, FALSE);
dc.RealizePalette();
RECT rect;
this->GetClientRect(&rect);
this->PaintGradiantRect(&dc, rect);
dc.SelectPalette(pPalOld, FALSE);
}
//-----------------------------------------------------------------------------
void CGradpalWnd::PaintGradiantRect(CDC *pDC, const RECT &rect) const
{
ASSERT(pDC != NULL);
ASSERT_KINDOF(CDC, pDC);
// initialize
RECT rectVar = { rect.left, rect.top, rect.left, rect.top };
int nTotalSize;
if (m_nPaintDir == GPD_TTOB || m_nPaintDir == GPD_BTOT)
{
rectVar.right = rect.right;
nTotalSize = rect.bottom - rect.top;
}
else
{
rectVar.bottom = rect.bottom;
nTotalSize = rect.right - rect.left;
}
// paint nSteps times
for (int nIndex = 0; nIndex < m_nPaintSteps; nIndex++)
{
// calculate the rectangle
if (m_nPaintDir == GPD_TTOB || m_nPaintDir == GPD_BTOT)
{
rectVar.top = rectVar.bottom;
rectVar.bottom = rect.top +
::MulDiv(nIndex + 1, nTotalSize, m_nPaintSteps);
}
else
{
rectVar.left = rectVar.right;
rectVar.right = rect.left +
::MulDiv(nIndex + 1, nTotalSize, m_nPaintSteps);
}
// calculate the color value
int nColor = ::MulDiv(nIndex, 255, m_nPaintSteps);
if (m_nPaintDir == GPD_BTOT || m_nPaintDir == GPD_RTOL)
nColor = 255 - nColor;
const COLORREF clrBr =
PALETTERGB((BYTE)(m_nPaintRGB & GPC_RED ? nColor : 0),
(BYTE)(m_nPaintRGB & GPC_GREEN ? nColor : 0),
(BYTE)(m_nPaintRGB & GPC_BLUE ? nColor : 0));
// paint the rectangle with the brush
CBrush brush(clrBr);
pDC->FillRect(&rectVar, &brush);
}
}
//-----------------------------------------------------------------------------
BOOL CGradpalWnd::CreateGradPalette()
{
if (m_Pal.GetSafeHandle() != NULL)
return FALSE;
BOOL bSucc = FALSE;
const int nNumColors = 236;
LPLOGPALETTE lpPal = (LPLOGPALETTE)new BYTE[sizeof(LOGPALETTE) +
sizeof(PALETTEENTRY) *
nNumColors];
if (lpPal != NULL)
{
lpPal->palVersion = 0x300;
lpPal->palNumEntries = nNumColors;
PALETTEENTRY *ppe = lpPal->palPalEntry;
for (int nIndex = 0; nIndex < nNumColors; nIndex++)
{
const int nColor = ::MulDiv(nIndex, 255, nNumColors);
ppe->peRed = (BYTE)(m_nPaintRGB & GPC_RED ? nColor : 0);
ppe->peGreen = (BYTE)(m_nPaintRGB & GPC_GREEN ? nColor : 0);
ppe->peBlue = (BYTE)(m_nPaintRGB & GPC_BLUE ? nColor : 0);
ppe->peFlags = (BYTE)0;
ppe++;
}
bSucc = m_Pal.CreatePalette(lpPal);
delete [](PBYTE)lpPal;
}
return bSucc;
}
//-----------------------------------------------------------------------------
//*****************************************************************************
// End of GRADPAL.CPP
Download sample project – 53KB
Last updated: 27 July 1998
Posted on: 19 Aug 1998