Introduction
XColorDialog mimics behavior of color picker dialog
found in Microsoft Office®:
This article is based on my articles
XColorHexagonCtrl
and
XColorSpectrumCtrl.
XColorDialog Features and Behaviors
XColorDialog has the same visual appearance as the two screenshots above,
and offers an API that is similar to
CColorDialog,
but without support for the multiple custom colors that you see here:
For a detailed description of the user interface behaviors of the two
tabs in XColorDialog, please see my articles
XColorHexagonCtrl
and
XColorSpectrumCtrl.
XColorDialog is implemented using standard MFC CDialog
and CTabCtrl
. Two tab pages host the color controls, which
communicate with the parent dialog via registered window messages.
The parent dialog then keeps the color control on the other tab page
informed of currently selected color, and updates
color display on the parent dialog:
When the user selects a new color by double-clicking left mouse button,
this has same effect as clicking on
OK button.
The Custom tab includes the same controls as the MS Office®
dialog, allowing user to select the color model (RGB or HSL) and values:
As user clicks on spin controls, color selectors (
crosshair and
luminosity arrow) are updated, and new color is also sent to parent
dialog, so that
New/Current display is continuously updated.
XColorDialog API
Here is the
XColorDialog API:
Function |
Description |
COLORREF GetColor()
|
Retrieves RGB value for current color
|
int GetColorModel()
|
Retrieves color model setting from Custom tab
|
int GetCurTab()
|
Retrieves current tab
|
void GetHSL(BYTE *h, BYTE *s, BYTE *l)
|
Retrieves HSL values for current color
|
COLORREF GetRGB()
|
Retrieves RGB value for current color
|
CXColorDialog& SetColorModel(int nColorModel)
|
Sets starting color model for Custom tab
|
CXColorDialog& SetCurrentColor(COLORREF cr)
|
Sets the current color from RGB values
|
CXColorDialog& SetHSL(BYTE h, BYTE s, BYTE l)
|
Sets the current color from HSL values
|
CXColorDialog& SetRGB(COLORREF cr)
|
Sets the current color from RGB values
|
CXColorDialog& SetStartTab(int nStartTab)
|
Sets the starting tab
|
CXColorDialog& SetTitle(LPCTSTR lpszTitle)
|
Sets the title of the dialog box
|
CXColorDialog& SetTooltipFormat(int nFormat)
|
Sets the tooltip format for the CXColorHexagonCtrl and
CXColorSpectrumCtrl controls
|
Implementation Notes
The implementation of
XColorDialog was fairly straightforward.
The only real surprise I got had to do with the visibility of
the grayscale hexagons on the
Standard tab.
The first time I ran the demo program, this is what I saw:
The large white hexagon and the small grayscale hexagon closest to it
are indiscernible from the background. When I took another look at
the MS Office® color dialog, I saw that what I thought was a solid
background color was in fact a
color gradient. Using the RGB-to-HSL
algorithms I already had, I quickly calculated a lower (ending) color
that was 10 points darker than the start color. Then I added
WM_ERASEBKGND
handler to each tab page,
so that I could paint the background with GDI function
GradientFill()
:
BOOL CTabStandard::OnEraseBkgnd(CDC* pDC)
{
CRect rectClient;
GetClientRect(&rectClient);
TRIVERTEX vert[2];
vert[0].x = 0;
vert[0].y = 0;
vert[0].Red = (COLOR16) (GetRValue(m_crStartColor) << 8);
vert[0].Green = (COLOR16) (GetGValue(m_crStartColor) << 8);
vert[0].Blue = (COLOR16) (GetBValue(m_crStartColor) << 8);
vert[0].Alpha = 0x0000;
vert[1].x = rectClient.right;
vert[1].y = rectClient.bottom;
vert[1].Red = (COLOR16) (GetRValue(m_crEndColor) << 8);
vert[1].Green = (COLOR16) (GetGValue(m_crEndColor) << 8);
vert[1].Blue = (COLOR16) (GetBValue(m_crEndColor) << 8);
vert[1].Alpha = 0x0000;
GRADIENT_RECT rect;
rect.UpperLeft = 0;
rect.LowerRight = 1;
::GradientFill(pDC->m_hDC, vert, 2, &rect, 1, GRADIENT_FILL_RECT_V);
return TRUE;
}
Here is what the Standard tab looks like with gradient fill:
Demo App
Here is what demo app looks like:
How to use
The following steps assume you want to add
XColorDialog to
a dialog. Steps would be similar for
CFormView
or
CPropertyPage
.
Step 1 - Add Files
To integrate CXColorDialog
into your app, you first need to
add following files to your project:
- CXCD.h
- CXRect.h
- CXToolTipCtrl.h
- help_vista.ico
- help_xp.ico
- rgbhsl.cpp †
- rgbhsl.h
- TabCustom.cpp
- TabCustom.h
- TabStandard.cpp
- TabStandard.h
- XBalloonMsg.cpp †
- XBalloonMsg.h
- XColorDialog.cpp
- XColorDialog.h
- XColorDialog.rc
- XColorDialogRes.h
- XColorHexagonCtrl.cpp †
- XColorHexagonCtrl.h
- XColorSpectrumCtrl.cpp †
- XColorSpectrumCtrl.h
The .cpp files marked with †
should be set to Not using precompiled header
in Visual Studio. Otherwise, you will get error
fatal error C1010: unexpected end of file while looking for precompiled header directive
Step 2 - Add XColorDialog Resource File
The dialog templates in XColorDialog.rc are invoked via
string resource name rather than numeric resource ID.
This technique allows you to use XColorDialog without having to worry
about resource ID collisions with the other dialogs in your app.
Step 3 - Add Code to Create XColorDialog
In source module where you want to call
XColorDialog,
include header file
XColorDialog.h. Then
create
XColorDialog like this:
CMyColorDialog dlg(m_crCurrent, m_nTooltip | ((m_nStartTab+1) << 4));
dlg.SetTitle(_T("My Colors"));
if (dlg.DoModal() == IDOK)
{
}
Step 4 (Optional) - Add Derived Class
The demo app shows how you can derive your own class from
CXColorDialog
to make use of
virtual function OnColorOK()
:
class CMyColorDialog : public CXColorDialog
{
public:
CMyColorDialog(COLORREF crInitial = 0,
DWORD dwFlags = XCD_TOOLTIP_NONE | XCD_OPEN_HEXAGON,
CWnd* pParent = NULL)
: CXColorDialog(crInitial, dwFlags, pParent)
{
}
virtual BOOL OnColorOK()
{
COLORREF cr = GetRGB();
if (cr == RGB(255,0,0))
{
AfxMessageBox(_T("That color is not allowed."));
return 1;
}
return 0;
}
};
Revision History
Version 1.0 - 2008 April 5
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.