| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129 | 
							- // Windows Template Library - WTL version 10.0
 
- // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
 
- //
 
- // This file is a part of the Windows Template Library.
 
- // The use and distribution terms for this software are covered by the
 
- // Microsoft Public License (http://opensource.org/licenses/MS-PL)
 
- // which can be found in the file MS-PL.txt at the root folder.
 
- #ifndef __ATLSPLIT_H__
 
- #define __ATLSPLIT_H__
 
- #pragma once
 
- #ifndef __ATLAPP_H__
 
- 	#error atlsplit.h requires atlapp.h to be included first
 
- #endif
 
- #ifndef __ATLWIN_H__
 
- 	#error atlsplit.h requires atlwin.h to be included first
 
- #endif
 
- ///////////////////////////////////////////////////////////////////////////////
 
- // Classes in this file:
 
- //
 
- // CSplitterImpl<T>
 
- // CSplitterWindowImpl<T, TBase, TWinTraits>
 
- // CSplitterWindowT<t_bVertical> - CSplitterWindow, CHorSplitterWindow
 
- namespace WTL
 
- {
 
- ///////////////////////////////////////////////////////////////////////////////
 
- // CSplitterImpl - Provides splitter support to any window
 
- // Splitter panes constants
 
- #define SPLIT_PANE_LEFT			 0
 
- #define SPLIT_PANE_RIGHT		 1
 
- #define SPLIT_PANE_TOP			 SPLIT_PANE_LEFT
 
- #define SPLIT_PANE_BOTTOM		 SPLIT_PANE_RIGHT
 
- #define SPLIT_PANE_NONE			-1
 
- // Splitter extended styles
 
- #define SPLIT_PROPORTIONAL		0x00000001
 
- #define SPLIT_NONINTERACTIVE		0x00000002
 
- #define SPLIT_RIGHTALIGNED		0x00000004
 
- #define SPLIT_BOTTOMALIGNED		SPLIT_RIGHTALIGNED
 
- #define SPLIT_GRADIENTBAR		0x00000008
 
- #define SPLIT_FLATBAR			0x00000020
 
- #define SPLIT_FIXEDBARSIZE		0x00000010
 
- // Note: SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED are 
 
- // mutually exclusive. If both are set, splitter defaults to SPLIT_PROPORTIONAL.
 
- // Also, SPLIT_FLATBAR overrides SPLIT_GRADIENTBAR if both are set.
 
- template <class T>
 
- class CSplitterImpl
 
- {
 
- public:
 
- 	enum { m_nPanesCount = 2, m_nPropMax = INT_MAX, m_cxyStep = 10 };
 
- 	bool m_bVertical;
 
- 	HWND m_hWndPane[m_nPanesCount];
 
- 	RECT m_rcSplitter;
 
- 	int m_xySplitterPos;            // splitter bar position
 
- 	int m_xySplitterPosNew;         // internal - new position while moving
 
- 	HWND m_hWndFocusSave;
 
- 	int m_nDefActivePane;
 
- 	int m_cxySplitBar;              // splitter bar width/height
 
- 	HCURSOR m_hCursor;
 
- 	int m_cxyMin;                   // minimum pane size
 
- 	int m_cxyBarEdge;              	// splitter bar edge
 
- 	bool m_bFullDrag;
 
- 	int m_cxyDragOffset;		// internal
 
- 	int m_nProportionalPos;
 
- 	bool m_bUpdateProportionalPos;
 
- 	DWORD m_dwExtendedStyle;        // splitter specific extended styles
 
- 	int m_nSinglePane;              // single pane mode
 
- 	int m_xySplitterDefPos;         // default position
 
- 	bool m_bProportionalDefPos;     // porportinal def pos
 
- // Constructor
 
- 	CSplitterImpl(bool bVertical = true) : 
 
- 	              m_bVertical(bVertical), m_xySplitterPos(-1), m_xySplitterPosNew(-1), m_hWndFocusSave(NULL), 
 
- 	              m_nDefActivePane(SPLIT_PANE_NONE), m_cxySplitBar(4), m_hCursor(NULL), m_cxyMin(0), m_cxyBarEdge(0), 
 
- 	              m_bFullDrag(true), m_cxyDragOffset(0), m_nProportionalPos(0), m_bUpdateProportionalPos(true),
 
- 	              m_dwExtendedStyle(SPLIT_PROPORTIONAL), m_nSinglePane(SPLIT_PANE_NONE), 
 
- 	              m_xySplitterDefPos(-1), m_bProportionalDefPos(false)
 
- 	{
 
- 		m_hWndPane[SPLIT_PANE_LEFT] = NULL;
 
- 		m_hWndPane[SPLIT_PANE_RIGHT] = NULL;
 
- 		::SetRectEmpty(&m_rcSplitter);
 
- 	}
 
- // Attributes
 
- 	void SetSplitterRect(LPRECT lpRect = NULL, bool bUpdate = true)
 
- 	{
 
- 		if(lpRect == NULL)
 
- 		{
 
- 			T* pT = static_cast<T*>(this);
 
- 			pT->GetClientRect(&m_rcSplitter);
 
- 		}
 
- 		else
 
- 		{
 
- 			m_rcSplitter = *lpRect;
 
- 		}
 
- 		if(IsProportional())
 
- 			UpdateProportionalPos();
 
- 		else if(IsRightAligned())
 
- 			UpdateRightAlignPos();
 
- 		if(bUpdate)
 
- 			UpdateSplitterLayout();
 
- 	}
 
- 	void GetSplitterRect(LPRECT lpRect) const
 
- 	{
 
- 		ATLASSERT(lpRect != NULL);
 
- 		*lpRect = m_rcSplitter;
 
- 	}
 
- 	bool SetSplitterPos(int xyPos = -1, bool bUpdate = true)
 
- 	{
 
- 		if(xyPos == -1)   // -1 == default position
 
- 		{
 
- 			if(m_bProportionalDefPos)
 
- 			{
 
- 				ATLASSERT((m_xySplitterDefPos >= 0) && (m_xySplitterDefPos <= m_nPropMax));
 
- 				if(m_bVertical)
 
- 					xyPos = ::MulDiv(m_xySplitterDefPos, m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge, m_nPropMax);
 
- 				else
 
- 					xyPos = ::MulDiv(m_xySplitterDefPos, m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge, m_nPropMax);
 
- 			}
 
- 			else if(m_xySplitterDefPos != -1)
 
- 			{
 
- 				xyPos = m_xySplitterDefPos;
 
- 			}
 
- 			else   // not set, use middle position
 
- 			{
 
- 				if(m_bVertical)
 
- 					xyPos = (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) / 2;
 
- 				else
 
- 					xyPos = (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge) / 2;
 
- 			}
 
- 		}
 
- 		// Adjust if out of valid range
 
- 		int cxyMax = 0;
 
- 		if(m_bVertical)
 
- 			cxyMax = m_rcSplitter.right - m_rcSplitter.left;
 
- 		else
 
- 			cxyMax = m_rcSplitter.bottom - m_rcSplitter.top;
 
- 		if(xyPos < m_cxyMin + m_cxyBarEdge)
 
- 			xyPos = m_cxyMin;
 
- 		else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin))
 
- 			xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin;
 
- 		// Set new position and update if requested
 
- 		bool bRet = (m_xySplitterPos != xyPos);
 
- 		m_xySplitterPos = xyPos;
 
- 		if(m_bUpdateProportionalPos)
 
- 		{
 
- 			if(IsProportional())
 
- 				StoreProportionalPos();
 
- 			else if(IsRightAligned())
 
- 				StoreRightAlignPos();
 
- 		}
 
- 		else
 
- 		{
 
- 			m_bUpdateProportionalPos = true;
 
- 		}
 
- 		if(bUpdate && bRet)
 
- 			UpdateSplitterLayout();
 
- 		return bRet;
 
- 	}
 
