Click here to Skip to main content
15,895,011 members
Articles / Desktop Programming / ATL

ATL Splitter ActiveX control

Rate me:
Please Sign up or sign in to vote.
4.67/5 (6 votes)
16 Nov 1999CPOL4 min read 153.1K   2.4K   56  
A port of my splitter ActiveX control with MFC to ATL.
// Splitter.h : Declaration of the CSplitter

#ifndef __SPLITTER_H_
#define __SPLITTER_H_

#include "resource.h"       // main symbols
#include <atlctl.h>

struct CControlInfo
{
	CComBSTR		m_strName;
	IOleObjectPtr	m_pOleObject;

	CControlInfo& operator=(const CControlInfo& other)
	{
		m_strName=other.m_strName;
		m_pOleObject=other.m_pOleObject;
		return *this;
	}
};

class CControlInfoArray : public std::vector<CControlInfo>
{
public:
	int IndexOf(const BSTR strName);
};



#define DISPID_SPLITTER_PERCENT_POSITION 1
#define DISPID_FIRST_CONTROL_NAME 3
#define DISPID_SECOND_CONTROL_NAME 4

class CSplitter;

class CHiddenWindow : public CWindowImpl<CHiddenWindow>
{
public:
	CSplitter*		m_pSplitter;

	CHiddenWindow()
	{
		m_pSplitter=NULL;
	}

BEGIN_MSG_MAP(CHiddenWindow)	
MESSAGE_HANDLER(WM_TIMER, OnTimer)
END_MSG_MAP()
	LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
};

/////////////////////////////////////////////////////////////////////////////
// CSplitter
class ATL_NO_VTABLE CSplitter : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public IDispatchImpl<ISplitter, &IID_ISplitter, &LIBID_SPLITTERATLCONTROLLib>,
	public CComControl<CSplitter>,
	public IPersistStreamInitImpl<CSplitter>,
	public IOleControlImpl<CSplitter>,
	public IOleObjectImpl<CSplitter>,
	public IOleInPlaceActiveObjectImpl<CSplitter>,
	public IViewObjectExImpl<CSplitter>,
	public IOleInPlaceObjectWindowlessImpl<CSplitter>,
	public ISupportErrorInfo,
	public IConnectionPointContainerImpl<CSplitter>,
	public IPersistStorageImpl<CSplitter>,
	public ISpecifyPropertyPagesImpl<CSplitter>,
	public IQuickActivateImpl<CSplitter>,
	public IDataObjectImpl<CSplitter>,
	public IProvideClassInfo2Impl<&CLSID_Splitter, &DIID__ISplitterEvents, &LIBID_SPLITTERATLCONTROLLib>,
	public IPropertyNotifySinkCP<CSplitter>,
	public IPerPropertyBrowsingImpl<CSplitter>,
	public CComCoClass<CSplitter, &CLSID_Splitter>
{
	friend class CHiddenWindow;

	float		m_fltSplitterPercentPosition;
	BOOL		m_bSplitterIsVertical;
	CComBSTR	m_strFirstControlName;
	CComBSTR	m_strSecondControlName;

	CControlInfoArray	m_arrayControls;
	BOOL				m_bTracking;
	RECT				m_rectTracking;
	SIZE				m_sizeTrackingOffset;
	HBRUSH				m_hbrHalftone;
	int					m_SplitterWidth;
	int					m_SplitterHeight;
	CHiddenWindow		m_wndHidden;

	void CalcSplitterRectBySplitterPercentPosition(float fltPercentPosition,
													RECT& rectSplitter,
													const RECT& rectControl);

	float CalcSplitterPercentPositionBySplitterRect(const RECT& rect,
													const RECT& rectControl);

	void GetRects(RECT& rectFirstPane,
					RECT& rectSecondPane,
					RECT& rectSplitter,
					const RECT& rectControl);

	//Returns the extended name of the control, which has been asigned
	//to it by the container (form)
	//pDispatch is the interface provided by the container's site object
	CComBSTR GetExtendedName(IDispatchPtr pDispatch);

	void GetOtherControlsOnTheContainer();
	void PlaceControlOnPane(const BSTR strControlName,const RECT& rectPane);
	void AdjustControlsToPanes();
	void DelayAdjustControlsToPanes();
	
	void InvertTracker(const RECT& rect);
	void CalcNewTrackingRect(POINT ptMouse,RECT* pRectResult);
	HBRUSH GetHalftoneBrush();

	POINT GetMouseCursorPosInContainerCoords();


public:
	CSplitter()
	{
		m_fltSplitterPercentPosition=50;
		m_bSplitterIsVertical=TRUE;
		m_bTracking=FALSE;
		m_hbrHalftone=NULL;
		m_SplitterWidth=GetSystemMetrics(SM_CXFRAME);
		m_SplitterHeight=GetSystemMetrics(SM_CYFRAME);
		m_wndHidden.m_pSplitter=this;
	}

	~CSplitter()
	{
		::DeleteObject(m_hbrHalftone);
		if(m_wndHidden.m_hWnd)
			m_wndHidden.DestroyWindow();
	}

	

DECLARE_REGISTRY_RESOURCEID(IDR_SPLITTER)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CSplitter)
	COM_INTERFACE_ENTRY(ISplitter)
	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(IPerPropertyBrowsing)
END_COM_MAP()

BEGIN_PROP_MAP(CSplitter)
	PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
	PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
	PROP_ENTRY("SplitterIsVertical", 2, CLSID_SplitterPropPage)
	PROP_ENTRY("FirstControlName", DISPID_FIRST_CONTROL_NAME, CLSID_SplitterPropPage)
	PROP_ENTRY("SecondControlName", DISPID_SECOND_CONTROL_NAME, CLSID_SplitterPropPage)

	// Example entries
	// PROP_ENTRY("Property Description", dispid, clsid)
	// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()

BEGIN_CONNECTION_POINT_MAP(CSplitter)
	CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
END_CONNECTION_POINT_MAP()

BEGIN_MSG_MAP(CSplitter)
	CHAIN_MSG_MAP(CComControl<CSplitter>)
	DEFAULT_REFLECTION_HANDLER()
	MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
	MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUP)
	MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
	MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
END_MSG_MAP()
// Handler prototypes:
//  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);



// ISupportsErrorInfo
	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);

// IViewObjectEx
	DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

// IOleControl
	STDMETHOD(OnAmbientPropertyChange)(DISPID dispid);

// IPerPropertyBrowsingImpl
	STDMETHOD(GetPredefinedStrings)(DISPID dispID, CALPOLESTR *pCaStringsOut,CADWORD *pCaCookiesOut);
	STDMETHOD(GetPredefinedValue)(DISPID /*dispID*/, DWORD /*dwCookie*/, VARIANT* /*pVarOut*/);

//IOleInPlaceObjectWindowlessImpl
	STDMETHOD(SetObjectRects)(LPCRECT prcPos,LPCRECT prcClip);
	

// ISplitter
public:
	STDMETHOD(get_SplitterPercentPosition)(/*[out, retval]*/ float *pVal);
	STDMETHOD(put_SplitterPercentPosition)(/*[in]*/ float newVal);
	STDMETHOD(get_SecondControlName)(/*[out, retval]*/ BSTR *pVal);
	STDMETHOD(put_SecondControlName)(/*[in]*/ BSTR newVal);
	STDMETHOD(get_FirstControlName)(/*[out, retval]*/ BSTR *pVal);
	STDMETHOD(put_FirstControlName)(/*[in]*/ BSTR newVal);
	STDMETHOD(get_SplitterIsVertical)(/*[out, retval]*/ BOOL *pVal);
	STDMETHOD(put_SplitterIsVertical)(/*[in]*/ BOOL newVal);

	HRESULT OnDraw(ATL_DRAWINFO& di);
	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 OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
};




#endif //__SPLITTER_H_

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions