Click here to Skip to main content
15,881,600 members
Articles / Desktop Programming / WTL

WTL Docking Windows

Rate me:
Please Sign up or sign in to vote.
4.89/5 (73 votes)
21 Nov 20077 min read 825.6K   14.1K   215  
This is an implementation of docking windows for the WTL library
// Copyright (c) 2002
// Sergey Klimov (kidd@ukr.net)

#ifndef WTL_DW_SSTATE_H_INCLUDED_
#define WTL_DW_SSTATE_H_INCLUDED_


#include<memory>
#include<utility>
#include<algorithm>
#include<map>
#include<cassert>
#include<limits>
#include<string>
#include<sstream>
#include<atlsplit.h>
#include<stg.h>


namespace sstate{

const	TCHAR ctxtGeneral[]		= _T("General");
const	TCHAR ctxtCXScreen[]	=_T("SM_CXSCREEN");
const	TCHAR ctxtCYScreen[]	=_T("SM_CYSCREEN");
const	TCHAR ctxtPlacement[]	=_T("placement");
const	TCHAR ctxtPosition[]	=_T("position");
const	TCHAR ctxtMainWindow[]	=_T("MainWindow");
const	TCHAR ctxtVisible[]		=_T("visible");
const	TCHAR ctxtBand[]		=_T("band");
const	TCHAR ctxtWndPrefix[]	=_T("Wnd-");
typedef std::basic_string<TCHAR> tstring;
typedef unsigned long ID;
//typedef tstring ID;

const unsigned int ForceDefaultCmdShow=0x80000000;

struct IState
{
	virtual ~IState(void){}
	virtual bool Store(IStorge& /*stg*/)=0;
	virtual bool Restore(IStorge& /*stg*/,const std::pair<long,long>& /*xratio*/,const std::pair<long,long>& /*yratio*/)=0;
	virtual bool RestoreDefault(void)=0;
	virtual void AddRef(void)=0;
	virtual void Release(void)=0;
};

template<class T>
class CStateBase : public T
{
public:
	CStateBase():m_ref(1)
	{
	}
	virtual void AddRef(void)
	{
		m_ref++;
	}
	virtual void Release(void)
	{
		if(--m_ref==0)
			delete this;
	}
	virtual ~CStateBase(void)
	{
		assert(m_ref==0);
	}
private:
	CStateBase(const CStateBase& );
	const CStateBase& operator=(const CStateBase& );
protected:
	unsigned long m_ref;
};

template<class T=IState>
class CStateHolder
{
	typedef CStateHolder<T> thisClass;
public:
	CStateHolder(void)
		:m_pState(0)
	{
	}
	CStateHolder(T* pState)
	{
		pState->AddRef();
		m_pState=pState;
	}
	CStateHolder(const thisClass& sholder)
	{
		*this=(sholder);
	}
	thisClass& operator = (const thisClass& sholder)
	{
		m_pState=const_cast<T*>(sholder.m_pState);
		if(m_pState!=0)
			m_pState->AddRef();
		return *this;
	}
	~CStateHolder(void)
	{
		if(m_pState!=0)
			m_pState->Release();
	}
	const T* operator ->() const
	{
		return m_pState;
	}
	T* operator ->()
	{
		return m_pState;
	}
protected:
	T* m_pState;
};

template<class TStorage>
class CContainerImpl
	: public CStateBase<IState>
{
protected:
	typedef CStateHolder<IState> CItem;
	typedef std::map<ID,CItem> CBunch;
    class CStorer
    {
    public:
		CStorer(IStorge& stgTop)
				:m_stgTop(stgTop)
        {
        }
        void operator() (std::pair<const ID,CItem>& x) const
        {
            std::basic_ostringstream<TCHAR> sstrKey;
            sstrKey.flags(std::ios::hex | std::ios::showbase );
			sstrKey<<ctxtWndPrefix<<x.first;
/*
            CRegKey key;
            DWORD dwDisposition;
            LONG lRes = key.Create(m_keyTop,sstrKey.str().c_str(),REG_NONE,
                                    REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ,
                                    NULL,&dwDisposition);
            if(lRes==ERROR_SUCCESS)
				x.second->Store(key);
*/
			TStorage stg;
			if(stg.Create(m_stgTop,sstrKey.str().c_str(),IStorge::ReadWrite)==ERROR_SUCCESS)
                x.second->Store(stg);
        }
    protected:
		IStorge& m_stgTop;
    };

	class CRestorer
	{
	public:
		CRestorer(IStorge& stgTop,const std::pair<long,long>& xratio,const std::pair<long,long>& yratio)
				:m_stgTop(stgTop)
				,m_xratio(xratio)
				,m_yratio(yratio)
		{
		}
		void operator() (std::pair<const ID,CItem>& x) const
		{
            std::basic_ostringstream<TCHAR> sstrKey;
            sstrKey.flags(std::ios::hex | std::ios::showbase );
			sstrKey<<ctxtWndPrefix<<x.first;
/*
            CRegKey key;
            LONG lRes = key.Open(m_keyTop,sstrKey.str().c_str(),KEY_READ);
            if(lRes==ERROR_SUCCESS)
                x.second->Restore(key,m_xratio,m_yratio);
			else
				x.second->RestoreDefault();
*/
			TStorage stg;
			if(stg.Open(m_stgTop,sstrKey.str().c_str(),IStorge::Read)!=ERROR_SUCCESS
				|| !x.second->Restore(stg,m_xratio,m_yratio))
					x.second->RestoreDefault();
		}
	protected:
		IStorge& m_stgTop;
		std::pair<long,long> m_xratio;
		std::pair<long,long> m_yratio;
	};
    struct CDefRestorer
    {
        void operator() (std::pair<const ID,CItem>& x) const
        {
			x.second->RestoreDefault();
        }
    };
public:
	CContainerImpl(void)
		:m_nextFreeID(/*std::numeric_limits<ID>::max()*/ULONG_MAX)
	{
	}
	ID GetUniqueID(void) const
	{
		return m_nextFreeID--;
	}
	virtual bool Store(IStorge& stg)
	{
        std::for_each(m_bunch.begin(),m_bunch.end(),CStorer(stg));
		return true;
	}
	virtual bool Restore(IStorge& stg,const std::pair<long,long>& xratio,const std::pair<long,long>& yratio)
	{
        std::for_each(m_bunch.begin(),m_bunch.end(),CRestorer(stg,xratio,yratio));
		return true;
	}
	virtual bool RestoreDefault(void)
	{
        std::for_each(m_bunch.begin(),m_bunch.end(),CDefRestorer());
		return true;
	}
	ID Add(IState* pState)
	{
		ID id=GetUniqueID();
		Add(id,pState);
		return id;
	}
	void Add(ID id,IState* pState)
	{
		CStateHolder<IState> h (pState);
		m_bunch[id]=h;
	}
	void Remove(ID id)
	{
		assert(m_bunch.find(id)!=m_bunch.end());
		m_bunch.erase(id);
	}
protected:
	mutable ID	m_nextFreeID;
	CBunch m_bunch;
};

namespace
{
	class SetWindowPlacementInsensibly
	{
	public:
		SetWindowPlacementInsensibly(HWND hWnd,const WINDOWPLACEMENT* wp)
			:m_hWnd(hWnd)
		{
			m_oldWindowProc=(WNDPROC)(::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC,LONG_PTR(&WndProc)));
			::SetWindowPlacement(m_hWnd,wp);
		}
		~SetWindowPlacementInsensibly(void)
		{
			::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC,LONG_PTR(m_oldWindowProc));
		}
		static LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
		{
			LRESULT res=0;
			switch(uMsg)
			{
			case WM_PAINT:
			case WM_NCACTIVATE:
			case WM_ACTIVATE:
			case WM_SIZE:
				break;
			default:
				res=::DefWindowProc(hWnd,uMsg,wParam,lParam);
			}
			return res;
		}
	private:
		HWND m_hWnd;
		WNDPROC m_oldWindowProc;
	};
}

template<class TStorage>
class CWindowStateMgr
{
protected:
	class CImpl 
		: public CContainerImpl<TStorage>
	{
		typedef CContainerImpl<TStorage> baseClass;
	public:
		CImpl(HWND hWnd=NULL,int nDefCmdShow=SW_SHOWDEFAULT)
			:m_hWnd(hWnd),m_nDefCmdShow(nDefCmdShow)
		{
		}
        void SetWindow(HWND hWnd=NULL,int nDefCmdShow=SW_SHOWDEFAULT)
        {
            assert(::IsWindow(hWnd));
            m_hWnd=hWnd;
            m_nDefCmdShow=nDefCmdShow;
        }
		virtual bool Store(IStorge& stg)
		{
			assert(IsWindow(m_hWnd));

            WINDOWPLACEMENT wp;
            wp.length = sizeof(WINDOWPLACEMENT);
            bool bRes=false;
            if (::GetWindowPlacement(m_hWnd,&wp))
            {
				if(wp.showCmd==SW_SHOWMINIMIZED)
					wp.showCmd=SW_SHOWNORMAL;
				wp.flags&=WPF_RESTORETOMAXIMIZED;
//				if(::IsZoomed(m_hWnd))
//					wp.flags |= WPF_RESTORETOMAXIMIZED;
				if(wp.flags!=0)
					wp.showCmd=SW_SHOWMAXIMIZED;
				bRes=(stg.SetBinary(ctxtPlacement,&wp,sizeof(WINDOWPLACEMENT))==ERROR_SUCCESS);
/*
                bRes=(::RegSetValueEx(key,ctxtPlacement,NULL,REG_BINARY,
										reinterpret_cast<CONST BYTE *>(&wp),
										sizeof(WINDOWPLACEMENT))==ERROR_SUCCESS);
*/
            }
			return baseClass::Store(stg);
		}
		virtual bool Restore(IStorge& stg,const std::pair<long,long>& xratio,const std::pair<long,long>& yratio)
		{
			assert(IsWindow(m_hWnd));
            WINDOWPLACEMENT wp;
/*
            DWORD dwType;
            DWORD cbData=sizeof(WINDOWPLACEMENT);
            bool bRes=(::RegQueryValueEx(key,ctxtPlacement,NULL,&dwType,
											reinterpret_cast<LPBYTE>(&wp),&cbData)==ERROR_SUCCESS)
											&&(dwType==REG_BINARY);
*/
			size_t size=sizeof(WINDOWPLACEMENT);
			bool bRes=(stg.GetBinary(ctxtPlacement,&wp,size)==ERROR_SUCCESS
							&& (size==sizeof(WINDOWPLACEMENT)));
            if(bRes)
			{
				wp.ptMaxPosition.x=long(::MulDiv(wp.ptMaxPosition.x,xratio.first,xratio.second));
				wp.ptMaxPosition.y=long(::MulDiv(wp.ptMaxPosition.y,yratio.first,yratio.second));
				wp.ptMinPosition.x=long(::MulDiv(wp.ptMinPosition.x,xratio.first,xratio.second));
				wp.ptMinPosition.y=long(::MulDiv(wp.ptMinPosition.y,yratio.first,yratio.second));

				wp.rcNormalPosition.left=long(::MulDiv(wp.rcNormalPosition.left,xratio.first,xratio.second));
				wp.rcNormalPosition.top=long(::MulDiv(wp.rcNormalPosition.top,yratio.first,yratio.second));
				wp.rcNormalPosition.right=long(::MulDiv(wp.rcNormalPosition.right,xratio.first,xratio.second));
				wp.rcNormalPosition.bottom=long(::MulDiv(wp.rcNormalPosition.bottom,yratio.first,yratio.second));

				UINT showCmd=((m_nDefCmdShow&ForceDefaultCmdShow)!=0)
											? m_nDefCmdShow&(~ForceDefaultCmdShow) 
											: wp.showCmd;
				wp.showCmd=SW_HIDE;
				if(showCmd==SW_MAXIMIZE)
				{
					RECT rc;
					GetWorkAreaOfMonitorFromWindow(&rc);
					::SetWindowPos(m_hWnd,0,rc.left,rc.top,
											rc.right-rc.left,
											rc.bottom-rc.top,
												SWP_DEFERERASE|SWP_NOREDRAW|/*SWP_NOCOPYBITS|*/
												SWP_NOACTIVATE|SWP_NOZORDER);

					bRes=baseClass::Restore(stg,xratio,yratio);
					{
						SetWindowPlacementInsensibly(m_hWnd,&wp);
					}
					::ShowWindow(m_hWnd,SW_MAXIMIZE);
					::SetWindowPos(m_hWnd,0,0,0,0,0,
										SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
										SWP_DRAWFRAME | SWP_FRAMECHANGED |
										SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
				}
				else
				{
					::SetWindowPlacement(m_hWnd,&wp);
					bRes=baseClass::Restore(stg,xratio,yratio);
					::ShowWindow(m_hWnd,showCmd);
				}
				::SetForegroundWindow(m_hWnd);	// Win95 needs this
			}
			else
				bRes=baseClass::RestoreDefault();
			return bRes;
		}
		virtual bool RestoreDefault(void)
		{
			assert(IsWindow(m_hWnd));
			bool bRes=baseClass::RestoreDefault();
			ShowWindow(m_hWnd,m_nDefCmdShow&(~ForceDefaultCmdShow));
			return bRes;
		}

		void GetWorkAreaOfMonitorFromWindow(RECT* rc)
		{

#ifdef HMONITOR_DECLARED
			MONITORINFO info;
			info.cbSize=sizeof(MONITORINFO);
			HMONITOR mon;
			if(m_hWnd!=0
				&& ( (mon=::MonitorFromWindow(m_hWnd,MONITOR_DEFAULTTOPRIMARY))!=0 )
					&& (::GetMonitorInfo(mon,&info)))
						::CopyRect(rc,&info.rcWork);
			else
#endif// HMONITOR_DECLARED
			{
				if(!::SystemParametersInfo(SPI_GETWORKAREA,0,rc,0))
				{
					rc->left=rc->top=0;
					rc->right=::GetSystemMetrics(SM_CXFULLSCREEN);
					rc->bottom=::GetSystemMetrics(SM_CYFULLSCREEN);
				}
			}
		}

	protected:
		HWND	m_hWnd;
		int		m_nDefCmdShow;
	};
public:
	CWindowStateMgr(HWND hWnd=NULL,int nDefCmdShow=SW_SHOWDEFAULT)
	{
		m_pImpl=new CImpl(hWnd,nDefCmdShow);
	}
	~CWindowStateMgr(void)
	{
		assert(m_pImpl);
		m_pImpl->Release();
	}
	operator IState* (void)
	{
		return m_pImpl;
	}
	ID Add(IState* pState)
	{
		return m_pImpl->Add(pState);
	}
	void Add(ID id,IState* pState)
	{
		m_pImpl->Add(id,pState);
	}
	void Remove(ID id)
	{
		m_pImpl->Remove(id);
	}

    void Initialize(HWND hWnd,int nDefCmdShow=SW_SHOWDEFAULT)
    {
		m_pImpl->SetWindow(hWnd,nDefCmdShow);
    }

    bool Store(TStorage& stgMain)
    {
		TStorage general;
		if(general.Create(stgMain,ctxtGeneral,IStorge::ReadWrite)==ERROR_SUCCESS)
		{
			RECT rc;
			m_pImpl->GetWorkAreaOfMonitorFromWindow(&rc);
			DWORD val=rc.right-rc.left/*::GetSystemMetrics(SM_CXSCREEN)*/;
			general.SetBinary(ctxtCXScreen,&val,sizeof(DWORD));
			val=rc.bottom-rc.top/*::GetSystemMetrics(SM_CYSCREEN)*/;
			general.SetBinary(ctxtCYScreen,&val,sizeof(DWORD));
		}

		TStorage stg;
		bool bRes=(stg.Create(stgMain,ctxtMainWindow,IStorge::ReadWrite)==ERROR_SUCCESS);
		if(bRes)
			bRes=m_pImpl->Store(stg);

//         DWORD dwDisposition;
// 		CRegKey keyMain;
//         if(keyMain.Create(HKEY_CURRENT_USER,m_strMainKey.c_str(),REG_NONE,
//                                     REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ,
//                                     NULL,&dwDisposition)==ERROR_SUCCESS)
//         {
//             CRegKey keyGeneral;
//             if(keyGeneral.Create(keyMain,ctxtGeneral,REG_NONE,
// 										REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ,
// 										NULL,&dwDisposition)==ERROR_SUCCESS)
//             {
// 
// 				DWORD val=::GetSystemMetrics(SM_CXSCREEN);
// 				::RegSetValueEx(keyGeneral, ctxtCXScreen, NULL, REG_DWORD,
// 								reinterpret_cast<BYTE*>(&val), sizeof(DWORD));
// 				val=::GetSystemMetrics(SM_CYSCREEN);
// 				::RegSetValueEx(keyGeneral, ctxtCYScreen, NULL, REG_DWORD,
// 								reinterpret_cast<BYTE*>(&val), sizeof(DWORD));
// /*
// 				keyGeneral.SetValue(::GetSystemMetrics(SM_CXSCREEN),ctxtCXScreen);
// 				keyGeneral.SetValue(::GetSystemMetrics(SM_CYSCREEN),ctxtCYScreen);
// */
//             }
//             CRegKey key;
//             if(key.Create(keyMain,ctxtMainWindow,REG_NONE,
// 							REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ,
// 							NULL,&dwDisposition)==ERROR_SUCCESS)
// 									m_pImpl->Store(key);
//         }
		return bRes;
    }

    bool Restore(TStorage& stgMain)
    {
		TStorage general;
		bool bRes=(general.Open(stgMain,ctxtGeneral,IStorge::Read)==ERROR_SUCCESS);
		if(bRes)
		{
			RECT rc;
			m_pImpl->GetWorkAreaOfMonitorFromWindow(&rc);
			std::pair<long,long> xratio(rc.right-rc.left,1);
			std::pair<long,long> yratio(rc.bottom-rc.top,1);
			DWORD val;
			size_t size = sizeof(DWORD);
			if(general.GetBinary(ctxtCXScreen,&val,size)==ERROR_SUCCESS
				&& (size == sizeof(DWORD))
					&& (xratio.first!=long(val)))
						xratio.second=long(val);
			else
				xratio.first=1;

			size = sizeof(DWORD);
			if(general.GetBinary(ctxtCYScreen,&val,size)==ERROR_SUCCESS
				&& (size == sizeof(DWORD))
					&& (yratio.first!=long(val)))
				yratio.second=long(val);
			else
				yratio.first=1;
/*
            SIZE szScreen;
			size_t size = sizeof(DWORD);
			float xratio=(general.GetBinary(ctxtCXScreen,&szScreen.cx,size)==ERROR_SUCCESS
							 && (size == sizeof(DWORD))
                                            ?float(::GetSystemMetrics(SM_CXSCREEN))/szScreen.cx
                                            :float(1.0));
				
			size = sizeof(DWORD);
			float yratio=(general.GetBinary(ctxtCYScreen,&szScreen.cy,size)==ERROR_SUCCESS
							&& (size == sizeof(DWORD))
                                            ?float(::GetSystemMetrics(SM_CYSCREEN))/szScreen.cy
                                            :float(1.0));
*/
			TStorage stg;
			bRes=(stg.Open(stgMain,ctxtMainWindow,IStorge::Read)==ERROR_SUCCESS
							&& m_pImpl->Restore(stg,xratio,yratio));
		}

// 		CRegKey keyMain;
//         CRegKey keyGeneral;
// 		bool bRes=keyMain.Open(HKEY_CURRENT_USER,m_strMainKey.c_str(),KEY_READ)==ERROR_SUCCESS
// 									&& (keyGeneral.Open(keyMain,ctxtGeneral,KEY_READ)==ERROR_SUCCESS);
//         if(bRes)
//         {
//             SIZE szScreen;
// 			DWORD dwCount = sizeof(DWORD);
// 			float xratio=(::RegQueryValueEx(keyGeneral,ctxtCXScreen,NULL,NULL,
// 							reinterpret_cast<LPBYTE>(&szScreen.cx),&dwCount) ==ERROR_SUCCESS
// 								&& (dwCount == sizeof(DWORD)))
//                                             ?float(::GetSystemMetrics(SM_CXSCREEN))/szScreen.cx
//                                             :float(1.0);
// 			dwCount = sizeof(DWORD);
// 			float yratio=(::RegQueryValueEx(keyGeneral,ctxtCYScreen,NULL,NULL,
// 							reinterpret_cast<LPBYTE>(&szScreen.cy),&dwCount) ==ERROR_SUCCESS
// 								&&(dwCount == sizeof(DWORD)))
//                                             ?float(::GetSystemMetrics(SM_CYSCREEN))/szScreen.cy
//                                             :float(1.0);
// /*
//             xratio=(keyGeneral.QueryValue(reinterpret_cast<DWORD&>(szScreen.cx),ctxtCXScreen)==ERROR_SUCCESS)
//                                             ?float(::GetSystemMetrics(SM_CXSCREEN))/szScreen.cx
//                                             :float(1.0);
//             yratio=(keyGeneral.QueryValue(reinterpret_cast<DWORD&>(szScreen.cy),ctxtCYScreen)==ERROR_SUCCESS)
//                                             ?float(::GetSystemMetrics(SM_CYSCREEN))/szScreen.cy
//                                             :float(1.0);
// */
// 			CRegKey key;
// 			bRes=key.Open(keyMain,ctxtMainWindow,KEY_READ)==ERROR_SUCCESS
// 					&&	m_pImpl->Restore(key,xratio,yratio);
// 
//         }

		if(!bRes)
			bRes=m_pImpl->RestoreDefault();
        return bRes;
    }
	bool RestoreDefault(void)
	{
		return m_pImpl->RestoreDefault();
	}
protected:
	CImpl*	m_pImpl;
};

class CWindowStateAdapter
{
protected:
	class CImpl : public CStateBase<IState>
	{
	public:
		CImpl(HWND hWnd,int nDefCmdShow=SW_SHOWNA)
			:m_hWnd(hWnd),m_nDefCmdShow(nDefCmdShow)
		{
			assert(::IsWindow(hWnd));
		}
		virtual bool Store(IStorge& stg)
		{
            WINDOWPLACEMENT wp;
            wp.length = sizeof(WINDOWPLACEMENT);
            assert(::IsWindow(m_hWnd));
            bool bRes=false;
            if (::GetWindowPlacement(m_hWnd,&wp))
            {
                wp.flags = 0;
                if (::IsZoomed(m_hWnd))
                        wp.flags |= WPF_RESTORETOMAXIMIZED;
/*
                bRes=(::RegSetValueEx(key,ctxtPlacement,NULL,REG_BINARY,
										reinterpret_cast<CONST BYTE *>(&wp),
										sizeof(WINDOWPLACEMENT))==ERROR_SUCCESS);
*/
				bRes=(stg.SetBinary(ctxtPlacement,&wp,sizeof(WINDOWPLACEMENT))==ERROR_SUCCESS);
            }
			return bRes;
		}
		virtual bool Restore(IStorge& stg,const std::pair<long,long>& /*xratio*/,const std::pair<long,long>& /*yratio*/)
		{
            assert(::IsWindow(m_hWnd));
            WINDOWPLACEMENT wp;
/*
            DWORD dwType;
            DWORD cbData=sizeof(WINDOWPLACEMENT);
            bool bRes=(::RegQueryValueEx(key,ctxtPlacement,NULL,&dwType,
											reinterpret_cast<LPBYTE>(&wp),&cbData)==ERROR_SUCCESS)
											&&(dwType==REG_BINARY);
*/
            size_t size=sizeof(WINDOWPLACEMENT);
			bool bRes=(stg.GetBinary(ctxtPlacement,&wp,size)==ERROR_SUCCESS
						&& (size == sizeof(WINDOWPLACEMENT) ) );
            if(bRes)
                    bRes=(::SetWindowPlacement(m_hWnd,&wp)!=FALSE);
            return bRes;
		}
		virtual bool RestoreDefault(void)
		{
			::ShowWindow(m_hWnd,m_nDefCmdShow);
			return true;
		}
	protected:
		HWND	m_hWnd;
		int		m_nDefCmdShow;
	};
public:
    CWindowStateAdapter(HWND hWnd,int nDefCmdShow=SW_SHOWNOACTIVATE)
    {
		m_pImpl = new CImpl(hWnd,nDefCmdShow);
    }
	~CWindowStateAdapter(void)
	{
		assert(m_pImpl);
		m_pImpl->Release();
	}
	operator IState* (void)
	{
		return m_pImpl;
	}
protected:
	CImpl* m_pImpl;
};

class CToggleWindowAdapter
{
protected:
	class CImpl : public CStateBase<IState>
	{
	public:
		CImpl(HWND hWnd,int nDefCmdShow=SW_SHOWNA)
			:m_hWnd(hWnd),m_nDefCmdShow(nDefCmdShow)
		{
			assert(::IsWindow(hWnd));
		}
		virtual bool Store(IStorge& stg)
		{
			DWORD visible=(::GetWindowLong(m_hWnd,GWL_STYLE)&WS_VISIBLE)!=0;
//			DWORD visible=::IsWindowVisible(m_hWnd);
/*
			return (::RegSetValueEx(key, ctxtVisible, NULL, REG_DWORD,
								reinterpret_cast<BYTE*>(&visible), sizeof(DWORD))==ERROR_SUCCESS);
//            return (key.SetValue(visible,ctxtVisible)==ERROR_SUCCESS);
*/
			return (stg.SetBinary(ctxtVisible,&visible,sizeof(DWORD))==ERROR_SUCCESS);
		}
		virtual bool Restore(IStorge& stg,const std::pair<long,long>& /*xratio*/,const std::pair<long,long>& /*yratio*/)
		{
            DWORD visible;
//          bool bRes=(key.QueryValue(visible,ctxtVisible)==ERROR_SUCCESS);
/*
			DWORD dwCount = sizeof(DWORD);
			bool bRes=(::RegQueryValueEx(key,ctxtVisible,NULL,NULL,
								reinterpret_cast<LPBYTE>(&visible),&dwCount)==ERROR_SUCCESS
									 && (dwCount == sizeof(DWORD)));
*/
			size_t size=sizeof(DWORD);
			bool bRes=(stg.GetBinary(ctxtVisible,&visible,size)==ERROR_SUCCESS
							&& (size==sizeof(DWORD)));
            if(bRes)
                    ::ShowWindow(m_hWnd, (visible!=0) ? SW_SHOWNA : SW_HIDE);
            else
                    RestoreDefault();
            return bRes;
		}
		virtual bool RestoreDefault(void)
		{
            ::ShowWindow(m_hWnd,m_nDefCmdShow);
            return true;
		}
	protected:
		HWND	m_hWnd;
		int		m_nDefCmdShow;
	};
public:
    CToggleWindowAdapter(HWND hWnd,int nDefCmdShow=SW_SHOWNOACTIVATE)
    {
		m_pImpl = new CImpl(hWnd,nDefCmdShow);
    }
	~CToggleWindowAdapter(void)
	{
		assert(m_pImpl);
		m_pImpl->Release();
	}
	operator IState* (void)
	{
		return m_pImpl;
	}
protected:
	CImpl* m_pImpl;
};

class CRebarStateAdapter
{
protected:
	class CImpl : public CStateBase<IState>
	{
	public:
		CImpl(HWND hWnd)
			:m_rebar(hWnd)
		{
			assert(::IsWindow(hWnd));
		}

		virtual bool Store(IStorge& stg)
		{
			assert(m_rebar.IsWindow());
			unsigned int bandCount=m_rebar.GetBandCount();
			for(unsigned int i=0;i<bandCount;i++)
			{
				std::basic_ostringstream<TCHAR> sstrKey;
				sstrKey<<ctxtBand<<i;
				REBARBANDINFO rbi;
				ZeroMemory(&rbi,sizeof(REBARBANDINFO));
				rbi.cbSize = sizeof(REBARBANDINFO);
				rbi.fMask = RBBIM_ID | RBBIM_COLORS |
							RBBIM_SIZE | RBBIM_STYLE
							| RBBIM_CHILDSIZE
							#if (_WIN32_IE >= 0x0400)
								| /*RBBIM_HEADERSIZE |*/ RBBIM_IDEALSIZE
							#endif
								;
				m_rebar.GetBandInfo(i, &rbi);
/*
				::RegSetValueEx(key,sstrKey.str().c_str(),NULL,REG_BINARY,
								reinterpret_cast<CONST BYTE *>(&rbi),
								rbi.cbSize);
*/
				stg.SetBinary(sstrKey.str().c_str(),&rbi,size_t(rbi.cbSize));
			}
			return true;
		}

		virtual bool Restore(IStorge& stg,const std::pair<long,long>& /*xratio*/,const std::pair<long,long>& /*yratio*/)
		{
			unsigned int bandCount=m_rebar.GetBandCount();
			for(unsigned int i=0;i<bandCount;i++)
			{
				std::basic_ostringstream<TCHAR> sstrKey;
				sstrKey<<ctxtBand<<i;
				REBARBANDINFO rbi;
				//ZeroMemory(&rbi,sizeof(REBARBANDINFO));
/*
				DWORD dwType;
				DWORD cbData=sizeof(REBARBANDINFO);
	            if((::RegQueryValueEx(key,sstrKey.str().c_str(),NULL,&dwType,
							reinterpret_cast<LPBYTE>(&rbi),&cbData)==ERROR_SUCCESS)
							&&(dwType==REG_BINARY))
*/
				size_t size=sizeof(REBARBANDINFO);
				if(stg.GetBinary(sstrKey.str().c_str(),&rbi,size)==ERROR_SUCCESS
					&& (size==sizeof(REBARBANDINFO)))
				{
					m_rebar.MoveBand(m_rebar.IdToIndex(rbi.wID), i);
					m_rebar.SetBandInfo(i, &rbi);
				}
			}
			return true;

		}
		virtual bool RestoreDefault(void)
		{
			return true;
		}
	protected:
		CReBarCtrl m_rebar;
	};
public:
    CRebarStateAdapter(HWND hWnd)
    {
		m_pImpl = new CImpl(hWnd);
    }
	~CRebarStateAdapter(void)
	{
		assert(m_pImpl);
		m_pImpl->Release();
	}
	operator IState* (void)
	{
		return m_pImpl;
	}
protected:
	CImpl* m_pImpl;
};

template <bool t_bVertical = true>
class CSplitterWindowStateAdapter
{
protected:
	template <bool t_bVertical>
	class CImplT : public CStateBase<IState>
	{
	public:
		CImplT(CSplitterWindow& splitter,int defaultPos)
			:m_splitter(splitter)
			,m_defaultPos(defaultPos)
		{
		}

