September 29, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

ColorSpace ATL Control

  • July 22, 2000
  • By Andrew Whitechapel
  • Send Email »
  • More Articles »

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

History

Date Posted: July 22, 2000






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel