Introduction
For many years I have been using my
XColourPicker control, which I based on
Chris Maunder's excellent
color picker control.
Recently my project manager asked me why I wasn't using a control
with a modern look.
That's when I realized that my control still had the flat Windows 2000 look,
even when used in a themed app:
To make this look good in a themed app, I knew I had to add support for
visual themes, which has always involved a good deal of effort whenever I
tried it. Nevertheless, I decided to look into it. What I
discovered was something unexpected that completely surprised me.
Comboboxes and Themes
In trying to decide how to proceed, it struck me that the color picker
has the appearance of a combobox, rather than a button (my
XColourPicker control is derived from
CButton
).
Because of this, my
XColourPicker control needed code to position and draw the down arrow,
and a lot of other details to make it look like a combobox.
But what if I started from CComboBox
? Could I eliminate
some of the drawing code? To investigate this possibility,
I started by creating a new class derived from
CComboBox
. I added the virtual DrawItem()
function, which the framework calls for ownerdraw controls.
Then I made sure the combobox in the demo was marked as ownerdraw.
When I tried the demo app, I was amazed. Without using any of
the
uxtheme functions at all, the combobox was drawn using
visual themes, even though it was marked as ownerdraw. Mouse hover
also worked, changing the appearance to hot state. And I did
not have to do anything to achieve this!
Naturally this made the job much easier. I added code to
DrawItem()
to draw a color-filled rect,
and I was done.
Here is what the demo app for the new control looks like:
XColorPickerXP API
The programmatic interface to
XColorSpectrumCtrl attributes is very
simple: just six functions to get/set color and custom colors.
Function |
Description |
COLORREF GetColor()
|
Retrieves RGB color value
|
void GetCustomColors(COLORREF * pCustomColors)
|
Retrieves array of 16 custom color RGB values
|
CString GetCustomColors()
|
Retrieves 16 custom colors as space-separated string of RGB values
|
CXColorPickerXP& SetColor(COLORREF crColor)
|
Sets color from RGB value
|
CXColorPickerXP& SetCustomColors(COLORREF * pCustomColors)
|
Sets 16 custom colors from array of RGB values
|
CXColorPickerXP& SetCustomColors(LPCTSTR lpszCustomColors)
|
Sets 16 custom colors from space-separated string of RGB values
|
XColorPickerXP DDX Helpers
XColorPickerXP provides two DDX helper functions:
void AFXAPI DDX_XColorPickerXP(CDataExchange * pDX, int nIDC, COLORREF& crColor);
void AFXAPI DDX_XColorPickerXPCustom(CDataExchange * pDX, int nIDC, CString& strCustomColors);
In the demo app, these functions are used in
DoDataExchange()
function:
void CXColorPickerXPTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CXColorPickerXPTestDlg)
DDX_Control(pDX, IDC_COLOR_SAMPLE, m_stcColorSample);
DDX_Control(pDX, IDC_BACKGROUND_COLOR, m_ctlBackgroundColor);
DDX_Control(pDX, IDC_TEXT_COLOR, m_ctlTextColor);
//}}AFX_DATA_MAP
DDX_XColorPickerXP(pDX, IDC_TEXT_COLOR, m_rgbText);
DDX_XColorPickerXP(pDX, IDC_BACKGROUND_COLOR, m_rgbBackground);
DDX_XColorPickerXPCustom(pDX, IDC_TEXT_COLOR, m_strTextCustomColors);
DDX_XColorPickerXPCustom(pDX, IDC_BACKGROUND_COLOR, m_strBackgroundCustomColors);
}
How To Use
To integrate XColorPickerXP
into your app, you first need
to add following files to your project:
- XColorPickerXP.cpp
- XColorPickerXP.h
- XColorPopupXP.cpp
- XColorPopupXP.h
Then use resource editor to add combobox control to your dialog,
and use Class Wizard to attach member variable to that control.
Next, include header file XColorPickerXP.h in
the dialog's header file. Then replace
the CComboBox
definition with CXColorPickerXP
.
Now you are ready to start using XColorPickerXP
.
Demo App
The demo dialog processes color changes
in the
OnColorChange
handler:
LRESULT CXColorPickerXPTestDlg::OnColorChange(WPARAM, LPARAM lParam)
{
TRACE(_T("in CXColorPickerXPTestDlg::OnColorChange\n"));
if (lParam == IDC_TEXT_COLOR)
{
TRACE(_T("IDC_TEXT_COLOR\n"));
}
else if (lParam == IDC_BACKGROUND_COLOR)
{
TRACE(_T("IDC_BACKGROUND_COLOR\n"));
}
if (m_ctlTextColor.GetColor() == m_ctlBackgroundColor.GetColor())
{
CXBalloonMsg::Show(_T("Unreadable Colors"),
_T("The text and background colors are identical.\r\n")
_T("The text will not be readable."),
m_ctlBackgroundColor.m_hWnd,
m_hWnd,
AfxGetInstanceHandle(),
TTI_ERROR);
}
else
{
m_rgbText = m_ctlTextColor.GetColor();
m_rgbBackground = m_ctlBackgroundColor.GetColor();
}
m_ctlTextColor.SetColor(m_rgbText);
m_ctlBackgroundColor.SetColor(m_rgbBackground);
m_stcColorSample.SetTextColor(m_rgbText);
m_stcColorSample.SetBackgroundColor(m_rgbBackground);
return 0;
}
Revision History
Version 1.0 - 2008 April 9
Usage
This software is released into the public domain. You are free
to use it in any way you like, except that you may not sell this
source code. If you modify it or extend it, please to consider posting
new code here for everyone to share. 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.