- 	int GetSplitterPos() const
 
- 	{
 
- 		return m_xySplitterPos;
 
- 	}
 
- 	void SetSplitterPosPct(int nPct, bool bUpdate = true)
 
- 	{
 
- 		ATLASSERT((nPct >= 0) && (nPct <= 100));
 
- 		m_nProportionalPos = ::MulDiv(nPct, m_nPropMax, 100);
 
- 		UpdateProportionalPos();
 
- 		if(bUpdate)
 
- 			UpdateSplitterLayout();
 
- 	}
 
- 	int GetSplitterPosPct() const
 
- 	{
 
- 		int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
 
- 		return ((cxyTotal > 0) && (m_xySplitterPos >= 0)) ? ::MulDiv(m_xySplitterPos, 100, cxyTotal) : -1;
 
- 	}
 
- 	bool SetSinglePaneMode(int nPane = SPLIT_PANE_NONE)
 
- 	{
 
- 		ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT) || (nPane == SPLIT_PANE_NONE));
 
- 		if(!((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT) || (nPane == SPLIT_PANE_NONE)))
 
- 			return false;
 
- 		if(nPane != SPLIT_PANE_NONE)
 
- 		{
 
- 			if(::IsWindowVisible(m_hWndPane[nPane]) == FALSE)
 
- 				::ShowWindow(m_hWndPane[nPane], SW_SHOW);
 
- 			int nOtherPane = (nPane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT;
 
- 			::ShowWindow(m_hWndPane[nOtherPane], SW_HIDE);
 
- 			if(m_nDefActivePane != nPane)
 
- 				m_nDefActivePane = nPane;
 
- 		}
 
- 		else if(m_nSinglePane != SPLIT_PANE_NONE)
 
- 		{
 
- 			int nOtherPane = (m_nSinglePane == SPLIT_PANE_LEFT) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT;
 
- 			::ShowWindow(m_hWndPane[nOtherPane], SW_SHOW);
 
- 		}
 
- 		m_nSinglePane = nPane;
 
- 		UpdateSplitterLayout();
 
- 		return true;
 
- 	}
 
- 	int GetSinglePaneMode() const
 
- 	{
 
- 		return m_nSinglePane;
 
- 	}
 
- 	DWORD GetSplitterExtendedStyle() const
 
- 	{
 
- 		return m_dwExtendedStyle;
 
- 	}
 
- 	DWORD SetSplitterExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
 
- 	{
 
- 		DWORD dwPrevStyle = m_dwExtendedStyle;
 
- 		if(dwMask == 0)
 
- 			m_dwExtendedStyle = dwExtendedStyle;
 
- 		else
 
- 			m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
 
- #ifdef _DEBUG
 
- 		if(IsProportional() && IsRightAligned())
 
- 			ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::SetSplitterExtendedStyle - SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED are mutually exclusive, defaulting to SPLIT_PROPORTIONAL.\n"));
 
- #endif // _DEBUG
 
- 		return dwPrevStyle;
 
- 	}
 
- 	void SetSplitterDefaultPos(int xyPos = -1)
 
- 	{
 
- 		m_xySplitterDefPos = xyPos;
 
- 		m_bProportionalDefPos = false;
 
- 	}
 
- 	void SetSplitterDefaultPosPct(int nPct)
 
- 	{
 
- 		ATLASSERT((nPct >= 0) && (nPct <= 100));
 
- 		m_xySplitterDefPos = ::MulDiv(nPct, m_nPropMax, 100);
 
- 		m_bProportionalDefPos = true;
 
- 	}
 
- // Splitter operations
 
- 	void SetSplitterPanes(HWND hWndLeftTop, HWND hWndRightBottom, bool bUpdate = true)
 
- 	{
 
- 		m_hWndPane[SPLIT_PANE_LEFT] = hWndLeftTop;
 
- 		m_hWndPane[SPLIT_PANE_RIGHT] = hWndRightBottom;
 
- 		ATLASSERT((m_hWndPane[SPLIT_PANE_LEFT] == NULL) || (m_hWndPane[SPLIT_PANE_RIGHT] == NULL) || (m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]));
 
- 		if(bUpdate)
 
- 			UpdateSplitterLayout();
 
- 	}
 
- 	bool SetSplitterPane(int nPane, HWND hWnd, bool bUpdate = true)
 
- 	{
 
- 		ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
 
- 		if((nPane != SPLIT_PANE_LEFT) && (nPane != SPLIT_PANE_RIGHT))
 
- 			return false;
 
- 		m_hWndPane[nPane] = hWnd;
 
- 		ATLASSERT((m_hWndPane[SPLIT_PANE_LEFT] == NULL) || (m_hWndPane[SPLIT_PANE_RIGHT] == NULL) || (m_hWndPane[SPLIT_PANE_LEFT] != m_hWndPane[SPLIT_PANE_RIGHT]));
 
- 		if(bUpdate)
 
- 			UpdateSplitterLayout();
 
- 		return true;
 
- 	}
 
- 	HWND GetSplitterPane(int nPane) const
 
- 	{
 
- 		ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
 
- 		if((nPane != SPLIT_PANE_LEFT) && (nPane != SPLIT_PANE_RIGHT))
 
- 			return NULL;
 
- 		return m_hWndPane[nPane];
 
- 	}
 
- 	bool SetActivePane(int nPane)
 
- 	{
 
- 		ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
 
- 		if((nPane != SPLIT_PANE_LEFT) && (nPane != SPLIT_PANE_RIGHT))
 
- 			return false;
 
- 		if((m_nSinglePane != SPLIT_PANE_NONE) && (nPane != m_nSinglePane))
 
- 			return false;
 
- 		::SetFocus(m_hWndPane[nPane]);
 
- 		m_nDefActivePane = nPane;
 
- 		return true;
 
- 	}
 
- 	int GetActivePane() const
 
- 	{
 
- 		int nRet = SPLIT_PANE_NONE;
 
- 		HWND hWndFocus = ::GetFocus();
 
- 		if(hWndFocus != NULL)
 
- 		{
 
- 			for(int nPane = 0; nPane < m_nPanesCount; nPane++)
 
- 			{
 
- 				if((hWndFocus == m_hWndPane[nPane]) || (::IsChild(m_hWndPane[nPane], hWndFocus) != FALSE))
 
- 				{
 
- 					nRet = nPane;
 
- 					break;
 
- 				}
 
- 			}
 
- 		}
 
- 		return nRet;
 
- 	}
 
- 	bool ActivateNextPane(bool bNext = true)
 
- 	{
 
- 		int nPane = m_nSinglePane;
 
- 		if(nPane == SPLIT_PANE_NONE)
 
- 		{
 
- 			switch(GetActivePane())
 
- 			{
 
- 			case SPLIT_PANE_LEFT:
 
- 				nPane = SPLIT_PANE_RIGHT;
 
- 				break;
 
- 			case SPLIT_PANE_RIGHT:
 
- 				nPane = SPLIT_PANE_LEFT;
 
- 				break;
 
- 			default:
 
- 				nPane = bNext ? SPLIT_PANE_LEFT : SPLIT_PANE_RIGHT;
 
- 				break;
 
- 			}
 
- 		}
 
- 		return SetActivePane(nPane);
 
- 	}
 
- 	bool SetDefaultActivePane(int nPane)
 
- 	{
 
- 		ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
 
- 		if((nPane != SPLIT_PANE_LEFT) && (nPane != SPLIT_PANE_RIGHT))
 
- 			return false;
 
- 		m_nDefActivePane = nPane;
 
- 		return true;
 
- 	}
 
- 	bool SetDefaultActivePane(HWND hWnd)
 
- 	{
 
- 		for(int nPane = 0; nPane < m_nPanesCount; nPane++)
 
- 		{
 
- 			if(hWnd == m_hWndPane[nPane])
 
- 			{
 
- 				m_nDefActivePane = nPane;
 
- 				return true;
 
- 			}
 
- 		}
 
- 		return false;   // not found
 
- 	}
 
- 	int GetDefaultActivePane() const
 
- 	{
 
- 		return m_nDefActivePane;
 
- 	}
 
- 	void DrawSplitter(CDCHandle dc)
 
- 	{
 
- 		ATLASSERT(dc.m_hDC != NULL);
 
- 		if((m_nSinglePane == SPLIT_PANE_NONE) && (m_xySplitterPos == -1))
 
- 			return;
 
- 		T* pT = static_cast<T*>(this);
 
- 		if(m_nSinglePane == SPLIT_PANE_NONE)
 
- 		{
 
- 			pT->DrawSplitterBar(dc);
 
- 			for(int nPane = 0; nPane < m_nPanesCount; nPane++)
 
- 			{
 
- 				if(m_hWndPane[nPane] == NULL)
 
- 					pT->DrawSplitterPane(dc, nPane);
 
- 			}
 
- 		}
 
- 		else
 
- 		{
 
- 			if(m_hWndPane[m_nSinglePane] == NULL)
 
- 				pT->DrawSplitterPane(dc, m_nSinglePane);
 
- 		}
 
- 	}
 
- 	// call to initiate moving splitter bar with keyboard
 
- 	void MoveSplitterBar()
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		int x = 0;
 
- 		int y = 0;
 
- 		if(m_bVertical)
 
- 		{
 
- 			x = m_xySplitterPos + (m_cxySplitBar / 2) + m_cxyBarEdge;
 
- 			y = (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge) / 2;
 
- 		}
 
- 		else
 
- 		{
 
- 			x = (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) / 2;
 
- 			y = m_xySplitterPos + (m_cxySplitBar / 2) + m_cxyBarEdge;
 
- 		}
 
- 		POINT pt = { x, y };
 
- 		pT->ClientToScreen(&pt);
 
- 		::SetCursorPos(pt.x, pt.y);
 
- 		m_xySplitterPosNew = m_xySplitterPos;
 
- 		pT->SetCapture();
 
- 		m_hWndFocusSave = pT->SetFocus();
 
- 		::SetCursor(m_hCursor);
 
- 		if(!m_bFullDrag)
 
- 			DrawGhostBar();
 
- 		if(m_bVertical)
 
- 			m_cxyDragOffset = x - m_rcSplitter.left - m_xySplitterPos;
 
- 		else
 
- 			m_cxyDragOffset = y - m_rcSplitter.top - m_xySplitterPos;
 
- 	}
 
- 	void SetOrientation(bool bVertical, bool bUpdate = true)
 
- 	{
 
- 		if(m_bVertical != bVertical)
 
- 		{
 
- 			m_bVertical = bVertical;
 
- 			m_hCursor = ::LoadCursor(NULL, m_bVertical ? IDC_SIZEWE : IDC_SIZENS);
 
- 			T* pT = static_cast<T*>(this);
 
- 			pT->GetSystemSettings(false);
 
- 			if(m_bVertical)
 
- 				m_xySplitterPos = ::MulDiv(m_xySplitterPos, m_rcSplitter.right - m_rcSplitter.left, m_rcSplitter.bottom - m_rcSplitter.top);
 
- 			else
 
- 				m_xySplitterPos = ::MulDiv(m_xySplitterPos, m_rcSplitter.bottom - m_rcSplitter.top, m_rcSplitter.right - m_rcSplitter.left);
 
- 		}
 
- 		if(bUpdate)
 
- 			UpdateSplitterLayout();
 
- 	}
 
- // Overrideables
 
- 	void DrawSplitterBar(CDCHandle dc)
 
- 	{
 
- 		RECT rect = {};
 
- 		if(GetSplitterBarRect(&rect))
 
- 		{
 
- 			dc.FillRect(&rect, COLOR_3DFACE);
 
- 			if((m_dwExtendedStyle & SPLIT_FLATBAR) != 0)
 
- 			{
 
- 				RECT rect1 = rect;
 
- 				if(m_bVertical)
 
- 					rect1.right = rect1.left + 1;
 
- 				else
 
- 					rect1.bottom = rect1.top + 1;
 
- 				dc.FillRect(&rect1, COLOR_WINDOW);
 
- 				rect1 = rect;
 
- 				if(m_bVertical)
 
- 					rect1.left = rect1.right - 1;
 
- 				else
 
- 					rect1.top = rect1.bottom - 1;
 
- 				dc.FillRect(&rect1, COLOR_3DSHADOW);
 
- 			}
 
- 			else if((m_dwExtendedStyle & SPLIT_GRADIENTBAR) != 0)
 
- 			{
 
- 				RECT rect2 = rect;
 
- 				if(m_bVertical)
 
- 					rect2.left = (rect.left + rect.right) / 2 - 1;
 
- 				else
 
- 					rect2.top = (rect.top + rect.bottom) / 2 - 1;
 
- 				dc.GradientFillRect(rect2, ::GetSysColor(COLOR_3DFACE), ::GetSysColor(COLOR_3DSHADOW), m_bVertical);
 
- 			}
 
- 			// draw 3D edge if needed
 
- 			T* pT = static_cast<T*>(this);
 
- 			if((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0)
 
- 				dc.DrawEdge(&rect, EDGE_RAISED, m_bVertical ? (BF_LEFT | BF_RIGHT) : (BF_TOP | BF_BOTTOM));
 
- 		}
 
- 	}
 
- 	// called only if pane is empty
 
- 	void DrawSplitterPane(CDCHandle dc, int nPane)
 
- 	{
 
- 		RECT rect = {};
 
- 		if(GetSplitterPaneRect(nPane, &rect))
 
- 		{
 
- 			T* pT = static_cast<T*>(this);
 
- 			if((pT->GetExStyle() & WS_EX_CLIENTEDGE) == 0)
 
- 				dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
 
- 			dc.FillRect(&rect, COLOR_APPWORKSPACE);
 
- 		}
 
- 	}
 
- // Message map and handlers
 
- 	BEGIN_MSG_MAP(CSplitterImpl)
 
- 		MESSAGE_HANDLER(WM_CREATE, OnCreate)
 
- 		MESSAGE_HANDLER(WM_PAINT, OnPaint)
 
- 		MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
 
- 		if(IsInteractive())
 
- 		{
 
- 			MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
 
- 			MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
 
- 			MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
 
- 			MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
 
- 			MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDoubleClick)
 
- 			MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
 
- 			MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
 
- 		}
 
