Click here to Skip to main content
15,888,977 members
Articles / Desktop Programming / Win32

XColorHexagonCtrl - a non-MFC color picker control that displays a color hexagon

Rate me:
Please Sign up or sign in to vote.
4.99/5 (30 votes)
4 Apr 2008CPOL10 min read 70K   1.2K   32  
XColorHexagonCtrl displays a color hexagon that allows user selection, and provides APIs for color based on RGB and HSL color models.
// XColorHexagonCtrlTestDlg.cpp : implementation file
//

#include "stdafx.h"
#include "XColorHexagonCtrlTest.h"
#include "XColorHexagonCtrlTestDlg.h"
#include "about.h"
#include "XNamedColors.h"

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

#pragma warning(disable : 4996)	// disable bogus deprecation warning

// copied from XColorHexagonCtrlConstants.h
static const COLORREF g_crCellColors[] = 
{
	RGB(  0,  51, 102),	// 1
	RGB( 51, 102, 153),
	RGB( 51, 102, 204),
	RGB(  0,  51, 153),
	RGB(  0,   0, 153),
	RGB(  0,   0, 204),
	RGB(  0,   0, 102),

	RGB(  0, 102, 102),	// 2
	RGB(  0, 102, 153),
	RGB(  0, 153, 204),
	RGB(  0, 102, 204),
	RGB(  0,  51, 204),
	RGB(  0,   0, 255),
	RGB( 51,  51, 255),
	RGB( 51,  51, 153),

	RGB(  0, 128, 128),	// 3
	RGB(  0, 153, 153),
	RGB( 51, 204, 204),
	RGB(  0, 204, 255),
	RGB(  0, 153, 255),
	RGB(  0, 102, 255),
	RGB( 51, 102, 255),
	RGB( 51,  51, 204),
	RGB(102, 102, 153),

	RGB( 51, 153, 102),	// 4
	RGB(  0, 204, 153),
	RGB(  0, 255, 204),
	RGB(  0, 255, 255),
	RGB( 51, 204, 255),
	RGB( 51, 153, 255),
	RGB(102, 153, 255),
	RGB(102, 102, 255),
	RGB(102,   0, 255),
	RGB(102,   0, 204),

	RGB( 51, 153,  51),	// 5
	RGB(  0, 204, 102),
	RGB(  0, 255, 153),
	RGB(102, 255, 204),
	RGB(102, 255, 255),
	RGB(102, 204, 255),
	RGB(153, 204, 255),
	RGB(153, 153, 255),
	RGB(153, 102, 255),
	RGB(153,  51, 255),
	RGB(153,   0, 255),

	RGB(  0, 102,   0),	// 6
	RGB(  0, 204,   0),
	RGB(  0, 255,   0),
	RGB(102, 255, 153),
	RGB(153, 255, 204),
	RGB(204, 255, 255),
	RGB(204, 236, 255),
	RGB(204, 204, 255),
	RGB(204, 153, 255),
	RGB(204, 102, 255),
	RGB(204,   0, 255),
	RGB(153,   0, 204),

	RGB(  0,  51,   0),	// 7
	RGB(  0, 128,   0),
	RGB( 51, 204,  51),
	RGB(102, 255, 102),
	RGB(153, 255, 153),
	RGB(204, 255, 204),
	RGB(255, 255, 255),
	RGB(255, 204, 255),
	RGB(255, 153, 255),
	RGB(255, 102, 255),
	RGB(255,   0, 255),
	RGB(204,   0, 204),
	RGB(102,   0, 102),

	RGB( 51, 102,   0),	// 8
	RGB(  0, 153,   0),
	RGB(102, 255,  51),
	RGB(153, 255, 102),
	RGB(204, 255, 153),
	RGB(255, 255, 204),
	RGB(255, 204, 204),
	RGB(255, 153, 204),
	RGB(255, 102, 204),
	RGB(255,  51, 204),
	RGB(204,   0, 153),
	RGB(128,   0, 128),

	RGB( 51,  51,   0),	// 9
	RGB(102, 153,   0),
	RGB(153, 255,  51),
	RGB(204, 255, 102),
	RGB(255, 255, 153),
	RGB(255, 204, 153),
	RGB(255, 153, 153),
	RGB(255, 102, 153),
	RGB(255,  51, 153),
	RGB(204,  51, 153),
	RGB(153,   0, 153),

	RGB(102, 102,  51),	// 10
	RGB(153, 204,   0),
	RGB(204, 255,  51),
	RGB(255, 255, 102),
	RGB(255, 204, 102),
	RGB(255, 153, 102),
	RGB(255, 124, 128),
	RGB(255,   0, 102),
	RGB(214,   0, 147),
	RGB(153,  51, 102),

	RGB(128, 128,   0),	// 11
	RGB(204, 204,   0),
	RGB(255, 255,   0),
	RGB(255, 204,   0),
	RGB(255, 153,  51),
	RGB(255, 102,   0),
	RGB(255,  80,  80),
	RGB(204,   0, 102),
	RGB(102,   0,  51),

	RGB(153, 102,  51),	// 12
	RGB(204, 153,   0),
	RGB(255, 153,   0),
	RGB(204, 102,   0),
	RGB(255,  51,   0),
	RGB(255,   0,   0),
	RGB(204,   0,   0),
	RGB(153,   0,  51),

	RGB(102,  51,   0),	// 13
	RGB(153, 102,   0),
	RGB(204,  51,   0),
	RGB(153,  51,   0),
	RGB(153,   0,   0),
	RGB(128,   0,   0),
	RGB(165,   0,  33),

	// gray scale
	RGB(248, 248, 248),	// 1
	RGB(221, 221, 221),
	RGB(178, 178, 178),
	RGB(128, 128, 128),
	RGB( 95,  95,  95),
	RGB( 51,  51,  51),
	RGB( 28,  28,  28),
	RGB(  8,   8,   8),

	RGB(234, 234, 234),	// 2
	RGB(192, 192, 192),
	RGB(150, 150, 150),
	RGB(119, 119, 119),
	RGB( 77,  77,  77),
	RGB( 41,  41,  41),
	RGB( 17,  17,  17),

	RGB(  0,   0,   0)
};

static const int g_nColors = sizeof(g_crCellColors) / sizeof(g_crCellColors[0]);


/////////////////////////////////////////////////////////////////////////////
// CXColorHexagonCtrlTestDlg dialog

BEGIN_MESSAGE_MAP(CXColorHexagonCtrlTestDlg, CDialog)
	//{{AFX_MSG_MAP(CXColorHexagonCtrlTestDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_STOP, OnStop)
	ON_BN_CLICKED(IDC_SPEED1, OnSpeed)
	ON_BN_CLICKED(IDC_ONLINE_HELP, OnOnlineHelp)
	ON_BN_CLICKED(IDC_TOOLTIP1, OnTooltip)
	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
	ON_BN_CLICKED(IDC_SPEED2, OnSpeed)
	ON_BN_CLICKED(IDC_SPEED3, OnSpeed)
	ON_BN_CLICKED(IDC_SPEED4, OnSpeed)
	ON_BN_CLICKED(IDC_TOOLTIP2, OnTooltip)
	ON_BN_CLICKED(IDC_TOOLTIP3, OnTooltip)
	ON_BN_CLICKED(IDC_TOOLTIP4, OnTooltip)
	ON_BN_CLICKED(IDC_TOOLTIP5, OnTooltip)
	ON_BN_CLICKED(IDC_TYPE1, OnType)
	ON_BN_CLICKED(IDC_TYPE2, OnType)
	//}}AFX_MSG_MAP
	ON_REGISTERED_MESSAGE(WM_XCOLORPICKER_SELCHANGE2, OnSelChange)
	ON_REGISTERED_MESSAGE(WM_XCOLORPICKER_SELENDOK2, OnSelendOk)
END_MESSAGE_MAP()

CXColorHexagonCtrlTestDlg::CXColorHexagonCtrlTestDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CXColorHexagonCtrlTestDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CXColorHexagonCtrlTestDlg)
	m_nSpeed = 0;
	m_nTooltipFormat = 0;
	m_nType = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	TRACE(_T("g_nColors=%d\n"), g_nColors);
}

void CXColorHexagonCtrlTestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CXColorHexagonCtrlTestDlg)
	DDX_Radio(pDX, IDC_SPEED1, m_nSpeed);
	DDX_Radio(pDX, IDC_TOOLTIP1, m_nTooltipFormat);
	DDX_Radio(pDX, IDC_TYPE1, m_nType);
	//}}AFX_DATA_MAP
}

/////////////////////////////////////////////////////////////////////////////
// CXColorHexagonCtrlTestDlg message handlers

BOOL CXColorHexagonCtrlTestDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	GetDlgItem(IDC_COLOR_NAME)->SetWindowText(_T(""));
	GetDlgItem(IDC_COLOR_RGB)->SetWindowText(_T(""));

	CRect rect;
	GetDlgItem(IDC_FRAME)->GetWindowRect(&rect);
	ScreenToClient(&rect);
	GetDlgItem(IDC_FRAME)->ShowWindow(SW_HIDE);
	VERIFY(m_ColorHexagon.Create(AfxGetInstanceHandle(), WS_CHILD | WS_VISIBLE | WS_TABSTOP /*| WS_BORDER*/, 
		rect, m_hWnd, 9001, RGB(0,255,0)));//, CXColorHexagonCtrl::XCOLOR_TOOLTIP_HTML));

	// call SetWindowPos to insert control in proper place in tab order
	::SetWindowPos(m_ColorHexagon.m_hWnd, ::GetDlgItem(m_hWnd, IDC_FRAME), 
		0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);

	m_ColorHexagon.SetBackground(GetSysColor(COLOR_BTNFACE));//RGB(255,255,0));	// yellow background

	//CRect rect2;
	//GetDlgItem(IDC_FRAME2)->GetWindowRect(&rect2);
	//ScreenToClient(&rect2);
	//GetDlgItem(IDC_FRAME2)->ShowWindow(SW_HIDE);
	//VERIFY(m_ColorSpectrum2.Create(AfxGetInstanceHandle(), WS_CHILD | WS_VISIBLE | WS_TABSTOP /*| WS_BORDER*/, 
	//	rect2, m_hWnd, 9002, RGB(0,255,0)));//, CXColorSpectrumCtrl::XCOLOR_TOOLTIP_HTML));

	srand((unsigned)time(NULL));
	SetTimer(1, 2000, NULL);
	
	::SetFocus(m_ColorHexagon.m_hWnd);

	return FALSE;  // return TRUE  unless you set the focus to a control
}

void CXColorHexagonCtrlTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

void CXColorHexagonCtrlTestDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

HCURSOR CXColorHexagonCtrlTestDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

// handler for WM_XCOLORPICKER_SELCHANGE
LRESULT CXColorHexagonCtrlTestDlg::OnSelChange(WPARAM wParam, LPARAM lParam)
{
	//TRACE(_T("CXColorHexagonCtrlTestDlg::OnSelChange: color=0x%06X  id=%d\n"), wParam, lParam);

	KillTimer(1);		// stop animation
	CString s = _T("");
	GetDlgItem(IDC_COLOR_NAME)->SetWindowText(s);
	GetDlgItem(IDC_COLOR_RGB)->SetWindowText(s);

	s.Format(_T("WM_XCOLORPICKER_SELCHANGE       RGB(%d,%d,%d)"), 
		GetRValue(wParam), GetGValue(wParam), GetBValue(wParam));

	if (lParam == 9001)
		GetDlgItem(IDC_SELECTION)->SetWindowText(s);
	//else
	//	GetDlgItem(IDC_SELECTION2)->SetWindowText(s);

	return 0;
}

// handler for WM_XCOLORPICKER_SELENDOK
LRESULT CXColorHexagonCtrlTestDlg::OnSelendOk(WPARAM wParam, LPARAM lParam)
{
	TRACE(_T("CXColorHexagonCtrlTestDlg::OnSelendOk:  color=0x%06X  id=%d\n"), wParam, lParam);

	KillTimer(1);		// stop animation
	CString s = _T("");
	GetDlgItem(IDC_COLOR_NAME)->SetWindowText(s);
	GetDlgItem(IDC_COLOR_RGB)->SetWindowText(s);

	s.Format(_T("WM_XCOLORPICKER_SELENDOK       RGB(%d,%d,%d)"), 
		GetRValue(wParam), GetGValue(wParam), GetBValue(wParam));

	if (lParam == 9001)
		GetDlgItem(IDC_SELECTION)->SetWindowText(s);
	//else
	//	GetDlgItem(IDC_SELECTION2)->SetWindowText(s);

	return 0;
}

void CXColorHexagonCtrlTestDlg::OnTimer(UINT nIDEvent) 
{
	static int index = 0;

	if (m_nType == 0)
		while ((index = rand()) >= g_nColors) index = rand();

	TCHAR s[200] = { _T('\0') };

	COLORREF cr = g_crCellColors[index++]; 
	_stprintf(s, _T("%d,%d,%d"), GetRValue(cr), GetGValue(cr), GetBValue(cr));
	GetDlgItem(IDC_COLOR_RGB)->SetWindowText(s);

	CXNamedColors nc;
	nc.SetRGB(cr);
	nc.GetName(s, sizeof(s)/sizeof(TCHAR)-2);
	GetDlgItem(IDC_COLOR_NAME)->SetWindowText(s);
	if (s[0] != _T('\0'))
	{
		TRACE(_T("named color: %s\n"), s);
	}

	m_ColorHexagon.SetRGB(cr);

	if (index >= g_nColors)
		index = 0;

	CDialog::OnTimer(nIDEvent);
}

void CXColorHexagonCtrlTestDlg::OnStop() 
{
	KillTimer(1);	
}

void CXColorHexagonCtrlTestDlg::OnSpeed() 
{
	int ms[4] = { 3000, 1000, 500, 100 };
	UpdateData(TRUE);
	if (m_nSpeed < 0 || m_nSpeed > 3)
		m_nSpeed = 0;
	SetTimer(1, ms[m_nSpeed], NULL);
}

void CXColorHexagonCtrlTestDlg::OnOnlineHelp() 
{
	CString strHelp = _T("");
	VERIFY(strHelp.LoadString(IDS_ONLINE_HELP));
	CXHyperLink::GotoURL(strHelp, SW_SHOW, TRUE);	
}

void CXColorHexagonCtrlTestDlg::OnTooltip() 
{
	UpdateData(TRUE);
	m_ColorHexagon.SetTooltipFormat((CXColorHexagonCtrl::TOOLTIP_FORMAT) m_nTooltipFormat);
	//m_ColorHexagon2.SetTooltipFormat((CXColorHexagonCtrl::TOOLTIP_FORMAT) m_nTooltipFormat);
}

// following was implemented to assist in screenshots
void CXColorHexagonCtrlTestDlg::OnButton1() 
{
#if 0  // -----------------------------------------------------------
	KillTimer(1);
	m_ColorSpectrum.SetRGB(RGB(0,0,0));
	CPoint pt(20,25);
	::ClientToScreen(m_ColorSpectrum.m_hWnd, &pt);
	::SetCursorPos(pt.x, pt.y);
#endif // -----------------------------------------------------------
}

void CXColorHexagonCtrlTestDlg::OnType() 
{
	UpdateData(TRUE);	
}

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) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.

For consulting and custom software development, please see www.hdsoft.org.






Comments and Discussions