// XTPScrollBase.cpp : implementation of the CXTPCommandBarScrollBarCtrl class.
//
// This file is a part of the XTREME COMMANDBARS MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "Common/XTPDrawHelpers.h"
#include "Common/XTPWinThemeWrapper.h"
#include "Common/XTPColorManager.h"

#include "XTPCommandBarsDefines.h"
#include "XTPCommandBars.h"
#include "XTPPaintManager.h"
#include "XTPScrollBase.h"
#include "XTPMouseManager.h"


#define IDSYS_SCROLL 23345
#define IDSYS_ANIMATE 23346


//////////////////////////////////////////////////////////////////////////
//  CXTPScrollBase

CXTPScrollBase::SLIDERTICKS::SLIDERTICKS(double* pTicks, int nCount)
{
	this->nCount = nCount;
	this->pTicks = new double[nCount];

	for (int i = 0; i < nCount; i++)
		this->pTicks[i] = pTicks[i];
}

CXTPScrollBase::SLIDERTICKS::~SLIDERTICKS()
{
	SAFE_DELETE(pTicks);
}

CXTPScrollBase::CXTPScrollBase()
{
	ZeroMemory(&m_spi, sizeof(m_spi));
	m_spi.fVert = TRUE;

	m_pSBTrack = NULL;

	m_scrollBarStyle = xtpScrollStyleDefault;

	m_bAnimation = FALSE;
	m_nTimerElapse = 0;

	m_pTicks = NULL;
}

CXTPScrollBase::~CXTPScrollBase()
{
	SAFE_DELETE(m_pTicks);
}

void CXTPScrollBase::SetTicks(double* pTicks, int nCount)
{
	SAFE_DELETE(m_pTicks);

	if (nCount)
	{
		m_pTicks = new SLIDERTICKS(pTicks, nCount);
	}
}

void CXTPScrollBase::CalcScrollBarInfo(LPRECT lprc, SCROLLBARPOSINFO* pSBInfo, SCROLLINFO* pSI)
{
	int cpx;
	DWORD dwRange;
	int denom;
	BOOL fVert = pSBInfo->fVert;

	pSBInfo->rc = *lprc;
	pSBInfo->pxPopup = 0;

	CXTPScrollBarPaintManager* pPaintManager = GetScrollBarPaintManager();

	if (fVert)
	{
		pSBInfo->pxTop = lprc->top;
		pSBInfo->pxBottom = lprc->bottom;
		pSBInfo->pxLeft = lprc->left;
		pSBInfo->pxRight = lprc->right;
		pSBInfo->cpxThumb = pPaintManager->m_cyVScroll;
	}
	else
	{
		pSBInfo->pxTop = lprc->left;
		pSBInfo->pxBottom = lprc->right;
		pSBInfo->pxLeft = lprc->top;
		pSBInfo->pxRight = lprc->bottom;
		pSBInfo->cpxThumb = pPaintManager->m_cxHScroll;
	}

	pSBInfo->pos = pSI->nPos;
	pSBInfo->page = pSI->nPage;
	pSBInfo->posMin = pSI->nMin;
	pSBInfo->posMax = pSI->nMax;

	if (pSBInfo->pos > pSBInfo->posMax)
		pSBInfo->pos = pSBInfo->posMax;
	if (pSBInfo->pos < pSBInfo->posMin)
		pSBInfo->pos = pSBInfo->posMin;

	dwRange = ((DWORD)(pSBInfo->posMax - pSBInfo->posMin)) + 1;

	cpx = min((pSBInfo->pxBottom - pSBInfo->pxTop) / 2, pSBInfo->cpxThumb);

	pSBInfo->pxUpArrow  = pSBInfo->pxTop    + cpx;
	pSBInfo->pxDownArrow = pSBInfo->pxBottom - cpx;

	if ((pSBInfo->page != 0) && (dwRange != 0))
	{
		int i = MulDiv(pSBInfo->pxDownArrow - pSBInfo->pxUpArrow,
			pSBInfo->page, dwRange);

		pSBInfo->cpxThumb = max(pSBInfo->cpxThumb / 2, i);
	}

	if (pPaintManager->m_cThumb > 0) pSBInfo->cpxThumb = pPaintManager->m_cThumb;

	pSBInfo->pxMin = pSBInfo->pxTop + cpx;
	pSBInfo->cpx = pSBInfo->pxBottom - cpx - pSBInfo->cpxThumb - pSBInfo->pxMin;

	denom = dwRange - (pSBInfo->page ? pSBInfo->page : 1);
	if (denom)
		pSBInfo->pxThumbTop = MulDiv(pSBInfo->pos - pSBInfo->posMin,
		pSBInfo->cpx, denom) + pSBInfo->pxMin;
	else
		pSBInfo->pxThumbTop = pSBInfo->pxMin - 1;

	pSBInfo->pxThumbBottom = pSBInfo->pxThumbTop + pSBInfo->cpxThumb;
}

void CXTPScrollBase::SetupScrollInfo()
{
	CRect rc = GetScrollBarRect();

	SCROLLINFO si;
	GetScrollInfo(&si);

	CalcScrollBarInfo(&rc, &m_spi, &si);
}

CRect CXTPScrollBase::GetScrollBarPartRect(int nPart) const
{
	CRect rc(m_spi.rc);

	switch (nPart)
	{
		case XTP_HTSCROLLUP: return m_spi.fVert ? CRect(rc.left, rc.top, rc.right, rc.top + m_spi.pxUpArrow) : CRect(rc.left, rc.top, rc.left + m_spi.pxUpArrow, rc.bottom);
		case XTP_HTSCROLLDOWN: return m_spi.fVert ? CRect(rc.left, rc.bottom - m_spi.pxDownArrow, rc.right, rc.bottom) : CRect(rc.right - m_spi.pxDownArrow, rc.top, rc.right, rc.bottom);
		case XTP_HTSCROLLUPPAGE: return m_spi.fVert ? CRect(rc.left, rc.top + m_spi.pxUpArrow, rc.right, rc.top + m_spi.pxThumbTop) : CRect(rc.left + m_spi.pxUpArrow, rc.top, rc.left + m_spi.pxThumbTop, rc.bottom);
		case XTP_HTSCROLLDOWNPAGE: return m_spi.fVert ? CRect(rc.left, rc.top + m_spi.pxThumbBottom, rc.right, rc.top + m_spi.pxDownArrow) : CRect(rc.left + m_spi.pxThumbBottom, rc.top, rc.left + m_spi.pxDownArrow, rc.bottom);
		case XTP_HTSCROLLTHUMB: return m_spi.fVert ? CRect(rc.left, rc.top + m_spi.pxThumbTop, rc.right, rc.top + m_spi.pxThumbBottom) : CRect(rc.left + m_spi.pxThumbTop, rc.top, rc.left + m_spi.pxThumbBottom, rc.bottom);
	}

	return rc;
}

int CXTPScrollBase::HitTestScrollBar(POINT pt) const
{
	int px = m_spi.fVert ? pt.y : pt.x;

	if (!::PtInRect(&m_spi.rc, pt))
		return HTNOWHERE;

	if (px < m_spi.pxUpArrow)
		return XTP_HTSCROLLUP;

	if (m_spi.pxPopup > 0 && px > m_spi.pxPopup)
		return XTP_HTSCROLLPOPUP;

	if (px >= m_spi.pxDownArrow)
		return XTP_HTSCROLLDOWN;

	if (px < m_spi.pxThumbTop)
		return XTP_HTSCROLLUPPAGE;

	if (px < m_spi.pxThumbBottom)
		return XTP_HTSCROLLTHUMB;

	if (px < m_spi.pxDownArrow)
		return XTP_HTSCROLLDOWNPAGE;

	return HTERROR;
}


//////////////////////////////////////////////////////////////////////////
// Scrolling

void CXTPScrollBase::EndScroll(BOOL fCancel)
{
	SCROLLBARTRACKINFO* pSBTrack = m_pSBTrack;

	if (pSBTrack)
	{
		pSBTrack->cmdSB = 0;
		ReleaseCapture();

		if (pSBTrack->bTrackThumb)
		{
			if (fCancel)
			{
				pSBTrack->posOld = pSBTrack->pSBInfo->pos;
			}

			DoScroll(SB_THUMBPOSITION, pSBTrack->posOld);

			RedrawScrollBar();
		}
		else
		{

			if (pSBTrack->hTimerSB != 0)
			{
				::KillTimer(pSBTrack->hWndTrack, pSBTrack->hTimerSB);
				pSBTrack->hTimerSB = 0;
			}
		}


		DoScroll(SB_ENDSCROLL, 0);
	}
}

AFX_INLINE int SBPosFromPx(CXTPScrollBase::SCROLLBARPOSINFO*  pSBInfo, int px)
{
	if (px < pSBInfo->pxMin)
	{
		return pSBInfo->posMin;
	}

	if (px >= pSBInfo->pxMin + pSBInfo->cpx)
	{
		return (pSBInfo->posMax - (pSBInfo->page ? pSBInfo->page - 1 : 0));
	}

	if (pSBInfo->cpx)
		return (pSBInfo->posMin + MulDiv(pSBInfo->posMax - pSBInfo->posMin -
		(pSBInfo->page ? pSBInfo->page - 1 : 0),
		px - pSBInfo->pxMin, pSBInfo->cpx));
	else
		return (pSBInfo->posMin - 1);
}


void CXTPScrollBase::MoveThumb(int px)
{
	SCROLLBARTRACKINFO* pSBTrack = m_pSBTrack;

	if ((pSBTrack == NULL) || (px == pSBTrack->pxOld))
		return;

	SCROLLBARPOSINFO* pSBInfo = m_pSBTrack->pSBInfo;

pxReCalc:

	pSBTrack->posNew = SBPosFromPx(pSBInfo, px);

	if (pSBTrack->posNew != pSBTrack->posOld)
	{
		DoScroll(SB_THUMBTRACK, pSBTrack->posNew);

		pSBTrack->posOld = pSBTrack->posNew;

		if (px >= pSBInfo->pxMin + pSBInfo->cpx)
		{
			px = pSBInfo->pxMin + pSBInfo->cpx;
			goto pxReCalc;
		}

	}

	pSBInfo->pxThumbTop = px;
	pSBInfo->pxThumbBottom = pSBInfo->pxThumbTop + pSBInfo->cpxThumb;
	pSBTrack->pxOld = px;

	RedrawScrollBar();
}

void CXTPScrollBase::TrackThumb(UINT message, CPoint pt)
{
	SCROLLBARTRACKINFO* pSBTrack = m_pSBTrack;
	if (!pSBTrack)
		return;

	SCROLLBARPOSINFO* pSBInfo = pSBTrack->pSBInfo;

	if (HIBYTE(message) != HIBYTE(WM_MOUSEFIRST))
		return;

	if (pSBInfo == NULL)
		return;

	int px;

	if (!PtInRect(&pSBTrack->rcTrack, pt) && (GetScrollBarPaintManager()->m_cThumb == 0))
		px = pSBInfo->pxStart;
	else
	{
		px = (pSBTrack->pSBInfo->fVert ? pt.y : pt.x) + pSBTrack->dpxThumb;
		if (px < pSBInfo->pxMin)
			px = pSBInfo->pxMin;
		else if (px >= pSBInfo->pxMin + pSBInfo->cpx)
			px = pSBInfo->pxMin + pSBInfo->cpx;
	}

	MoveThumb(px);

	if (message == WM_LBUTTONUP || GetKeyState(VK_LBUTTON) >= 0)
	{
		EndScroll(FALSE);
	}
}

void CXTPScrollBase::TrackBox(UINT message, CPoint point)
{
	SCROLLBARTRACKINFO* pSBTrack = m_pSBTrack;

	if (pSBTrack == NULL)
		return;

	if (message != WM_NULL && HIBYTE(message) != HIBYTE(WM_MOUSEFIRST))
		return;

	if ((pSBTrack->cmdSB == SB_PAGEUP || pSBTrack->cmdSB == SB_PAGEDOWN))
	{
		int* pLength = (int *)&pSBTrack->rcTrack;

		if (pSBTrack->pSBInfo->fVert)
			pLength++;

		if (pSBTrack->cmdSB == SB_PAGEUP)
			pLength[2] = pSBTrack->pSBInfo->pxThumbTop;
		else
			pLength[0] = pSBTrack->pSBInfo->pxThumbBottom;
	}

	BOOL fHit = PtInRect(&pSBTrack->rcTrack, point);

	BOOL fHitChanged = fHit != (BOOL)pSBTrack->fHitOld;

	if (fHitChanged)
	{
		pSBTrack->fHitOld = fHit;
		RedrawScrollBar();
	}

	int cmsTimer = GetDoubleClickTime() / 10;

	switch (message)
	{
	case WM_LBUTTONUP:
		EndScroll(FALSE);
		break;

	case WM_LBUTTONDOWN:
		pSBTrack->hTimerSB = 0;
		cmsTimer = GetDoubleClickTime() * 4 / 5;

		/*
		*** FALL THRU **
		*/

	case WM_MOUSEMOVE:
		if (fHit && fHitChanged)
		{
			pSBTrack->hTimerSB = SetTimer(m_pSBTrack->hWndTrack, IDSYS_SCROLL, m_nTimerElapse = cmsTimer, NULL);

			DoScroll(pSBTrack->cmdSB, 0);
		}
	}
}

void CXTPScrollBase::DoAnimate()
{

}
void CXTPScrollBase::ContScroll()
{
	SCROLLBARTRACKINFO* pSBTrack = m_pSBTrack;
	ASSERT(pSBTrack);

	if (pSBTrack == NULL)
		return;

	CPoint pt;
	GetCursorPos(&pt);

	ScreenToClient(m_pSBTrack->hWndTrack, &pt);

	TrackBox(WM_NULL, pt);

	if (pSBTrack->fHitOld)
	{
		pSBTrack->hTimerSB = SetTimer(m_pSBTrack->hWndTrack, IDSYS_SCROLL, m_nTimerElapse = GetDoubleClickTime() / 10, NULL);

		DoScroll(pSBTrack->cmdSB, 0);
	}
}

void CXTPScrollBase::CalcTrackDragRect(SCROLLBARTRACKINFO* pSBTrack) const
{

	int     cx;
	int     cy;
	LPINT   pwX, pwY;

	pwX = pwY = (LPINT)&pSBTrack->rcTrack;

	if (pSBTrack->pSBInfo->fVert)
	{
		cy = GetSystemMetrics(SM_CYVTHUMB);
		pwY++;
	}
	else
	{
		cy = GetSystemMetrics(SM_CXHTHUMB);
		pwX++;
	}

	cx = (pSBTrack->pSBInfo->pxRight - pSBTrack->pSBInfo->pxLeft) * 8;
	cy *= 2;

	*(pwX + 0) = pSBTrack->pSBInfo->pxLeft - cx;
	*(pwY + 0) = pSBTrack->pSBInfo->pxTop - cy;
	*(pwX + 2) = pSBTrack->pSBInfo->pxRight + cx;
	*(pwY + 2) = pSBTrack->pSBInfo->pxBottom + cy;
}

void CXTPScrollBase::PerformTrackInit(HWND hWnd, CPoint point, SCROLLBARPOSINFO* pSBInfo, BOOL bDirect)
{

	int px = m_spi.fVert ? point.y : point.x;

	SCROLLBARTRACKINFO* pSBTrack = new SCROLLBARTRACKINFO;
	memset(pSBTrack, 0, sizeof(SCROLLBARTRACKINFO));

	pSBTrack->cmdSB = (UINT)-1;
	pSBTrack->bTrackThumb = FALSE;
	pSBTrack->pSBInfo = pSBInfo;
	pSBTrack->hWndTrack = hWnd;

	m_pSBTrack = pSBTrack;

	CXTPMouseManager* pMouseManager = XTPMouseManager();

	RECT rcSB;
	LPINT pwX = (LPINT)&rcSB;
	LPINT pwY = pwX + 1;
	if (!pSBInfo->fVert)
		pwX = pwY--;

	*(pwX + 0) = pSBInfo->pxLeft;
	*(pwY + 0) = pSBInfo->pxTop;
	*(pwX + 2) = pSBInfo->pxRight;
	*(pwY + 2) = pSBInfo->pxBottom;


	if (px < pSBInfo->pxUpArrow)
	{
		pSBInfo->ht = XTP_HTSCROLLUP;
		pSBTrack->cmdSB = SB_LINEUP;
		*(pwY + 2) = pSBInfo->pxUpArrow;

	}
	else if (px >= pSBInfo->pxDownArrow)
	{
		pSBInfo->ht = XTP_HTSCROLLDOWN;
		pSBTrack->cmdSB = SB_LINEDOWN;
		*(pwY + 0) = pSBInfo->pxDownArrow;
	}
	else if (px < pSBInfo->pxThumbTop)
	{
		pSBInfo->ht = XTP_HTSCROLLUPPAGE;
		pSBTrack->cmdSB = SB_PAGEUP;
		*(pwY + 0) = pSBInfo->pxUpArrow;
		*(pwY + 2) = pSBInfo->pxThumbTop;
	}
	else if (px < pSBInfo->pxThumbBottom)
	{
		pSBInfo->ht = XTP_HTSCROLLTHUMB;
DoThumbPos:

		if (pSBInfo->pxDownArrow - pSBInfo->pxUpArrow <= pSBInfo->cpxThumb)
		{
			delete m_pSBTrack;
			m_pSBTrack = NULL;
			return;
		}

		pSBTrack->cmdSB = SB_THUMBPOSITION;
		CalcTrackDragRect(pSBTrack);

		pSBTrack->pxOld = pSBInfo->pxStart = pSBInfo->pxThumbTop;
		pSBTrack->posNew = pSBTrack->posOld = pSBInfo->pos;
		pSBTrack->dpxThumb = pSBInfo->pxStart - px;

		pSBTrack->bTrackThumb = TRUE;

		::SetCapture(hWnd);

		DoScroll(SB_THUMBTRACK, pSBTrack->posOld);

	}
	else if (px < pSBInfo->pxDownArrow)
	{
		pSBInfo->ht = XTP_HTSCROLLDOWNPAGE;
		pSBTrack->cmdSB = SB_PAGEDOWN;
		*(pwY + 0) = pSBInfo->pxThumbBottom;
		*(pwY + 2) = pSBInfo->pxDownArrow;
	}

	if ((bDirect && pSBTrack->cmdSB != SB_LINEUP && pSBTrack->cmdSB != SB_LINEDOWN))
	{
		if (pSBTrack->cmdSB != SB_THUMBPOSITION)
		{
			goto DoThumbPos;
		}
		pSBTrack->dpxThumb = -(pSBInfo->cpxThumb / 2);
	}

	::SetCapture(hWnd);

	if (pSBTrack->cmdSB != SB_THUMBPOSITION)
	{
		CopyRect(&pSBTrack->rcTrack, &rcSB);
	}

	if (!pSBTrack->bTrackThumb)
	{
		TrackBox(WM_LBUTTONDOWN, point);
	}
	else
	{
		TrackThumb(WM_LBUTTONDOWN, point);
		RedrawScrollBar();
	}

	pMouseManager->LockMouseMove();

	while (::GetCapture() == hWnd)
	{
			MSG msg;

			if (!::GetMessage(&msg, NULL, 0, 0))
			{
				AfxPostQuitMessage((int)msg.wParam);
				break;
			}

			if (!IsWindow(hWnd))
				break;

			UINT cmd = msg.message;

			if (cmd == WM_TIMER && msg.wParam == IDSYS_SCROLL)
			{
				ContScroll();
			}
			else if (cmd == WM_TIMER && msg.wParam == IDSYS_ANIMATE)
			{
				DoAnimate();
			}
			else if (cmd >= WM_MOUSEFIRST && cmd <= WM_MOUSELAST)
			{
				CPoint ptScreen = msg.pt;

				ScreenToClient(hWnd, &ptScreen);

				if (!pSBTrack->bTrackThumb)
				{
					TrackBox(cmd, ptScreen);
				}
				else
				{
					TrackThumb(cmd, ptScreen);
				}
			}
			else
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}

	}
	pMouseManager->UnlockMouseMove();

	if (pSBTrack->hTimerSB != 0)
	{
		::KillTimer(hWnd, pSBTrack->hTimerSB);
	}

	delete m_pSBTrack;
	m_pSBTrack = NULL;

	if (IsWindow(hWnd))
	{
		GetCursorPos(&point);
		ScreenToClient(hWnd, &point);
		m_spi.ht = HitTestScrollBar(point);

		RedrawScrollBar();
	}

	while (IsWindow(hWnd) && m_bAnimation)
	{
		MSG msg;

		if (!::GetMessage(&msg, NULL, 0, 0))
		{
			AfxPostQuitMessage((int)msg.wParam);
			break;
		}

		UINT cmd = msg.message;

		if (cmd == WM_TIMER && msg.wParam == IDSYS_ANIMATE)
		{
			DoAnimate();
		}
		else
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

}

XTPScrollBarStyle CXTPScrollBase::GetScrollBarStyle() const
{
	if (m_scrollBarStyle != xtpScrollStyleDefault)
		return m_scrollBarStyle;

	switch (GetScrollBarPaintManager()->GetPaintManager()->BaseTheme())
	{
		case xtpThemeOffice2000:
			return xtpScrollStyleFlat;

		case xtpThemeResource:
		case xtpThemeRibbon:
			return xtpScrollStyleOffice2007Light;
	}

	return xtpScrollStyleSystem;
}


//////////////////////////////////////////////////////////////////////////
// CXTPCommandBarScrollBarCtrl

CXTPCommandBarScrollBarCtrl::CXTPCommandBarScrollBarCtrl()
{
	m_pCommandBars = 0;
}

CXTPCommandBarScrollBarCtrl::~CXTPCommandBarScrollBarCtrl()
{

}

BEGIN_MESSAGE_MAP(CXTPCommandBarScrollBarCtrl, CScrollBar)
	//{{AFX_MSG_MAP(CXTPStatusBar)
	ON_WM_PAINT()
	ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
	ON_WM_ENABLE()
	ON_WM_MOUSEMOVE()
	ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONDBLCLK()
	ON_MESSAGE(SBM_SETSCROLLINFO, OnSetScrollInfo)
	ON_MESSAGE(SBM_GETSCROLLINFO, OnGetScrollInfo)
	ON_WM_SETFOCUS()
	ON_WM_CONTEXTMENU()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


CRect CXTPCommandBarScrollBarCtrl::GetScrollBarRect()
{
	return CXTPClientRect(this);
}

void CXTPCommandBarScrollBarCtrl::GetScrollInfo(SCROLLINFO* psi)
{
	psi->cbSize = sizeof(SCROLLINFO);

	psi->fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
	::GetScrollInfo(m_hWnd, SB_CTL, psi);
}

BOOL CXTPCommandBarScrollBarCtrl::IsScrollBarEnabled() const
{
	return IsWindowEnabled();
}

CWnd* CXTPCommandBarScrollBarCtrl::GetParentWindow() const
{
	return GetParent();
}

CXTPScrollBarPaintManager* CXTPCommandBarScrollBarCtrl::GetScrollBarPaintManager() const
{
	if (m_pCommandBars)
		return (CXTPScrollBarPaintManager*)m_pCommandBars->GetPaintManager()->GetGalleryPaintManager();

	return (CXTPScrollBarPaintManager*)XTPPaintManager()->GetGalleryPaintManager();
}

void CXTPCommandBarScrollBarCtrl::OnPaint()
{
	CPaintDC dcPaint(this); // device context for painting
	CXTPBufferDC dc(dcPaint);

	OnDraw(&dc);
}

LRESULT CXTPCommandBarScrollBarCtrl::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
{
	CDC* pDC = CDC::FromHandle((HDC)wParam);
	if (pDC) OnDraw(pDC);
	return 1;
}

void CXTPCommandBarScrollBarCtrl::OnDraw(CDC* pDC)
{
	DefWindowProc(WM_PAINT, (WPARAM)pDC->GetSafeHdc(), 0);

	m_spi.fVert = GetStyle() & SBS_VERT;

	if (!m_pSBTrack || !m_pSBTrack->bTrackThumb)
		SetupScrollInfo();

	GetScrollBarPaintManager()->DrawScrollBar(pDC, this);
}

void CXTPCommandBarScrollBarCtrl::DoScroll(int cmd, int pos)
{
	GetParent()->SendMessage((UINT)(m_spi.fVert ? WM_VSCROLL : WM_HSCROLL),
		MAKELONG(cmd, pos), (LPARAM)m_hWnd);
}

void CXTPCommandBarScrollBarCtrl::RedrawScrollBar()
{
	if (m_hWnd) Invalidate(FALSE);
}


void CXTPCommandBarScrollBarCtrl::OnEnable(BOOL /*bEnable*/)
{
	RedrawScrollBar();
}

void CXTPCommandBarScrollBarCtrl::OnMouseLeave()
{
	OnMouseMove(0, CPoint(-1, -1));
}

void CXTPCommandBarScrollBarCtrl::OnMouseMove(UINT /*nFlags*/, CPoint point)
{
	int ht = HitTestScrollBar(point);

	if (ht != m_spi.ht)
	{
		m_spi.ht = ht;
		Invalidate(FALSE);

		if (m_spi.ht != HTNOWHERE)
		{
			TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, HOVER_DEFAULT};
			_TrackMouseEvent(&tme);
		}
	}
}


void CXTPCommandBarScrollBarCtrl::OnLButtonDown(UINT /*nFlags*/, CPoint point)
{
	PerformTrackInit(m_hWnd, point, &m_spi, (GetKeyState(VK_SHIFT) < 0) ? TRUE : FALSE);
}

void CXTPCommandBarScrollBarCtrl::OnContextMenu(CWnd* pWnd, CPoint pos)
{
	CScrollBar::OnContextMenu(pWnd, pos);
	Invalidate(FALSE);
}

void CXTPCommandBarScrollBarCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	OnLButtonDown(nFlags, point);
}

LRESULT CXTPCommandBarScrollBarCtrl::OnSetScrollInfo(WPARAM wParam, LPARAM lParam)
{
	LRESULT bResult = DefWindowProc(SBM_SETSCROLLINFO, FALSE, lParam);

	if (wParam)
	{
		Invalidate(FALSE);
		UpdateWindow();
	}

	return bResult;
}

LRESULT CXTPCommandBarScrollBarCtrl::OnGetScrollInfo(WPARAM wParam, LPARAM lParam)
{
	LRESULT bResult = DefWindowProc(SBM_GETSCROLLINFO, wParam, lParam);

	LPSCROLLINFO lpsi = (LPSCROLLINFO)lParam;

	if (lpsi && (lpsi->fMask & SIF_TRACKPOS) && m_pSBTrack)
	{
		lpsi->nTrackPos = m_pSBTrack->posNew;
	}

	return bResult;
}


void CXTPCommandBarScrollBarCtrl::OnSetFocus(CWnd* pOldWnd)
{
	pOldWnd;
}


//////////////////////////////////////////////////////////////////////////
// CXTPScrollBarPaintManager

CXTPScrollBarPaintManager::CXTPScrollBarPaintManager(CXTPPaintManager* pPaintManager)
{
	m_pPaintManager = pPaintManager;

	m_cxHScroll = GetSystemMetrics(SM_CXHSCROLL);
	m_cyHScroll = GetSystemMetrics(SM_CYHSCROLL);
	m_cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
	m_cyVScroll = GetSystemMetrics(SM_CYVSCROLL);

	m_cThumb = 0;

	m_themeScrollBar = new CXTPWinThemeWrapper();
}

CXTPScrollBarPaintManager::~CXTPScrollBarPaintManager()
{
	SAFE_DELETE(m_themeScrollBar);
}


void CXTPScrollBarPaintManager::RefreshMetrics()
{
	m_cxHScroll = GetSystemMetrics(SM_CXHSCROLL);
	m_cyHScroll = GetSystemMetrics(SM_CYHSCROLL);
	m_cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
	m_cyVScroll = GetSystemMetrics(SM_CYVSCROLL);

	m_themeScrollBar->OpenTheme(0, L"SCROLLBAR");
}

void CXTPScrollBarPaintManager::DrawArrowGlyph(CDC* pDC, CRect rcArrow, BOOL bHorz, BOOL bUpArrow, BOOL bEnabled)
{
	int nHeight = min(rcArrow.Width(), rcArrow.Height());
	if (nHeight < 6) return;

	int x = rcArrow.left + ((rcArrow.Width() - nHeight) / 2) + 2;
	int y = rcArrow.top + ((rcArrow.Height() - nHeight) / 2) + 2;
	nHeight -= 4;

	COLORREF clr = bEnabled ? RGB(0, 0, 0) : GetSysColor(COLOR_3DSHADOW);

	HFONT hFont = CreateFont(nHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, SYMBOL_CHARSET, 0, 0, 0, 0, _T("MARLETT"));
	HFONT hOldFont = (HFONT)SelectObject(pDC->GetSafeHdc(), hFont);

	SetTextColor(pDC->GetSafeHdc(), clr);
	pDC->SetBkMode(TRANSPARENT);
	TextOut(pDC->GetSafeHdc(), x, y, bHorz ? (bUpArrow ? _T("3") : _T("4")) : (bUpArrow ? _T("5") : _T("6")), 1);

	SelectObject(pDC->GetSafeHdc(), hOldFont);
	DeleteObject(hFont);
}

void CXTPScrollBarPaintManager::DrawScrollBar(CDC* pDC, CXTPScrollBase* pGallery)
{
	#define GETPARTSTATE(ht, pressed, hot, normal, disabled) \
		(!bEnabled ? disabled : nPressetHt == ht ? pressed : nHotHt == ht ? hot : normal)

	CXTPScrollBase::SCROLLBARTRACKINFO* pSBTrack = pGallery->GetScrollBarTrackInfo();
	CXTPScrollBase::SCROLLBARPOSINFO* pSBInfo = pGallery->GetScrollBarPosInfo();

	BOOL nPressetHt = pSBTrack ? (pSBTrack->bTrackThumb || pSBTrack->fHitOld ? pSBInfo->ht : -1) : -1;
	BOOL nHotHt = pSBTrack ? -1 : pSBInfo->ht;


	int cWidth = (pSBInfo->pxRight - pSBInfo->pxLeft);

	if (cWidth <= 0)
	{
		return;
	}

	BOOL bEnabled = (pSBInfo->posMax - pSBInfo->posMin - pSBInfo->page + 1 > 0) && pGallery->IsScrollBarEnabled();

	int nBtnTrackSize =   pSBInfo->pxThumbBottom - pSBInfo->pxThumbTop;
	int nBtnTrackPos = pSBInfo->pxThumbTop - pSBInfo->pxUpArrow;

	if (!bEnabled || pSBInfo->pxThumbBottom > pSBInfo->pxDownArrow)
		nBtnTrackPos = nBtnTrackSize = 0;
	XTPScrollBarStyle style = pGallery->GetScrollBarStyle();

	if (pSBInfo->fVert)
	{
		CRect rcVScroll(pSBInfo->rc);

		CRect rcArrowUp(rcVScroll.left, rcVScroll.top, rcVScroll.right, pSBInfo->pxUpArrow);
		CRect rcArrowDown(rcVScroll.left, pSBInfo->pxDownArrow, rcVScroll.right, rcVScroll.bottom);
		CRect rcTrack(rcVScroll.left, rcArrowUp.bottom, rcVScroll.right, rcArrowDown.top);

		CRect rcLowerTrack(rcTrack.left, rcTrack.top, rcTrack.right, rcTrack.top + nBtnTrackPos);
		CRect rcBtnTrack(rcTrack.left, rcLowerTrack.bottom, rcTrack.right, rcLowerTrack.bottom + nBtnTrackSize);
		CRect rcUpperTrack(rcTrack.left, rcBtnTrack.bottom, rcTrack.right, rcTrack.bottom);


		if (style == xtpScrollStyleSystem  && m_themeScrollBar->IsAppThemed())
		{
			m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_ARROWBTN, GETPARTSTATE(XTP_HTSCROLLUP, ABS_UPPRESSED, ABS_UPHOT, ABS_UPNORMAL, ABS_UPDISABLED),  rcArrowUp, NULL);
			m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_ARROWBTN, GETPARTSTATE(XTP_HTSCROLLDOWN, ABS_DOWNPRESSED, ABS_DOWNHOT, ABS_DOWNNORMAL, ABS_DOWNDISABLED),  rcArrowDown, NULL);

			if (!rcTrack.IsRectEmpty())
			{
				if (!rcLowerTrack.IsRectEmpty())
					m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_LOWERTRACKVERT, GETPARTSTATE(XTP_HTSCROLLUPPAGE, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED),  rcLowerTrack, NULL);

				if (!rcBtnTrack.IsRectEmpty())
				{
					m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_THUMBBTNVERT, GETPARTSTATE(XTP_HTSCROLLTHUMB, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED),  rcBtnTrack, NULL);
					if (rcBtnTrack.Height() > 13)
						m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_GRIPPERVERT, GETPARTSTATE(XTP_HTSCROLLTHUMB, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED),  rcBtnTrack, NULL);
				}

				if (!rcUpperTrack.IsRectEmpty())
					m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_UPPERTRACKVERT, GETPARTSTATE(XTP_HTSCROLLDOWNPAGE, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED),  rcUpperTrack, NULL);
			}
		}
		else
		{
			if (style == xtpScrollStyleFlat)
			{
				pDC->FillSolidRect(rcArrowUp, GetXtremeColor(COLOR_3DFACE));
				if (bEnabled && nPressetHt == XTP_HTSCROLLUP)
					pDC->Draw3dRect(rcArrowUp,GetXtremeColor(COLOR_3DSHADOW), GetXtremeColor(COLOR_3DHIGHLIGHT));
				else
					pDC->Draw3dRect(rcArrowUp, GetXtremeColor(COLOR_3DHIGHLIGHT), GetXtremeColor(COLOR_3DSHADOW));

				DrawArrowGlyph(pDC, rcArrowUp, FALSE, TRUE, bEnabled);

				pDC->FillSolidRect(rcArrowDown, GetXtremeColor(COLOR_3DFACE));
				if (bEnabled && nPressetHt == XTP_HTSCROLLDOWN)
					pDC->Draw3dRect(rcArrowDown,GetXtremeColor(COLOR_3DSHADOW), GetXtremeColor(COLOR_3DHIGHLIGHT));
				else
					pDC->Draw3dRect(rcArrowDown, GetXtremeColor(COLOR_3DHIGHLIGHT), GetXtremeColor(COLOR_3DSHADOW));
				DrawArrowGlyph(pDC, rcArrowDown, FALSE, FALSE, bEnabled);

			}
			else
			{
				DrawFrameControl(pDC->GetSafeHdc(), &rcArrowUp, DFC_SCROLL, DFCS_SCROLLUP | (!bEnabled ? DFCS_INACTIVE : 0) | (nPressetHt == XTP_HTSCROLLUP ? DFCS_PUSHED : 0));
				DrawFrameControl(pDC->GetSafeHdc(), &rcArrowDown, DFC_SCROLL, DFCS_SCROLLDOWN | (!bEnabled ? DFCS_INACTIVE : 0)  | (nPressetHt == XTP_HTSCROLLDOWN ? DFCS_PUSHED : 0));
			}

			CWnd* pParent = pGallery->GetParentWindow();
			HBRUSH hbrRet = (HBRUSH)DefWindowProc(pParent->GetSafeHwnd(), WM_CTLCOLORSCROLLBAR, (WPARAM)pDC->GetSafeHdc(), (LPARAM)pParent->GetSafeHwnd());

			::FillRect(pDC->GetSafeHdc(), &rcTrack, hbrRet);

			if (nPressetHt == XTP_HTSCROLLUPPAGE)
			{
				::InvertRect(pDC->GetSafeHdc(), &rcLowerTrack);
			}

			if (!rcTrack.IsRectEmpty() && !rcBtnTrack.IsRectEmpty())
			{
				pDC->FillSolidRect(rcBtnTrack, GetXtremeColor(COLOR_3DFACE));

				if (style == xtpScrollStyleFlat)
				{
					pDC->Draw3dRect(rcBtnTrack, GetXtremeColor(COLOR_3DHIGHLIGHT), GetXtremeColor(COLOR_3DSHADOW));
				}
				else
				{
					DrawEdge(pDC->GetSafeHdc(), &rcBtnTrack, EDGE_RAISED, (UINT)(BF_ADJUST | BF_RECT));
				}
			}

			if (nPressetHt == XTP_HTSCROLLDOWNPAGE)
			{
				::InvertRect(pDC->GetSafeHdc(), &rcUpperTrack);
			}
		}
	}
	else
	{
		CRect rcHScroll(pSBInfo->rc);

		CRect rcArrowLeft(rcHScroll.left, rcHScroll.top, pSBInfo->pxUpArrow, rcHScroll.bottom);
		CRect rcArrowRight(pSBInfo->pxDownArrow, rcHScroll.top, rcHScroll.right, rcHScroll.bottom);
		CRect rcTrack(rcArrowLeft.right, rcHScroll.top, rcArrowRight.left, rcHScroll.bottom);

		CRect rcLowerTrack(rcTrack.left, rcTrack.top, rcTrack.left + nBtnTrackPos, rcTrack.bottom);
		CRect rcBtnTrack(rcLowerTrack.right, rcTrack.top, rcLowerTrack.right + nBtnTrackSize, rcTrack.bottom);
		CRect rcUpperTrack(rcBtnTrack.right, rcTrack.top, rcTrack.right, rcTrack.bottom);


		if (style == xtpScrollStyleSystem  && m_themeScrollBar->IsAppThemed())
		{
			m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_ARROWBTN, GETPARTSTATE(XTP_HTSCROLLUP, ABS_LEFTPRESSED, ABS_LEFTHOT, ABS_LEFTNORMAL, ABS_LEFTDISABLED),  rcArrowLeft, NULL);
			m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_ARROWBTN, GETPARTSTATE(XTP_HTSCROLLDOWN, ABS_RIGHTPRESSED, ABS_RIGHTHOT, ABS_RIGHTNORMAL, ABS_RIGHTDISABLED),  rcArrowRight, NULL);

			if (!rcTrack.IsRectEmpty())
			{
				if (!rcLowerTrack.IsRectEmpty())
					m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_LOWERTRACKHORZ, GETPARTSTATE(XTP_HTSCROLLUPPAGE, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED),  rcLowerTrack, NULL);

				if (!rcBtnTrack.IsRectEmpty())
				{
					m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_THUMBBTNHORZ, GETPARTSTATE(XTP_HTSCROLLTHUMB, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED),  rcBtnTrack, NULL);
					if (rcBtnTrack.Width() > 13)
						m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_GRIPPERHORZ, GETPARTSTATE(XTP_HTSCROLLTHUMB, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED),  rcBtnTrack, NULL);
				}

				if (!rcUpperTrack.IsRectEmpty())
					m_themeScrollBar->DrawThemeBackground(pDC->GetSafeHdc(), SBP_UPPERTRACKHORZ, GETPARTSTATE(XTP_HTSCROLLDOWNPAGE, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED),  rcUpperTrack, NULL);
			}
		}
		else
		{
			if (style == xtpScrollStyleFlat)
			{
				pDC->FillSolidRect(rcArrowLeft, GetXtremeColor(COLOR_3DFACE));
				if (bEnabled && nPressetHt == XTP_HTSCROLLUP)
					pDC->Draw3dRect(rcArrowLeft,GetXtremeColor(COLOR_3DSHADOW), GetXtremeColor(COLOR_3DHIGHLIGHT));
				else
					pDC->Draw3dRect(rcArrowLeft, GetXtremeColor(COLOR_3DHIGHLIGHT), GetXtremeColor(COLOR_3DSHADOW));

				DrawArrowGlyph(pDC, rcArrowLeft, TRUE, TRUE, bEnabled);

				pDC->FillSolidRect(rcArrowRight, GetXtremeColor(COLOR_3DFACE));
				if (bEnabled && nPressetHt == XTP_HTSCROLLDOWN)
					pDC->Draw3dRect(rcArrowRight,GetXtremeColor(COLOR_3DSHADOW), GetXtremeColor(COLOR_3DHIGHLIGHT));
				else
					pDC->Draw3dRect(rcArrowRight, GetXtremeColor(COLOR_3DHIGHLIGHT), GetXtremeColor(COLOR_3DSHADOW));
				DrawArrowGlyph(pDC, rcArrowRight, TRUE, FALSE, bEnabled);

			}
			else
			{
				DrawFrameControl(pDC->GetSafeHdc(), &rcArrowLeft, DFC_SCROLL, DFCS_SCROLLLEFT | (!bEnabled ? DFCS_INACTIVE : 0) | (nPressetHt == XTP_HTSCROLLUP ? DFCS_PUSHED : 0));
				DrawFrameControl(pDC->GetSafeHdc(), &rcArrowRight, DFC_SCROLL, DFCS_SCROLLRIGHT | (!bEnabled ? DFCS_INACTIVE : 0)  | (nPressetHt == XTP_HTSCROLLDOWN ? DFCS_PUSHED : 0));
			}

			CWnd* pParent = pGallery->GetParentWindow();
			HBRUSH hbrRet = (HBRUSH)DefWindowProc(pParent->GetSafeHwnd(), WM_CTLCOLORSCROLLBAR, (WPARAM)pDC->GetSafeHdc(), (LPARAM)pParent->GetSafeHwnd());

			::FillRect(pDC->GetSafeHdc(), &rcTrack, hbrRet);

			if (nPressetHt == XTP_HTSCROLLUPPAGE)
			{
				::InvertRect(pDC->GetSafeHdc(), &rcLowerTrack);
			}

			if (!rcTrack.IsRectEmpty() && !rcBtnTrack.IsRectEmpty())
			{
				pDC->FillSolidRect(rcBtnTrack, GetXtremeColor(COLOR_3DFACE));

				if (style == xtpScrollStyleFlat)
				{
					pDC->Draw3dRect(rcBtnTrack, GetXtremeColor(COLOR_3DHIGHLIGHT), GetXtremeColor(COLOR_3DSHADOW));
				}
				else
				{
					DrawEdge(pDC->GetSafeHdc(), &rcBtnTrack, EDGE_RAISED, (UINT)(BF_ADJUST | BF_RECT));
				}
			}

			if (nPressetHt == XTP_HTSCROLLDOWNPAGE)
			{
				::InvertRect(pDC->GetSafeHdc(), &rcUpperTrack);
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////
// CXTPSliderPaintManager

CXTPSliderPaintManager::CXTPSliderPaintManager(CXTPPaintManager* pPaintManager)
	: CXTPScrollBarPaintManager(pPaintManager)
{
}

void CXTPSliderPaintManager::RefreshMetrics()
{
	CXTPScrollBarPaintManager::RefreshMetrics();

	m_cyHScroll = 16;
	m_cxHScroll = 16;

	m_cThumb = 11;
}

void CXTPSliderPaintManager::DrawScrollBar(CDC* pDC, CXTPScrollBase* pGallery)
{
	CXTPScrollBase::SCROLLBARTRACKINFO* pSBTrack = pGallery->GetScrollBarTrackInfo();
	CXTPScrollBase::SCROLLBARPOSINFO* pSBInfo = pGallery->GetScrollBarPosInfo();

	BOOL nPressetHt = pSBTrack ? (pSBTrack->bTrackThumb || pSBTrack->fHitOld ? pSBInfo->ht : -1) : -1;
	BOOL nHotHt = pSBTrack ? -1 : pSBInfo->ht;

	int cWidth = (pSBInfo->pxRight - pSBInfo->pxLeft);

	if (cWidth <= 0)
		return;

	BOOL bEnabled = (pSBInfo->posMax - pSBInfo->posMin - pSBInfo->page + 1 > 0) && pGallery->IsScrollBarEnabled();

	int nBtnTrackSize =   pSBInfo->pxThumbBottom - pSBInfo->pxThumbTop;
	int nBtnTrackPos = pSBInfo->pxThumbTop - pSBInfo->pxUpArrow;

	if (!bEnabled || pSBInfo->pxThumbBottom > pSBInfo->pxDownArrow)
		nBtnTrackPos = nBtnTrackSize = 0;

	COLORREF clrFace = GetXtremeColor(COLOR_3DFACE);
	COLORREF clrShadow = GetXtremeColor(COLOR_3DSHADOW);
	COLORREF clrLight = GetXtremeColor(COLOR_3DHIGHLIGHT);

	if (!pSBInfo->fVert)
	{
		CRect rcHScroll(pSBInfo->rc);

		CRect rcArrowLeft(rcHScroll.left, rcHScroll.top, pSBInfo->pxUpArrow, rcHScroll.bottom);
		CRect rcArrowRight(pSBInfo->pxDownArrow, rcHScroll.top, rcHScroll.right, rcHScroll.bottom);
		CRect rcTrack(rcArrowLeft.right, rcHScroll.top, rcArrowRight.left, rcHScroll.bottom);
		CRect rcBtnTrack(rcTrack.left + nBtnTrackPos, rcTrack.top, rcTrack.left + nBtnTrackPos + nBtnTrackSize, rcTrack.bottom);

		CRect rcTrackDest(CPoint(rcTrack.left, (rcTrack.top + rcTrack.bottom - 2) / 2), CSize(rcTrack.Width(), 2));

		pDC->FillSolidRect(rcTrackDest.left, rcTrackDest.top, rcTrackDest.Width(), 1, clrShadow);
		pDC->FillSolidRect(rcTrackDest.left, rcTrackDest.top + 1, rcTrackDest.Width(), 1, clrLight);

		CXTPScrollBase::SLIDERTICKS* pTicks = pGallery->GetTicks();
		if (!pTicks || (pSBInfo->posMax <= pSBInfo->posMin))
		{
			CRect rcTrackTickDest(CPoint((rcTrackDest.left + rcTrackDest.right - 2) / 2,
				(rcTrackDest.top + rcTrackDest.bottom - 8) / 2), CSize(2, 8));

			pDC->FillSolidRect(rcTrackTickDest.left, rcTrackTickDest.top, 1, 4, clrShadow);
			pDC->FillSolidRect(rcTrackTickDest.left, rcTrackTickDest.top + 5, 1, 2, clrShadow);
			pDC->FillSolidRect(rcTrackTickDest.left + 1, rcTrackTickDest.top + 1, 1, 7, clrLight);
		}
		else
		{
			rcTrackDest.DeflateRect(6, 0);

			for (int i = 0; i < pTicks->nCount; i++)
			{
				double dTick = pTicks->pTicks[i];
				double dPos = (dTick - pSBInfo->posMin) * rcTrackDest.Width() / (pSBInfo->posMax - pSBInfo->posMin);

				if (dPos >= 0 && dPos <= rcTrackDest.Width())
				{
					CRect rcTrackTickDest(CPoint(rcTrackDest.left + (int)dPos - 1,
						(rcTrackDest.top + rcTrackDest.bottom - 8) / 2), CSize(2, 8));

					pDC->FillSolidRect(rcTrackTickDest.left, rcTrackTickDest.top, 1, 4, clrShadow);
					pDC->FillSolidRect(rcTrackTickDest.left, rcTrackTickDest.top + 5, 1, 2, clrShadow);
					pDC->FillSolidRect(rcTrackTickDest.left + 1, rcTrackTickDest.top + 1, 1, 7, clrLight);
				}
			}
		}

		m_pPaintManager->AlphaEllipse(pDC, rcArrowLeft, clrShadow, nHotHt == XTP_HTSCROLLUP ? clrLight : clrFace);
		if (nPressetHt != XTP_HTSCROLLUP)
		{
			rcArrowLeft.DeflateRect(1, 1);
			m_pPaintManager->AlphaEllipse(pDC, rcArrowLeft, clrLight, nHotHt == XTP_HTSCROLLUP ? clrLight : clrFace);
		}
		CPoint ptCenter = rcArrowLeft.CenterPoint();
		pDC->FillSolidRect(ptCenter.x - 4, ptCenter.y - 1, 8, 2, 0);

		m_pPaintManager->AlphaEllipse(pDC, rcArrowRight, clrShadow, nHotHt == XTP_HTSCROLLDOWN ? clrLight : clrFace);
		if (nPressetHt != XTP_HTSCROLLDOWN)
		{
			rcArrowRight.DeflateRect(1, 1);
			m_pPaintManager->AlphaEllipse(pDC, rcArrowRight, clrLight, nHotHt == XTP_HTSCROLLDOWN ? clrLight : clrFace);
		}
		ptCenter = rcArrowRight.CenterPoint();
		pDC->FillSolidRect(ptCenter.x - 4, ptCenter.y - 1, 8, 2, 0);
		pDC->FillSolidRect(ptCenter.x - 1, ptCenter.y - 4, 2, 8, 0);

		if (bEnabled)
		{
			CRect rc(CPoint((rcBtnTrack.left + rcBtnTrack.right - 8) / 2,
				(rcBtnTrack.top + rcBtnTrack.bottom - 13) / 2), CSize(8, 13));

			POINT pts[] = {rc.left, rc.top, rc.right, rc.top,
				rc.right,  rc.bottom - 4, rc.left + 4, rc.bottom, rc.left, rc.bottom - 4, rc.left, rc.top};

			CXTPPenDC pen (*pDC, nHotHt == XTP_HTSCROLLTHUMB ? clrLight : clrFace);
			CXTPBrushDC brush (*pDC, nHotHt == XTP_HTSCROLLTHUMB ? clrLight : clrFace);

			pDC->Polygon(pts, sizeof(pts) / sizeof(POINT));

			pen.Color(clrShadow);
			pDC->Polyline(pts, sizeof(pts) / sizeof(POINT));

			if (nPressetHt != XTP_HTSCROLLTHUMB)
			{
				POINT pts2[] = {rc.left + 1, rc.top + 1, rc.right - 1, rc.top + 1,
					rc.right - 1,  rc.bottom - 4, rc.left + 4, rc.bottom - 1, rc.left + 1, rc.bottom - 4, rc.left + 1, rc.top + 1};

				pen.Color(clrLight);
				pDC->Polyline(pts2, sizeof(pts2) / sizeof(POINT));
			}
		}
	}
}