Click here to Skip to main content
15,881,767 members
Articles / Desktop Programming / MFC

Style Toolkit - Use advanced graphics techniques to create a custom user interface

Rate me:
Please Sign up or sign in to vote.
4.97/5 (112 votes)
11 Aug 2008CPOL15 min read 227.4K   18.1K   403  
The Style Toolkit allows you to modernize the look of your programs using gradients, transparency, PNG images, and more.
//
// StyleProgress.cpp : Version 1.0 - see article at CodeProject.com
//
// Author:  Darren Sessions
//          
//
// Description:
//     StyleProgress is a CProgressCtrl derived control that uses the Style class
//	   and GDI+ to support different styles
//
// History
//     Version 1.0 - 2008 June 20
//     - Initial public release
//
// License:
//     This software is released under the Code Project Open License (CPOL),
//     which may be found here:  http://www.codeproject.com/info/eula.aspx
//     You are free to use this software in any way you like, except that you 
//     may not sell this source code.
//
//     This software is provided "as is" with no expressed or implied warranty.
//     I accept no liability for any damage or loss of business that this 
//     software may cause.
//
///////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "StyleProgress.h"

StyleProgress::StyleProgress(void)
{
	m_bCreated	= FALSE;
	
	// default gray
	m_BackColor = RGB(0xC9, 0xC9, 0xC9);
	// default green
	m_ForeColor = RGB(0x00, 0xd3, 0x28);

	m_Lower = 0; 
	m_Upper = 100; 
	m_Pos = 50;
	m_Step = 5;

	// default will step the bottom layer of the second stack
	m_StepStackIdx = -1;
	m_StepLayerIdx = 0;
	m_StepLayerWidth = 0;
}

StyleProgress::~StyleProgress(void)
{
}

BEGIN_MESSAGE_MAP(StyleProgress, CProgressCtrl)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_NCPAINT()
END_MESSAGE_MAP()

void StyleProgress::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	// need to create if default
	if(!m_bCreated) CreateDefaultStack();

	m_Style.PaintStyle(&dc, m_ProgRect);
}

BOOL StyleProgress::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

void StyleProgress::OnNcPaint()
{
	// Needed to stop the base from painting the border
}

void StyleProgress::AddStack(Stack stack)
{
	m_Style.AddStack(stack);
}

void StyleProgress::AddStepStack(Stack stack)
{
	// this function must get called, so get m_ProgRect here
	GetClientRect(m_ProgRect);
	m_StepStackIdx = m_Style.AddStack(stack);

	// default layer is zero - over ridden in SetStepLayer
	m_StepLayerWidth = m_Style.m_Stacks[m_StepStackIdx].m_Layers[0].lrect.Width;

	// the step layer needs to have its rect defined
	// e.g. use the rect version FillSolid(rect, Blue) instead of FillSolid(Blue)
	ASSERT(m_StepLayerWidth != 0);

	m_bCreated = TRUE;
}

void StyleProgress:: SetStepLayer(int layerIdx)
{
	// AddStepStack needs to be called before this funtion is called
	ASSERT(m_StepStackIdx != -1);

	m_StepLayerIdx = layerIdx; 
	m_StepLayerWidth = m_Style.m_Stacks[m_StepStackIdx].m_Layers[layerIdx].lrect.Width;
}

void StyleProgress::SetForeColor(COLORREF color, int Alpha)
{
	m_ForeColor = color;
	m_ForeAlpha = Alpha;
}

void StyleProgress::SetBackColor(COLORREF color, int Alpha)
{
	m_BackColor = color;
	m_BackAlpha = Alpha;
}

void StyleProgress::UpdateStack()
{
	Rect frc, lrc; CRect crc;
	float ratio; int width;

	// AddStepStack needs to be called for 1 stack
	ASSERT(m_StepStackIdx != -1);

	// get the frame rect
	frc = m_Style.m_Stacks[m_StepStackIdx].Frame.frect;
	
	// calculate step position
	ratio = float(m_Pos)/float(m_Upper - m_Lower);
	width = (int)(ratio*m_StepLayerWidth);

	// adjust the rects
	frc.Width = width;
	lrc.Width = width;

	// set the new rects
	m_Style.m_Stacks[m_StepStackIdx].Frame.frect = frc;
	m_Style.m_Stacks[m_StepStackIdx].Regenerate(m_StepLayerIdx);

	// need to regenerate any stacks above this one
	for(int i = (m_StepStackIdx+1); i < (int)m_Style.m_Stacks.size(); i++)
	{
		m_Style.m_Stacks[i].Regenerate();
	}
}