		virtual bool Store(IStorge& stg)
		{
			int pos=m_splitter.GetSplitterPos();
			return (stg.SetBinary(ctxtPosition,&pos,sizeof(int))==ERROR_SUCCESS);
		}

		virtual bool Restore(IStorge& stg,const std::pair<long,long>& xratio,const std::pair<long,long>& yratio)
		{
			int pos;
			size_t size=sizeof(int);
			bool res=(stg.GetBinary(ctxtPosition,&pos,size)==ERROR_SUCCESS
							&& (size==sizeof(int)));
			if(res)
			{
				if(t_bVertical)
					pos=::MulDiv(pos,xratio.first,xratio.second);
				else
					pos=::MulDiv(pos,yratio.first,yratio.second);
				m_splitter.SetSplitterPos(pos);
			}
			return true;

		}
		virtual bool RestoreDefault(void)
		{
			m_splitter.SetSplitterPos(m_defaultPos);
			return true;
		}
	protected:
		CSplitterWindowT<t_bVertical>& m_splitter;
		int m_defaultPos;
	};
	typedef CImplT<t_bVertical> CImpl;
public:
    CSplitterWindowStateAdapter(CSplitterWindow& splitter,int defaultPos=-1)
    {
		m_pImpl = new CImpl(splitter,defaultPos);
    }
	~CSplitterWindowStateAdapter(void)
	{
		assert(m_pImpl);
		m_pImpl->Release();
	}
	operator IState* (void)
	{
		return m_pImpl;
	}
protected:
	CImpl* m_pImpl;
};

}//namespace sstate
#endif // WTL_DW_SSTATE_H_INCLUDED_

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


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

Comments and Discussions