- 		MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
 
- 		MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
 
- 		MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
 
- 	END_MSG_MAP()
 
- 	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		pT->Init();
 
- 		bHandled = FALSE;
 
- 		return 1;
 
- 	}
 
- 	LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		// try setting position if not set
 
- 		if((m_nSinglePane == SPLIT_PANE_NONE) && (m_xySplitterPos == -1))
 
- 			pT->SetSplitterPos();
 
- 		// do painting
 
- 		if(wParam != NULL)
 
- 		{
 
- 			pT->DrawSplitter((HDC)wParam);
 
- 		}
 
- 		else
 
- 		{
 
- 			CPaintDC dc(pT->m_hWnd);
 
- 			pT->DrawSplitter(dc.m_hDC);
 
- 		}
 
- 		return 0;
 
- 	}
 
- 	LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		if(((HWND)wParam == pT->m_hWnd) && (LOWORD(lParam) == HTCLIENT))
 
- 		{
 
- 			DWORD dwPos = ::GetMessagePos();
 
- 			POINT ptPos = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
 
- 			pT->ScreenToClient(&ptPos);
 
- 			if(IsOverSplitterBar(ptPos.x, ptPos.y))
 
- 				return 1;
 
- 		}
 
- 		bHandled = FALSE;
 
- 		return 0;
 
- 	}
 
- 	LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		int xPos = GET_X_LPARAM(lParam);
 
- 		int yPos = GET_Y_LPARAM(lParam);
 
- 		if(::GetCapture() == pT->m_hWnd)
 
- 		{
 
- 			int xyNewSplitPos = 0;
 
- 			if(m_bVertical)
 
- 				xyNewSplitPos = xPos - m_rcSplitter.left - m_cxyDragOffset;
 
- 			else
 
- 				xyNewSplitPos = yPos - m_rcSplitter.top - m_cxyDragOffset;
 
- 			if(xyNewSplitPos == -1)   // avoid -1, that means default position
 
- 				xyNewSplitPos = -2;
 
- 			if(m_xySplitterPos != xyNewSplitPos)
 
- 			{
 
- 				if(m_bFullDrag)
 
- 				{
 
- 					if(pT->SetSplitterPos(xyNewSplitPos, true))
 
- 						pT->UpdateWindow();
 
- 				}
 
- 				else
 
- 				{
 
- 					DrawGhostBar();
 
- 					pT->SetSplitterPos(xyNewSplitPos, false);
 
- 					DrawGhostBar();
 
- 				}
 
- 			}
 
- 		}
 
- 		else		// not dragging, just set cursor
 
- 		{
 
- 			if(IsOverSplitterBar(xPos, yPos))
 
- 				::SetCursor(m_hCursor);
 
- 			bHandled = FALSE;
 
- 		}
 
- 		return 0;
 
- 	}
 
- 	LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		int xPos = GET_X_LPARAM(lParam);
 
- 		int yPos = GET_Y_LPARAM(lParam);
 
- 		if((::GetCapture() != pT->m_hWnd) && IsOverSplitterBar(xPos, yPos))
 
- 		{
 
- 			m_xySplitterPosNew = m_xySplitterPos;
 
- 			pT->SetCapture();
 
- 			m_hWndFocusSave = pT->SetFocus();
 
- 			::SetCursor(m_hCursor);
 
- 			if(!m_bFullDrag)
 
- 				DrawGhostBar();
 
- 			if(m_bVertical)
 
- 				m_cxyDragOffset = xPos - m_rcSplitter.left - m_xySplitterPos;
 
- 			else
 
- 				m_cxyDragOffset = yPos - m_rcSplitter.top - m_xySplitterPos;
 
- 		}
 
- 		else if((::GetCapture() == pT->m_hWnd) && !IsOverSplitterBar(xPos, yPos))
 
- 		{
 
- 			::ReleaseCapture();
 
- 		}
 
- 		bHandled = FALSE;
 
- 		return 1;
 
- 	}
 
- 	LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		if(::GetCapture() == pT->m_hWnd)
 
- 		{
 
- 			m_xySplitterPosNew = m_xySplitterPos;
 
- 			::ReleaseCapture();
 
- 		}
 
- 		bHandled = FALSE;
 
- 		return 1;
 
- 	}
 
- 	LRESULT OnLButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		pT->SetSplitterPos();   // default
 
- 		return 0;
 
- 	}
 
- 	LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
 
- 	{
 
- 		if(!m_bFullDrag)
 
- 			DrawGhostBar();
 
- 		if((m_xySplitterPosNew != -1) && (!m_bFullDrag || (m_xySplitterPos != m_xySplitterPosNew)))
 
- 		{
 
- 			m_xySplitterPos = m_xySplitterPosNew;
 
- 			m_xySplitterPosNew = -1;
 
- 			UpdateSplitterLayout();
 
- 			T* pT = static_cast<T*>(this);
 
- 			pT->UpdateWindow();
 
- 		}
 
- 		if(m_hWndFocusSave != NULL)
 
- 			::SetFocus(m_hWndFocusSave);
 
- 		return 0;
 
- 	}
 
- 	LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		if(::GetCapture() == pT->m_hWnd)
 
- 		{
 
- 			switch(wParam)
 
- 			{
 
- 			case VK_RETURN:
 
- 				m_xySplitterPosNew = m_xySplitterPos;
 
- 				// FALLTHROUGH
 
- 			case VK_ESCAPE:
 
- 				::ReleaseCapture();
 
- 				break;
 
- 			case VK_LEFT:
 
- 			case VK_RIGHT:
 
- 				if(m_bVertical)
 
- 				{
 
- 					POINT pt = {};
 
- 					::GetCursorPos(&pt);
 
- 					int xyPos = m_xySplitterPos + ((wParam == VK_LEFT) ? -pT->m_cxyStep : pT->m_cxyStep);
 
- 					int cxyMax = m_rcSplitter.right - m_rcSplitter.left;
 
- 					if(xyPos < (m_cxyMin + m_cxyBarEdge))
 
- 						xyPos = m_cxyMin;
 
- 					else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin))
 
- 						xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin;
 
- 					pt.x += xyPos - m_xySplitterPos;
 
- 					::SetCursorPos(pt.x, pt.y);
 
- 				}
 
- 				break;
 
- 			case VK_UP:
 
- 			case VK_DOWN:
 
- 				if(!m_bVertical)
 
- 				{
 
- 					POINT pt = {};
 
- 					::GetCursorPos(&pt);
 
- 					int xyPos = m_xySplitterPos + ((wParam == VK_UP) ? -pT->m_cxyStep : pT->m_cxyStep);
 
- 					int cxyMax = m_rcSplitter.bottom - m_rcSplitter.top;
 
- 					if(xyPos < (m_cxyMin + m_cxyBarEdge))
 
- 						xyPos = m_cxyMin;
 
- 					else if(xyPos > (cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin))
 
- 						xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin;
 
- 					pt.y += xyPos - m_xySplitterPos;
 
- 					::SetCursorPos(pt.x, pt.y);
 
- 				}
 
- 				break;
 
- 			default:
 
- 				break;
 
- 			}
 
- 		}
 
- 		else
 
- 		{
 
- 			bHandled = FALSE;
 
- 		}
 
- 		return 0;
 
- 	}
 
- 	LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM, BOOL& bHandled)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		if(::GetCapture() != pT->m_hWnd)
 
- 		{
 
- 			if(m_nSinglePane == SPLIT_PANE_NONE)
 
- 			{
 
- 				if((m_nDefActivePane == SPLIT_PANE_LEFT) || (m_nDefActivePane == SPLIT_PANE_RIGHT))
 
- 					::SetFocus(m_hWndPane[m_nDefActivePane]);
 
- 			}
 
- 			else
 
- 			{
 
- 				::SetFocus(m_hWndPane[m_nSinglePane]);
 
- 			}
 
- 		}
 
- 		bHandled = FALSE;
 
- 		return 1;
 
- 	}
 
- 	LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		LRESULT lRet = pT->DefWindowProc(uMsg, wParam, lParam);
 
- 		if((lRet == MA_ACTIVATE) || (lRet == MA_ACTIVATEANDEAT))
 
- 		{
 
- 			DWORD dwPos = ::GetMessagePos();
 
- 			POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
 
- 			pT->ScreenToClient(&pt);
 
- 			RECT rcPane = {};
 
- 			for(int nPane = 0; nPane < m_nPanesCount; nPane++)
 
- 			{
 
- 				if(GetSplitterPaneRect(nPane, &rcPane) && (::PtInRect(&rcPane, pt) != FALSE))
 
- 				{
 
- 					m_nDefActivePane = nPane;
 
- 					break;
 
- 				}
 
- 			}
 
- 		}
 
- 		return lRet;
 
- 	}
 
- 	LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
 
- 	{
 
- 		T* pT = static_cast<T*>(this);
 
- 		pT->GetSystemSettings(true);
 
- 		return 0;
 
- 	}
 
- // Implementation - internal helpers
 
- 	void Init()
 
- 	{
 
- 		m_hCursor = ::LoadCursor(NULL, m_bVertical ? IDC_SIZEWE : IDC_SIZENS);
 
- 		T* pT = static_cast<T*>(this);
 
- 		pT->GetSystemSettings(false);
 
- 	}
 
- 	void UpdateSplitterLayout()
 
