Click here to Skip to main content
Licence 
First Posted 25 Oct 2002
Views 88,058
Bookmarked 37 times

Paint a Gradient Color Background

By | 25 Oct 2002 | Article
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

About the Author

Chen Su

Software Developer

Canada Canada

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 5 Pinmembermanoj kumar choubey20:58 26 Feb '12  
GeneralMy vote of 5 PinmemberMember 780004017:20 30 Nov '11  
GeneralWinCE PinmemberBBurgess0:00 21 Oct '04  
QuestionWhy so much trouble ? Pinmemberjocool4:51 15 Sep '04  
AnswerRe: Why so much trouble ? PinmemberChen Su11:01 15 Sep '04  
AnswerRe: Why so much trouble ? PinmemberString_Pass19752:52 1 Dec '06  
GeneralKinda Clueless here... Pinmemberog_ghost21:01 27 Jan '04  
QuestionIs This Just For CFrameWnd? Pinmemberalan934:37 30 Sep '03  
AnswerRe: Is This Just For CFrameWnd? PinmemberChen Su8:02 30 Sep '03  

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

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 26 Oct 2002
Article Copyright 2002 by Chen Su
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid