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

Color components editor control

Rate me:
Please Sign up or sign in to vote.
4.93/5 (11 votes)
2 Apr 20025 min read 79.7K   2.7K   31  
This control lets you edit RGB or HSL components of a color, like in Paint Shop Pro.
// This is a part of the GWC Library
// Copyright (C) 2001-2002 Aircom software
// All rights reserved.
//
// This source code can be used, distributed or modified
// free of charge only if this header copyright is not removed.
// In other cases, contact us at:
// web:   http://www.aircom.org
// email: info@aircom.org
//

#include "stdafx.h"
#include "GWCGradientColorWnd.h"
#include "GWCColorComponentEditCtrl.h"
#include "GWCColorComponentSet.h"
#include "GWCColorFunc.h"
#include "memdc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define WINDOW_WIDTH 262	// 262 = 256 colors + 3 pixels each side for the 3D border

//==================================================================
// Description:
// Constructs a new GWCGradientColorWnd instance.
//
// Parameters:
// pComp - A pointer to the component control that owns this window.
//==================================================================
GWCGradientColorWnd::GWCGradientColorWnd(GWCColorComponentEditCtrl* pComp) : m_comp(pComp)
{
}

//========================================================================
// Description:
// Creates the handle of this popup window.
//
// Parameters:
// dwStyle - The window style to apply to this window. Should be WS_POPUP.
// pParentWnd - A pointer to the parent window.
// nID - The child ID of this window.
//
// Returns:
// TRUE if successfull, FALSE otherwise.
//========================================================================
BOOL GWCGradientColorWnd::Create(DWORD dwStyle, CWnd* pParentWnd, UINT nID)
{
	return CWnd::CreateEx(0,AfxRegisterWndClass(CS_CLASSDC), NULL, dwStyle, CRect(0,0,WINDOW_WIDTH,20), pParentWnd, nID);
}

BEGIN_MESSAGE_MAP(GWCGradientColorWnd, CWnd)
	//{{AFX_MSG_MAP(GWCGradientColorWnd)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_NCPAINT()
	ON_WM_NCCALCSIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//===============================================================
// Description:
// Called before OnPaint to erase the background of this control. 
//
// Parameters:
// pDC - A pointer to the device context used for drawing.
//
// Returns:
// TRUE so that the parent won't paint the background.
//===============================================================
BOOL GWCGradientColorWnd::OnEraseBkgnd(CDC* pDC) 
{
	return TRUE;
}

//===============================================
// Description:
// Called by the framework to paint this control.
//===============================================
void GWCGradientColorWnd::OnPaint() 
{
	// Create a memory DC for a non flickering draw
	CPaintDC paintDC(this);
	CMemDC dc(&paintDC);

	// Draw the gradient bar

	CRect rect;
	GetClientRect(&rect);

	COLORREF color = m_comp->GetOwnerSet()->GetColor();
	int type = m_comp->GetType();

	if (type == GWCColorComponentEditCtrl::RED)
	{
		for(int i=0;i<256;i++)
		{
			CPen pen(PS_SOLID,1,RGB(i,GetGValue(color),GetBValue(color)));
			CPen* oldPen = dc.SelectObject(&pen);
			dc.MoveTo(i,0);
			dc.LineTo(i,14);
			dc.SelectObject(oldPen);
		}
	}
	else if (type == GWCColorComponentEditCtrl::GREEN)
	{
		for(int i=0;i<256;i++)
		{
			CPen pen(PS_SOLID,1,RGB(GetRValue(color),i,GetBValue(color)));
			CPen* oldPen = dc.SelectObject(&pen);
			dc.MoveTo(i,0);
			dc.LineTo(i,14);
			dc.SelectObject(oldPen);
		}
	}
	else if (type == GWCColorComponentEditCtrl::BLUE)
	{
		for(int i=0;i<256;i++)
		{
			CPen pen(PS_SOLID,1,RGB(GetRValue(color),GetGValue(color),i));
			CPen* oldPen = dc.SelectObject(&pen);
			dc.MoveTo(i,0);
			dc.LineTo(i,14);
			dc.SelectObject(oldPen);
		}
	}
	else if (type == GWCColorComponentEditCtrl::HUE)
	{
		BYTE hue,sat,light;
		m_comp->GetOwnerSet()->GetColor(&hue,&sat,&light);

		for(int i=0;i<256;i++)
		{
			CPen pen(PS_SOLID,1,GWCColorFunc::HSLtoRGB((double)i/255.0,(double)sat/255.,(double)light/255.));
			CPen* oldPen = dc.SelectObject(&pen);
			dc.MoveTo(i,0);
			dc.LineTo(i,14);
			dc.SelectObject(oldPen);
		}
	}
	else if (type == GWCColorComponentEditCtrl::SAT)
	{
		BYTE hue,sat,light;
		m_comp->GetOwnerSet()->GetColor(&hue,&sat,&light);

		for(int i=0;i<256;i++)
		{
			CPen pen(PS_SOLID,1,GWCColorFunc::HSLtoRGB((double)hue/255.,(double)i/255.0,(double)light/255.));
			CPen* oldPen = dc.SelectObject(&pen);
			dc.MoveTo(i,0);
			dc.LineTo(i,14);
			dc.SelectObject(oldPen);
		}
	}
	else if (type == GWCColorComponentEditCtrl::LIGHT)
	{
		BYTE hue,sat,light;
		m_comp->GetOwnerSet()->GetColor(&hue,&sat,&light);

		for(int i=0;i<256;i++)
		{
			CPen pen(PS_SOLID,1,GWCColorFunc::HSLtoRGB((double)hue/255.,(double)sat/255.,(double)i/255.0));
			CPen* oldPen = dc.SelectObject(&pen);
			dc.MoveTo(i,0);
			dc.LineTo(i,14);
			dc.SelectObject(oldPen);
		}
	}

	// Draw a mark for the current value
	BYTE hue,sat,light;
	m_comp->GetOwnerSet()->GetColor(&hue,&sat,&light);
	double dHue = (double)hue/255. + 0.5;
	if (dHue > 1.0) dHue -= 1.0;
	COLORREF markColor = GWCColorFunc::HSLtoRGB(dHue,1.0,0.5);
	CPen pen(PS_SOLID,1,markColor);
	CPen* oldPen = dc.SelectObject(&pen);
	BYTE value = m_comp->GetValue();
	dc.MoveTo(value,0);
	dc.LineTo(value,14);
	dc.MoveTo(value-1,0);
	dc.LineTo(value-1,14);
	dc.MoveTo(value+1,0);
	dc.LineTo(value+1,14);
	dc.SelectObject(oldPen);
}

//===========================================================
// Description:
// Called by the framework to draw the border of this window.
//===========================================================
void GWCGradientColorWnd::OnNcPaint() 
{
	// Draw a 3D border

	CWindowDC dc(this);

	CRect rect;
	GetWindowRect(&rect);
	int w = rect.Width();
	int h = rect.Height();

	CPen lightPen(PS_SOLID,1,::GetSysColor(COLOR_BTNFACE));
	CPen darkPen(PS_SOLID,1,::GetSysColor(COLOR_BTNSHADOW));

	CPen* oldPen = dc.SelectObject(&lightPen);

	dc.MoveTo(0, h-2);
	dc.LineTo(0, 0);
	dc.LineTo(w, 0);

	dc.MoveTo(2, h-3);
	dc.LineTo(2, 2);
	dc.LineTo(w-3, 2);
	dc.LineTo(w-3, h-3);
	dc.LineTo(2, h-3);

	dc.SelectStockObject(WHITE_PEN);

	dc.MoveTo(1, h-2);
	dc.LineTo(1, 1);
	dc.LineTo(w-1, 1);

	dc.SelectStockObject(BLACK_PEN);

	dc.MoveTo(0, h-1);
	dc.LineTo(w-1, h-1);
	dc.LineTo(w-1, -1);

	dc.SelectObject(&darkPen);

	dc.MoveTo(1, h-2);
	dc.LineTo(w-2, h-2);
	dc.LineTo(w-2, 0);

	dc.SelectObject(oldPen);
}

//========================================================================
// Description:
// Called bu the framework to calculates the rectangle of the client area.
//
// Parameters:
// bCalcValidRects - Not used.
// lpncsp - Contains the rectangle of the client area.
//========================================================================
void GWCGradientColorWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
{
	// 3 pixels are removed from each side for the 3D effect
	lpncsp->rgrc[0].left += 3;
	lpncsp->rgrc[0].top += 3;
	lpncsp->rgrc[0].right -= 3;
	lpncsp->rgrc[0].bottom -= 3;

	CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
}

//=====================================================================================
// Description:
// Shows the popup window
//
// Parameters:
// point - x contains the x position of the mouse, y contains the top side of the popup
//         window.
//=====================================================================================
void GWCGradientColorWnd::Show(CPoint point)
{
	int value = m_comp->GetValue();

	// Get the screen rectangle
	CRect rect;
	::SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);

	// Check if the bar is not beyond the right side of the screen
	int posx = point.x-value-3;
	if (posx + WINDOW_WIDTH > rect.right)
	{
		int deltax = point.x - posx;
		posx = rect.right - WINDOW_WIDTH;

		CPoint mousePos;
		::GetCursorPos(&mousePos);
		::SetCursorPos(posx+deltax,mousePos.y);
	}

	// Check if the bar is not beyond the left side of the screen
	else if (posx < 0)
	{
		int deltax = point.x - posx;
		posx = 0;

		CPoint mousePos;
		::GetCursorPos(&mousePos);
		::SetCursorPos(posx+deltax,mousePos.y);
	}

	SetWindowPos(NULL,posx,point.y,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW|SWP_NOACTIVATE);
}

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 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
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions