ColorSpace ATL Control | CodeGuru

ColorSpace ATL Control

Environment: Written with VC6 and ATL3, tested under NT4 SP3+4+5, Windows95 and 98 This is a follow-up to Rajiv Ramachandran’s excellent Corel PhotoHouse-like Color Chooser (btw: great work, Rajiv!). Rajiv’s Color Chooser is based on MFC dialogs.  My version is based on the ATL and WTL, and is in fact an ActiveX Control. I’ve used […]

Written By
CodeGuru Staff
CodeGuru Staff
Jul 23, 2000
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

Environment: Written with VC6 and ATL3, tested under NT4 SP3+4+5, Windows95 and 98

This is a follow-up to Rajiv Ramachandran’s excellent
Corel PhotoHouse-like Color Chooser
(btw: great work, Rajiv!). Rajiv’s
Color Chooser is based on MFC dialogs.  My version is based on the ATL and
WTL, and is in fact an ActiveX Control.

I’ve used Rajiv’s bitmap and underlying maths code for the graphics itself, and
I’ve restricted my control to an RGB and luminosity selector, cutting out the
full HSV part of Rajiv’s dialog (mainly to reduce the size of the control).

To
use this control, download the demo zip, which contains the built OCX and two
built test apps, one built using the MFC, the other with the ATL window and
dialog classes.  Then register the control with:   REGSVR32 
COLORSPACE.OCX.  The sourcecode zip includes the source for all three
projects.

The control is an ATL composite control.  It exposes two
properties via four get/put methods: get_RGB, put_RGB, get_HSV and put_HSV;
fires one event when the color is changed; and responds to ambient background
color changes.  The control does support ErrorInfo, and throws an Error if
the user attempts to put an invalid RGB value.  Most of the rest of the
code is basically rewritten from Rajiv’s original.

Some interesting ATL bits
include:

– The parent class CComCompositeControl<>::OnDraw in atlctl.h
has been replaced with a custom one – this is only used for drawing the
metafile, and therefore gives the user (the client project developer) a
recognisable image of the control while they are working with it in say the
dialog editor.

– The parent class CComCompositeControl<>::CalcExtent has
been similarly replaced in order to prepare the child control template sizes
converted to draw units.

– The use of the undocumented Platform SDK WTL,
specifically: atlapp.h for the WTL generically; atlmisc.h for the WTL CString
class (very similar to MFC CString); atlgdi.h for CBitmap, CDC, CPen and CBrush;
and atlctrls.h for CUpDownCtrl (== CSpinButtonCtrl).  

The primary
control class declaration is listed here, to give you an idea of its scope, but
for full details see the sourcecode download:

class ATL_NO_VTABLE CColorSpace :
 public CComObjectRootEx<CComSingleThreadModel>,
 public IDispatchImpl<IColorSpace,
                      &IID_IColorSpace,
                      &LIBID_COLORSPACESERVERLib>,
 public CComCompositeControl<CColorSpace>,
 public IPersistStreamInitImpl<CColorSpace>,
 public IOleControlImpl<CColorSpace>,
 public IOleObjectImpl<CColorSpace>,
 public IOleInPlaceActiveObjectImpl<CColorSpace>,
 public IViewObjectExImpl<CColorSpace>,
 public IOleInPlaceObjectWindowlessImpl<CColorSpace>,
 public ISupportErrorInfo,
 public IConnectionPointContainerImpl<CColorSpace>,
 public IPersistStorageImpl<CColorSpace>,
 public ISpecifyPropertyPagesImpl<CColorSpace>,
 public IQuickActivateImpl<CColorSpace>,
 public IDataObjectImpl<CColorSpace>,
 public IProvideClassInfo2Impl<&CLSID_ColorSpace,
                               &DIID__IColorSpaceEvents,
                               &LIBID_COLORSPACESERVERLib>,
 public IPropertyNotifySinkCP<CColorSpace>,
 public CComCoClass<CColorSpace, &CLSID_ColorSpace>,
 public CProxy_IColorSpaceEvents< CColorSpace >
{
public:
 CColorSpace();
 CColorSpace(COLORREF c);
 ~CColorSpace();
 COLORREF GetColor() { return m_RGB.GetColorref(); }
 // overrides
 HRESULT OnDraw(ATL_DRAWINFO &di);
 BOOL CalcExtent(SIZE& size);
DECLARE_REGISTRY_RESOURCEID(IDR_COLORSPACE)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CColorSpace)
 COM_INTERFACE_ENTRY(IColorSpace)
 COM_INTERFACE_ENTRY(IDispatch)
 COM_INTERFACE_ENTRY(IViewObjectEx)
 COM_INTERFACE_ENTRY(IViewObject2)
 COM_INTERFACE_ENTRY(IViewObject)
 COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
 COM_INTERFACE_ENTRY(IOleInPlaceObject)
 COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
 COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
 COM_INTERFACE_ENTRY(IOleControl)
 COM_INTERFACE_ENTRY(IOleObject)
 COM_INTERFACE_ENTRY(IPersistStreamInit)
 COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
 COM_INTERFACE_ENTRY(ISupportErrorInfo)
 COM_INTERFACE_ENTRY(IConnectionPointContainer)
 COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
 COM_INTERFACE_ENTRY(IQuickActivate)
 COM_INTERFACE_ENTRY(IPersistStorage)
 COM_INTERFACE_ENTRY(IDataObject)
 COM_INTERFACE_ENTRY(IProvideClassInfo)
 COM_INTERFACE_ENTRY(IProvideClassInfo2)
 COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()
BEGIN_PROP_MAP(CColorSpace)
 PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
 PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
END_PROP_MAP()
BEGIN_CONNECTION_POINT_MAP(CColorSpace)
 CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
 CONNECTION_POINT_ENTRY(DIID__IColorSpaceEvents)
END_CONNECTION_POINT_MAP()
BEGIN_MSG_MAP(CColorSpace)
 CHAIN_MSG_MAP(CComCompositeControl<CColorSpace>)
 MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUP)
 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
 MESSAGE_HANDLER(WM_PAINT, OnPaint)
 MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange)
 COMMAND_HANDLER(IDC_EDIT_BLUE, EN_CHANGE, OnChangeEditBlue)
 COMMAND_HANDLER(IDC_EDIT_GREEN, EN_CHANGE, OnChangeEditGreen)
 COMMAND_HANDLER(IDC_EDIT_RED, EN_CHANGE, OnChangeEditRed)
 MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
END_MSG_MAP()
BEGIN_SINK_MAP(CColorSpace)
 //Make sure the Event Handlers have __stdcall calling convention
END_SINK_MAP()
 STDMETHOD(OnAmbientPropertyChange)(DISPID dispid);
// ISupportsErrorInfo
 STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
// IViewObjectEx
 DECLARE_VIEW_STATUS(0)
// IColorSpace
public:
 STDMETHOD(get_HSV)(/*[out, retval]*/ LONG *pVal);
 STDMETHOD(put_HSV)(/*[in]*/ LONG newVal);
 STDMETHOD(get_RGB)(/*[out, retval]*/ OLE_COLOR *pVal);
 STDMETHOD(put_RGB)(/*[in]*/ OLE_COLOR newVal);
 enum { IDD = IDD_COLORSPACE };
protected:
 void DrawFilledColor(CDC *pDC, CRect cr, COLORREF c);
 void DrawLines(CDC *pDC);
 void DrawXorRect(CDC *pDC, CRect& cr);
 void CalcSlopes();
 void CalcCuboid();
 void DrawMarkers(CDC *pDC);
 void SetSpinVals();
 void SetEditVals();
 void DrawAll();
 void DrawRGB(CDC *pDC);
 void LoadMappedBitmap(CBitmap& bitmap, UINT nIdResource, CSize& size);
 CBitmap  m_RGBbitmap;
 CDC      m_memDC;
 int      m_nRGBwidth, m_nRGBheight;
 RGBType  m_RGB;
 RGBType  m_OldRGB;
 CPoint   m_ptVertex, m_ptTop, m_ptLeft, m_ptRight;
 CRect    m_rects[3];
 CPoint   m_Cuboid[8];
 BOOL     m_bInMouse;
 int      m_nIndex;
 int      m_nRedLen, m_nGreenLen, m_nBlueLen;
 LineDesc m_lines[3];
 CRect    m_rectRGB;
 CRect    m_rectOldColor, m_rectNewColor;
 BOOL     m_bInitOver;
 BOOL     m_bInDrawAll;
 HSVType  m_HSV;
 CRect    m_rectBright;
 CRect    m_rectBrightMark;
 CRect    m_rectHSV;
 CDIB     m_BrightDIB;
 int      m_nMouseIn;
 BOOL     InBright(CPoint pt);
 void     TrackPoint(CPoint pt);
 void     CreateBrightDIB();
 void     SetDIBPalette();
 void     CalcRects();
 void     DrawHSV(CDC *pDC);
 // additional rects for drawing the metafile
 CRect    m_rectRed, m_rectGreen, m_rectBlue;
 CRect    m_rectSmallControls;
 CPoint   m_ptRed, m_ptGreen, m_ptBlue, m_ptOld, m_ptNew;
protected:
 void UpdateColor(BYTE r, BYTE g, BYTE b);
 // Windows message handlers
 LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 LRESULT OnLButtonUP(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 LRESULT OnChangeEditBlue(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
 LRESULT OnChangeEditGreen(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
 LRESULT OnChangeEditRed(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
 LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
};

For further info on the WTL, see Richard Grimes’s excellent article in Visual
C++ Developers Journal Vol3 No3 April 2000, or from http://www.vcdj.com
  If you haven’t got the
Platform SDK, you can download it (including the WTL and an ATL/WTL AppWizard)
from Microsoft’s website:
http://msdn.microsoft.com/downloads/c-frame.htm?007#/downloads/sdks/ 

 

Downloads

Download demo project – 113 Kb

Download source – 88 Kb

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.