- 	{
 
- 		if((m_nSinglePane == SPLIT_PANE_NONE) && (m_xySplitterPos == -1))
 
- 			return;
 
- 		T* pT = static_cast<T*>(this);
 
- 		RECT rect = {};
 
- 		if(m_nSinglePane == SPLIT_PANE_NONE)
 
- 		{
 
- 			if(GetSplitterBarRect(&rect))
 
- 				pT->InvalidateRect(&rect);
 
- 			for(int nPane = 0; nPane < m_nPanesCount; nPane++)
 
- 			{
 
- 				if(GetSplitterPaneRect(nPane, &rect))
 
- 				{
 
- 					if(m_hWndPane[nPane] != NULL)
 
- 						::SetWindowPos(m_hWndPane[nPane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
 
- 					else
 
- 						pT->InvalidateRect(&rect);
 
- 				}
 
- 			}
 
- 		}
 
- 		else
 
- 		{
 
- 			if(GetSplitterPaneRect(m_nSinglePane, &rect))
 
- 			{
 
- 				if(m_hWndPane[m_nSinglePane] != NULL)
 
- 					::SetWindowPos(m_hWndPane[m_nSinglePane], NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
 
- 				else
 
- 					pT->InvalidateRect(&rect);
 
- 			}
 
- 		}
 
- 	}
 
- 	bool GetSplitterBarRect(LPRECT lpRect) const
 
- 	{
 
- 		ATLASSERT(lpRect != NULL);
 
- 		if((m_nSinglePane != SPLIT_PANE_NONE) || (m_xySplitterPos == -1))
 
- 			return false;
 
- 		if(m_bVertical)
 
- 		{
 
- 			lpRect->left = m_rcSplitter.left + m_xySplitterPos;
 
- 			lpRect->top = m_rcSplitter.top;
 
- 			lpRect->right = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
 
- 			lpRect->bottom = m_rcSplitter.bottom;
 
- 		}
 
- 		else
 
- 		{
 
- 			lpRect->left = m_rcSplitter.left;
 
- 			lpRect->top = m_rcSplitter.top + m_xySplitterPos;
 
- 			lpRect->right = m_rcSplitter.right;
 
- 			lpRect->bottom = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
 
- 		}
 
- 		return true;
 
- 	}
 
- 	bool GetSplitterPaneRect(int nPane, LPRECT lpRect) const
 
- 	{
 
- 		ATLASSERT((nPane == SPLIT_PANE_LEFT) || (nPane == SPLIT_PANE_RIGHT));
 
- 		ATLASSERT(lpRect != NULL);
 
- 		bool bRet = true;
 
- 		if(m_nSinglePane != SPLIT_PANE_NONE)
 
- 		{
 
- 			if(nPane == m_nSinglePane)
 
- 				*lpRect = m_rcSplitter;
 
- 			else
 
- 				bRet = false;
 
- 		}
 
- 		else if(nPane == SPLIT_PANE_LEFT)
 
- 		{
 
- 			if(m_bVertical)
 
- 			{
 
- 				lpRect->left = m_rcSplitter.left;
 
- 				lpRect->top = m_rcSplitter.top;
 
- 				lpRect->right = m_rcSplitter.left + m_xySplitterPos;
 
- 				lpRect->bottom = m_rcSplitter.bottom;
 
- 			}
 
- 			else
 
- 			{
 
- 				lpRect->left = m_rcSplitter.left;
 
- 				lpRect->top = m_rcSplitter.top;
 
- 				lpRect->right = m_rcSplitter.right;
 
- 				lpRect->bottom = m_rcSplitter.top + m_xySplitterPos;
 
- 			}
 
- 		}
 
- 		else if(nPane == SPLIT_PANE_RIGHT)
 
- 		{
 
- 			if(m_bVertical)
 
- 			{
 
- 				lpRect->left = m_rcSplitter.left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
 
- 				lpRect->top = m_rcSplitter.top;
 
- 				lpRect->right = m_rcSplitter.right;
 
- 				lpRect->bottom = m_rcSplitter.bottom;
 
- 			}
 
- 			else
 
- 			{
 
- 				lpRect->left = m_rcSplitter.left;
 
- 				lpRect->top = m_rcSplitter.top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge;
 
- 				lpRect->right = m_rcSplitter.right;
 
- 				lpRect->bottom = m_rcSplitter.bottom;
 
- 			}
 
- 		}
 
- 		else
 
- 		{
 
- 			bRet = false;
 
- 		}
 
- 		return bRet;
 
- 	}
 
- 	bool IsOverSplitterRect(int x, int y) const
 
- 	{
 
- 		// -1 == don't check
 
- 		return (((x == -1) || ((x >= m_rcSplitter.left) && (x <= m_rcSplitter.right))) &&
 
- 			((y == -1) || ((y >= m_rcSplitter.top) && (y <= m_rcSplitter.bottom))));
 
- 	}
 
- 	bool IsOverSplitterBar(int x, int y) const
 
- 	{
 
- 		if(m_nSinglePane != SPLIT_PANE_NONE)
 
- 			return false;
 
- 		if((m_xySplitterPos == -1) || !IsOverSplitterRect(x, y))
 
- 			return false;
 
- 		int xy = m_bVertical ? x : y;
 
- 		int xyOff = m_bVertical ? m_rcSplitter.left : m_rcSplitter.top;
 
- 		return ((xy >= (xyOff + m_xySplitterPos)) && (xy < (xyOff + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge)));
 
- 	}
 
- 	void DrawGhostBar()
 
- 	{
 
- 		RECT rect = {};
 
- 		if(GetSplitterBarRect(&rect))
 
- 		{
 
- 			// convert client to window coordinates
 
- 			T* pT = static_cast<T*>(this);
 
- 			RECT rcWnd = {};
 
- 			pT->GetWindowRect(&rcWnd);
 
- 			::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcWnd, 2);
 
- 			::OffsetRect(&rect, -rcWnd.left, -rcWnd.top);
 
- 			// invert the brush pattern (looks just like frame window sizing)
 
- 			CBrush brush(CDCHandle::GetHalftoneBrush());
 
- 			if(brush.m_hBrush != NULL)
 
- 			{
 
- 				CWindowDC dc(pT->m_hWnd);
 
- 				CBrushHandle brushOld = dc.SelectBrush(brush);
 
- 				dc.PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
 
- 				dc.SelectBrush(brushOld);
 
- 			}
 
- 		}
 
- 	}
 
- 	void GetSystemSettings(bool bUpdate)
 
- 	{
 
- 		if((m_dwExtendedStyle & SPLIT_FIXEDBARSIZE) == 0)
 
- 		{
 
- 			m_cxySplitBar = ::GetSystemMetrics(m_bVertical ? SM_CXSIZEFRAME : SM_CYSIZEFRAME);
 
- 		}
 
- 		T* pT = static_cast<T*>(this);
 
- 		if((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0)
 
- 		{
 
- 			m_cxyBarEdge = 2 * ::GetSystemMetrics(m_bVertical ? SM_CXEDGE : SM_CYEDGE);
 
- 			m_cxyMin = 0;
 
- 		}
 
- 		else
 
- 		{
 
- 			m_cxyBarEdge = 0;
 
- 			m_cxyMin = 2 * ::GetSystemMetrics(m_bVertical ? SM_CXEDGE : SM_CYEDGE);
 
- 		}
 
- 		::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bFullDrag, 0);
 
- 		if(bUpdate)
 
- 			UpdateSplitterLayout();
 
- 	}
 
- 	bool IsProportional() const
 
- 	{
 
- 		return ((m_dwExtendedStyle & SPLIT_PROPORTIONAL) != 0);
 
- 	}
 
- 	void StoreProportionalPos()
 
- 	{
 
- 		int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
 
- 		if(cxyTotal > 0)
 
- 			m_nProportionalPos = ::MulDiv(m_xySplitterPos, m_nPropMax, cxyTotal);
 
- 		else
 
- 			m_nProportionalPos = 0;
 
- 		ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreProportionalPos - %i\n"), m_nProportionalPos);
 
- 	}
 
- 	void UpdateProportionalPos()
 
- 	{
 
- 		int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
 
- 		if(cxyTotal > 0)
 
- 		{
 
- 			int xyNewPos = ::MulDiv(m_nProportionalPos, cxyTotal, m_nPropMax);
 
- 			m_bUpdateProportionalPos = false;
 
- 			T* pT = static_cast<T*>(this);
 
- 			pT->SetSplitterPos(xyNewPos, false);
 
- 		}
 
- 	}
 
- 	bool IsRightAligned() const
 
- 	{
 
- 		return ((m_dwExtendedStyle & SPLIT_RIGHTALIGNED) != 0);
 
- 	}
 
- 	void StoreRightAlignPos()
 
- 	{
 
- 		int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
 
- 		if(cxyTotal > 0)
 
- 			m_nProportionalPos = cxyTotal - m_xySplitterPos;
 
- 		else
 
- 			m_nProportionalPos = 0;
 
- 		ATLTRACE2(atlTraceUI, 0, _T("CSplitterImpl::StoreRightAlignPos - %i\n"), m_nProportionalPos);
 
- 	}
 
- 	void UpdateRightAlignPos()
 
- 	{
 
- 		int cxyTotal = m_bVertical ? (m_rcSplitter.right - m_rcSplitter.left - m_cxySplitBar - m_cxyBarEdge) : (m_rcSplitter.bottom - m_rcSplitter.top - m_cxySplitBar - m_cxyBarEdge);
 
- 		if(cxyTotal > 0)
 
- 		{
 
- 			m_bUpdateProportionalPos = false;
 
- 			T* pT = static_cast<T*>(this);
 
- 			pT->SetSplitterPos(cxyTotal - m_nProportionalPos, false);
 
- 		}
 
- 	}
 
- 	bool IsInteractive() const
 
- 	{
 
- 		return ((m_dwExtendedStyle & SPLIT_NONINTERACTIVE) == 0);
 
- 	}
 
- };
 
- ///////////////////////////////////////////////////////////////////////////////
 
- // CSplitterWindowImpl - Implements a splitter window
 
- template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
 
- class ATL_NO_VTABLE CSplitterWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CSplitterImpl< T >
 
- {
 
- public:
 
- 	DECLARE_WND_CLASS_EX2(NULL, T, CS_DBLCLKS, COLOR_WINDOW)
 
- 	CSplitterWindowImpl(bool bVertical = true) : CSplitterImpl< T >(bVertical)
 
- 	{ }
 
- 	BOOL SubclassWindow(HWND hWnd)
 
- 	{
 
- 		BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
 
- 		if(bRet != FALSE)
 
- 		{
 
- 			T* pT = static_cast<T*>(this);
 
- 			pT->Init();
 
- 			this->SetSplitterRect();
 
- 		}
 
- 		return bRet;
 
- 	}
 
- 	BEGIN_MSG_MAP(CSplitterWindowImpl)
 
- 		MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
 
- 		MESSAGE_HANDLER(WM_SIZE, OnSize)
 
- 		CHAIN_MSG_MAP(CSplitterImpl< T >)
 
- 		FORWARD_NOTIFICATIONS()
 
- 	END_MSG_MAP()
 
- 	LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
 
- 	{
 
- 		// handled, no background painting needed
 
- 		return 1;
 
- 	}
 
- 	LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
 
- 	{
 
- 		if(wParam != SIZE_MINIMIZED)
 
- 			this->SetSplitterRect();
 
- 		bHandled = FALSE;
 
- 		return 1;
 
- 	}
 
- };
 
- ///////////////////////////////////////////////////////////////////////////////
 
- // CSplitterWindow/CHorSplitterWindow - Implements splitter windows to be used as is
 
- template <bool t_bVertical = true>
 
- class CSplitterWindowT : public CSplitterWindowImpl<CSplitterWindowT<t_bVertical> >
 
- {
 
- public:
 
- 	DECLARE_WND_CLASS_EX2(_T("WTL_SplitterWindow"), CSplitterWindowT<t_bVertical>, CS_DBLCLKS, COLOR_WINDOW)
 
- 	CSplitterWindowT() : CSplitterWindowImpl<CSplitterWindowT<t_bVertical> >(t_bVertical)
 
- 	{ }
 
- };
 
- typedef CSplitterWindowT<true>    CSplitterWindow;
 
- typedef CSplitterWindowT<false>   CHorSplitterWindow;
 
- } // namespace WTL
 
- #endif // __ATLSPLIT_H__
 
 
  |