Combobox Color Picker

I recently wanted to allow certain color selection in one of my projects. The common control available is a great thing but I wanted the look-and-feel of something similar to what VC++ offers in its options dialog box. The following code acomplishes exactly that.

Just include the ComboColorPicker.h and ComboColorPicker.cpp files in your project and create a control member variable for a regular combobox in VC’s classwizard and you have your self a combobox for color selection. This combobox implements focus indication correctly but still lacks the [Automatic] option VC has.

ComboColorPicker.h


#if !defined(AFX_COMBOCOLORPICKER_H__B2348841_5541_11D1_8756_
00A0C9181E86__INCLUDED_)
#define AFX_COMBOCOLORPICKER_H__B2348841_5541_11D1_8756_
00A0C9181E86__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// ComboColorPicker.h : header file
// © 1997 Baldvin Hansson

///////////////////////////////////////////////////////////////////
// CComboColorPicker window

class CComboColorPicker : public CComboBox
{
// Construction
public:
CComboColorPicker();

// Attributes
private:
bool m_bInitialized;
static COLORREF m_rgStandardColors[];
public:

// Operations
private:
void InitializeData();
public:
COLORREF GetSelectedColor();

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CComboColorPicker)
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

// Implementation
public:
virtual ~CComboColorPicker();

// Generated message map functions
protected:
//{{AFX_MSG(CComboColorPicker)
int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG

DECLARE_MESSAGE_MAP()
};

///////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations
// immediately before the previous line.

#endif // !defined(AFX_COMBOCOLORPICKER_H__B2348841_5541_11D1_
// 8756_00A0C9181E86__INCLUDED_)

ComboColorPicker.cpp


// ComboColorPicker.cpp : implementation file
// © 1997 Baldvin Hansson

#include “stdafx.h”
#include “ComboColorPicker.h”

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

///////////////////////////////////////////////////////////////////
// CComboColorPicker

COLORREF CComboColorPicker::m_rgStandardColors[] = {
RGB(0, 0, 0), // Black
RGB(255, 255, 255), // White
RGB(128, 0, 0), // Dark Red
RGB(0, 128, 0), // Dark Green
RGB(128, 128, 0), // Dark Yellow
RGB(0, 0, 128), // Dark Blue
RGB(128, 0, 128), // Dark Magenta
RGB(0, 128, 128), // Dark Cyan
RGB(192, 192, 192), // Light Grey
RGB(128, 128, 128), // Dark Grey
RGB(255, 0, 0), // Red
RGB(0, 255, 0), // Green
RGB(255, 255, 0), // Yellow
RGB(0, 0, 255), // Blue
RGB(255, 0, 255), // Magenta
RGB(0, 255, 255), // Cyan
};

CComboColorPicker::CComboColorPicker()
{
m_bInitialized = false;
}

CComboColorPicker::~CComboColorPicker()
{
}

BEGIN_MESSAGE_MAP(CComboColorPicker, CComboBox)
//{{AFX_MSG_MAP(CComboColorPicker)
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

///////////////////////////////////////////////////////////////////
// CComboColorPicker message handlers

int CComboColorPicker::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CComboBox::OnCreate(lpCreateStruct) == -1)
return -1;

InitializeData();

return 0;
}

void CComboColorPicker::PreSubclassWindow()
{
InitializeData();

CComboBox::PreSubclassWindow();
}

void CComboColorPicker::InitializeData()
{
int nItem;

if (m_bInitialized)
return;

for (int nColor = 0; nColor < sizeof(m_rgStandardColors)/
sizeof(COLORREF); nColor++)
{
// Here we could affect the sort order at run-time
nItem = AddString((LPCTSTR)m_rgStandardColors[nColor]);

if (CB_ERRSPACE == nItem)
break;
}

m_bInitialized = true;
}

void CComboColorPicker::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC dc;
CBrush brushBlack;
brushBlack.CreateStockObject(BLACK_BRUSH);

if (!dc.Attach(lpDrawItemStruct->hDC))
return;

COLORREF rgbTextColor = dc.GetTextColor();
COLORREF rgbBkColor = dc.GetBkColor();

if (lpDrawItemStruct->itemAction & ODA_FOCUS)
{
dc.DrawFocusRect(&lpDrawItemStruct->rcItem);
}
else if (lpDrawItemStruct->itemAction & ODA_DRAWENTIRE)
{
if (lpDrawItemStruct->itemState & ODS_FOCUS)
dc.DrawFocusRect(&lpDrawItemStruct->rcItem);
else
dc.ExtTextOut(0, 0, ETO_OPAQUE, &lpDrawItemStruct->rcItem,
_T(“”), 0, NULL);
}

if (0 <= (int)lpDrawItemStruct->itemID) // Any item selected?
{
::InflateRect(&lpDrawItemStruct->rcItem, -2, -2);

dc.FillSolidRect(&lpDrawItemStruct->rcItem,
(COLORREF)lpDrawItemStruct->itemData);
dc.FrameRect(&lpDrawItemStruct->rcItem, &brushBlack);
}

// Restore the DC state
dc.SetTextColor(rgbTextColor);
dc.SetBkColor(rgbBkColor);
dc.Detach();
}

COLORREF CComboColorPicker::GetSelectedColor()
{
int nItem = GetCurSel();
if (CB_ERR == nItem)
return RGB(0, 0, 0); // Default to black if nothing is selected

return m_rgStandardColors[nItem];
}

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read