Paint a gradient color background


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

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read