Click here to Skip to main content
15,886,422 members
Articles / Desktop Programming / MFC
Article

Paint a Gradient Color Background

Rate me:
Please Sign up or sign in to vote.
4.29/5 (7 votes)
25 Oct 2002 109.3K   1.4K   38   9
Code to create a gradient palette and paint with it

Gradient Palette

Introduction

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::PaintGradientRect()).

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.

// GRADPAL.H
// Written by Chen Su


// m_nPaintDir:
// GPD_TTOB - top to bottom,
// GPD_BTOT - bottom to top,
// GPD_LTOR - left to right,
// GPD_RTOL - right to left
const int GPD_TTOB = 0;
const int GPD_BTOT = 1;
const int GPD_LTOR = 2;
const int 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
const UINT GPC_RED = 0x00000001;
const UINT GPC_GREEN = 0x00000002;
const UINT GPC_BLUE = 0x00000004;


//-----------------------------------------------------------------------------
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 BOOL OnEraseBkgnd(CDC *pDC);
        afx_msg void OnPaint();
        
        DECLARE_MESSAGE_MAP()
    
    private:
        const int m_nPaintSteps, m_nPaintDir;
        const UINT m_nPaintRGB;

        CPalette m_Pal;
        
        void PaintGradientRect(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 Chen Su


#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_ERASEBKGND()
    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();
    }
}
//-----------------------------------------------------------------------------
BOOL CGradpalWnd::OnEraseBkgnd(CDC * /*pDC*/)
{
    return TRUE;
}
//-----------------------------------------------------------------------------
void CGradpalWnd::OnPaint()
{
    CPaintDC dc(this);
    
    CPalette *pPalOld = dc.SelectPalette(&m_Pal, FALSE);
    dc.RealizePalette();
    
    RECT rect;
    this->GetClientRect(&rect);
    
    this->PaintGradientRect(&dc, rect);
    
    dc.SelectPalette(pPalOld, FALSE);
}
//-----------------------------------------------------------------------------
void CGradpalWnd::PaintGradientRect(CDC *pDC, const RECT &rect) const
{
    ASSERT_POINTER(pDC, CDC);
    ASSERT_KINDOF(CDC, pDC);

    ASSERT(m_nPaintSteps > 0);
    
    // 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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey26-Feb-12 20:58
professionalManoj Kumar Choubey26-Feb-12 20:58 
GeneralMy vote of 5 Pin
VinhTran_30-Nov-11 17:20
VinhTran_30-Nov-11 17:20 
GeneralWinCE Pin
BBurgess21-Oct-04 0:00
BBurgess21-Oct-04 0:00 
QuestionWhy so much trouble ? Pin
jocool15-Sep-04 4:51
jocool15-Sep-04 4:51 
AnswerRe: Why so much trouble ? Pin
Chen Su15-Sep-04 11:01
Chen Su15-Sep-04 11:01 
AnswerRe: Why so much trouble ? Pin
String_Pass19751-Dec-06 2:52
String_Pass19751-Dec-06 2:52 
GeneralKinda Clueless here... Pin
og_ghost27-Jan-04 21:01
og_ghost27-Jan-04 21:01 
QuestionIs This Just For CFrameWnd? Pin
alan9330-Sep-03 4:37
alan9330-Sep-03 4:37 
AnswerRe: Is This Just For CFrameWnd? Pin
Chen Su30-Sep-03 8:02
Chen Su30-Sep-03 8:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.