int StyleProgress::SetStep(int step)
{
	if(step <= m_Upper)
	{
		m_Step = step;
	}
	return m_Step;
}

void StyleProgress::SetRange(int lower, int upper)
{
	// negative range values not implemented
	ASSERT(lower >= 0 && upper > 0);

	if(upper > lower)
	{
		m_Upper = upper; 
		m_Lower = lower;
	}
}
int StyleProgress::SetPos(int pos)
{
	if		(pos <= m_Lower)	m_Pos = m_Lower;
	else if	(pos >= m_Upper)	m_Pos = m_Upper;
	else						m_Pos = pos;

	if(!m_bCreated) CreateDefaultStack();

	UpdateStack();
	Invalidate();
	
	return m_Pos;
}

int StyleProgress::StepIt()
{
	int newPos = m_Pos + m_Step;

	if		(m_Pos == m_Upper)	m_Pos = m_Step;
	else if	(newPos > m_Upper)	m_Pos = m_Upper;
	else						m_Pos = newPos;

	if(m_bCreated)
	{
		UpdateStack();
		Invalidate();
	}

	return m_Pos;
}

////////////////////////////////////////
/// DEFAULT PROGRESS CONTOL STACK //////
////////////////////////////////////////
void StyleProgress::CreateDefaultStack()
{
	// define the rects
	GetClientRect(m_ProgRect); CRect EffRect(m_ProgRect); CRect TopRect(m_ProgRect); 

	// some adustments
	EffRect.DeflateRect(1, 1); 
	TopRect.DeflateRect(1, 1); 

	//=============== Background Layers ===================//
	Stack ProgressBack(m_ProgRect, m_BackColor);

	ProgressBack.SetShape(ROUNDRECT, 1);
	ProgressBack.SetOuterBorder(1, RGB(0xB2, 0xB2, 0xB2));
	ProgressBack.SetMiddleBorder(1, Clr(100,White));
	
	ProgressBack.FillBar(EffRect, LEFT_EDGE, 8, Clr(40,Black), Clr(0,Black));
	ProgressBack.FillBar(EffRect, RIGHT_EDGE, 8, Clr(0,Black), Clr(40,Black));

	float btprof[3] = { 0.0f, 0.20f, 1.0f };
	ProgressBack.FillBar(EffRect, TOP_EDGE, 6, Clr(200,White), Clr(241,White), Clr(40,White), btprof);
	float bbprof[3] = { 0.0f, 0.80f, 1.0f };
	ProgressBack.FillBar(EffRect, BOTTOM_EDGE, 6, Clr(0,White), Clr(100,White), Clr(80,White), bbprof);

	//=========== Foreground Layers ======================//

	Stack ProgressFront(TopRect);
	ProgressFront.FillSolid(TopRect, m_ForeColor);

	// top and bottom

	float tprof[3] = { 0.0f, 0.15f, 1.0f };

	ProgressFront.FillBar(TopRect, TOP_EDGE, 6, Clr(180,White), Clr(200,White), Clr(128,White), tprof);
	ProgressFront.FillBar(TopRect, BOTTOM_EDGE, 6, Clr(0,White), Clr(100,White));

	float lprof[3] = { 0.0f, 0.15f, 1.0f };
	float rprof[3] = { 0.0f, 0.85f, 1.0f };

	ProgressFront.FillBar(TopRect, LEFT_EDGE, 20, Clr(20,Black), Clr(40,Black), Clr(0,Black), lprof);
	ProgressFront.FillBar(TopRect, RIGHT_EDGE, 20, Clr(0,Black), Clr(40,Black), Clr(20,Black), rprof);

	// add it to the style
	AddStack(ProgressBack);
	AddStepStack(ProgressFront);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
I am currently working as a consultant in Southern California.

I have worked as a Hardware Engineer, Firmware Engineer, Software Engineer and Applications Engineer.

I spent 13 years in the Disk Drive industry and the last 7 working in GPS.

Comments and Discussions