//---------------------------------------------------------------------------

#pragma hdrstop

#include "SkinTrackBar.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#define trHorizontal	1               //横向滑块
#define trVertical		0               //纵向滑块

#define SLIDER_MAX_H    25              //滑块长度
#define SLIDER_MIN_H    10
#define SLIDER_W		10				//滑块宽度

#define PANEL_MIN_W    30               //Panel最小宽度

#define CHANNEL_LEFT	5
#define CHANNEL_W		2				//滑槽宽度

static const COLORREF
			CLR_BACK_ENABLE 				=  RGB(22,33,44), //d5dde8
			CLR_BACK_DISABLE 				=  RGB(112,130,154), //d5dde8
			CLR_SLIDER_DOWN 				=  RGB(77,88,99), //d5dde8
			CLR_SLIDER_HOVER 				=  RGB(55,66,77), //d5dde8
			CLR_SLIDER_NORMAL 				=  RGB(44,55,77); //d5dde8

static inline void ValidCtrCheck(TSkinTrackBar *)
{
	new TSkinTrackBar(NULL);
}

namespace Skintrackbar
{
	void __fastcall PACKAGE Register()
	{
		TComponentClass classes[1] = {__classid(TSkinTrackBar)};
		RegisterComponents(L"Samples", classes, 0);
	}
}

__fastcall TSkinTrackBar::TSkinTrackBar(System::Classes::TComponent* AOwner)
	: TPanel(AOwner)
{
	bDown = false;
	bMouse = false;
	FEnabled = true;

	FOrientation = 1;         //默认横向滑块
	FMax = 100;
	FMin = 0;
	FPosition = 0;
	FPageSize = 1;
	Hint = IntToStr(FPosition);

	ParentBackground = true;

	Slider = new TPaintBox(this);
	Slider->Parent = this;
    Slider->ParentShowHint = false;
    Slider->ShowHint = false;

	Slider->OnMouseEnter = CMMouseEnter;
	Slider->OnMouseLeave = CMMouseLeave;
	Slider->OnMouseDown = CMMouseDown;
	Slider->OnPaint = SliderPaint;

	ParentColor = true;
}
//-----------------------------------------------------------------------------
__fastcall TSkinTrackBar::~TSkinTrackBar()
{
	delete Slider;
	Slider = NULL;
}

void __fastcall TSkinTrackBar::SetMax(int Value)
{
	if(Value <= FMin)
    {
//        if(ComponentState.Contains(csDesigning))
//        {
//			MessageBox(Handle, "Max：必须大于Min!!!", "错误", MB_OK | MB_ICONERROR);
//		}
	}
    else
    {
        if(FMax != Value)
		{
			FMax = Value;

			if(FPosition > FMax){
				FPosition = FMax;
				if(FOnChange)
					FOnChange(this);
			}

			if( FOrientation ){
				Slider->Left = CHANNEL_LEFT+(double)(FPosition-FMin)*(Width-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin);
			}
			else{
				Slider->Top = Height-CHANNEL_LEFT-(double)(FPosition-FMin)*(Height-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin)-SLIDER_W;
			}
        }
	}
}

void __fastcall TSkinTrackBar::SetMin(int Value)
{
	if(Value >= FMax)
	{
//		if(ComponentState.Contains(csDesigning))
//		{
//			MessageBox(Handle, "Min：必须小于Max!!!", "错误", MB_OK | MB_ICONERROR);
//		}
	}
	else
	{
		if(FMin != Value)
		{
			FMin = Value;

			if(FPosition < FMin){
				FPosition = FMin;
				if(FOnChange)
					FOnChange(this);
			}

			if( FOrientation ){
				Slider->Left = CHANNEL_LEFT+(double)(FPosition-FMin)*(Width-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin);
			}
			else{
				Slider->Top = Height-CHANNEL_LEFT-(double)(FPosition-FMin)*(Height-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin)-SLIDER_W;
			}
		}
	}
}

void __fastcall TSkinTrackBar::SetPosition(int iPosition)
{
	if(iPosition>FMax)
		iPosition = FMax;
	if(iPosition<FMin)
		iPosition = FMin;

	if(FPosition!=iPosition){

		FPosition = iPosition;
		Hint = IntToStr(FPosition);

		if( FOrientation ){
			Slider->Left = CHANNEL_LEFT+(double)(FPosition-FMin)*(Width-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin);
		}
		else{
			Slider->Top = Height-CHANNEL_LEFT-(double)(FPosition-FMin)*(Height-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin)-SLIDER_W;
		}

		if(FOnChange)
			FOnChange(this);

		Invalidate();
//		Slider->Invalidate();

	}
}

void __fastcall TSkinTrackBar::SetOrientation(bool bOrientation)
{
    if(FOrientation != bOrientation)
    {
		FOrientation = bOrientation;

		TWMSize msg;
		WMSize(msg);

		Invalidate();
//		Slider->Invalidate();
	}
}

void __fastcall TSkinTrackBar::SetEnabled(bool bEnabled)
{
	if( FEnabled!=bEnabled ){
		FEnabled = bEnabled;
		Invalidate();
	}
}

void __fastcall TSkinTrackBar::CMMouseEnter(System::TObject* Sender)
{
	if( FEnabled ){
		bMouse = true;
		Slider->Invalidate();
	}
}


void __fastcall TSkinTrackBar::CMMouseLeave(System::TObject* Sender)
{
	if( FEnabled ){
		bMouse = false;
		Slider->Invalidate();
	}
}

void __fastcall TSkinTrackBar::CMMouseDown(System::TObject* Sender, System::Uitypes::TMouseButton Button,
														System::Classes::TShiftState Shift, int X, int Y)
{
	if( FEnabled && Button==mbLeft ){
		bDown = true;
		MouseCapture = true;
		Slider->Invalidate();
		SetFocus();
	}
}

void __fastcall TSkinTrackBar::WMMouseMove(TWMMouse &Message)
{
	if( FEnabled && bDown ){
		if( FOrientation ){     // trHorizontal	1               //横向滑块
			DrawH(Message);
		}
		else{
			DrawV(Message);
		}
	}

	TPanel::Dispatch(&Message);
}

void __fastcall TSkinTrackBar::WMLButtonDown(TWMLButtonDown &Message)
{
	if( FEnabled ){
		if( FOrientation && Message.YPos>Slider->Top
							&& Message.YPos<Slider->Top+Slider->Height
							&& Message.XPos>0 && Message.XPos<Width){
			//横向
			DrawH(Message);
			bDown = true;
			MouseCapture = true;
		}
		else if( !FOrientation && Message.XPos>Slider->Left
							&& Message.XPos<Slider->Left + Slider->Width
							&& Message.YPos>0 && Message.YPos<Height){
			//纵向
			DrawV(Message);
			bDown = true;
			MouseCapture = true;
		}

		SetFocus();
	}

	TPanel::Dispatch(&Message);
}

void __fastcall TSkinTrackBar::WMLButtonUp(TWMLButtonUp &Message)
{
	if( FEnabled ){
		bDown = false;
		bMouse = false;
		MouseCapture = false;

		Slider->Invalidate();
	}

	TPanel::Dispatch(&Message);
}

void __fastcall TSkinTrackBar::WMMouseWheel(TWMMouseWheel &Message)
{
	if( FEnabled ){
		int iPos = FPosition;
		if( Message.WheelDelta>0 ){
			iPos += FPageSize;
			if( iPos>FMax )
				iPos = FMax;
		}
		else{
			iPos -= FPageSize;
			if( iPos<FMin )
				iPos = FMin;
		}

		Position = iPos;
	}
}

void __fastcall TSkinTrackBar::WMEraseBkgnd(TWMEraseBkgnd &Message)
{
	TPanel::Dispatch(&Message);

	TRect Channel;

	if( Orientation )
		Channel.init( CHANNEL_LEFT,
					Height/2-CHANNEL_W,
					Width-CHANNEL_LEFT,
					Height/2+CHANNEL_W);
	else
		Channel.init(
					Width/2-CHANNEL_W,
					CHANNEL_LEFT,
					Width/2+CHANNEL_W,
					Height-CHANNEL_LEFT
					);

	TCanvas* tempCanvas = new TCanvas;
	tempCanvas->Handle = Message.DC;

	if( Enabled ){
		tempCanvas->Brush->Color = CLR_BACK_ENABLE;
		tempCanvas->FillRect(Channel);
	}
	else{
		tempCanvas->Brush->Color = CLR_BACK_DISABLE;
		tempCanvas->FillRect(Channel);
	}

	delete	tempCanvas;
}

void __fastcall TSkinTrackBar::SliderPaint(System::TObject* Sender)
{
	TRect rect = Slider->ClientRect;

	if ( !FEnabled ) {
		Slider->Canvas->Brush->Color = CLR_BACK_DISABLE;
		Slider->Canvas->FillRect(rect);

//		TRect rct(rect);
//		Frame3D( Slider->Canvas, rect, clBlack,clGray,1 );
//		rect = rct;
	}
	else if(bDown){//鼠标按下
		Slider->Canvas->Brush->Color = CLR_SLIDER_DOWN;
		Slider->Canvas->FillRect(rect);

//		TRect rct(rect);
		Frame3D( Slider->Canvas, rect, clBlack,clGray,1 );
//		rect = rct;
	}
	else if(bMouse){//鼠标移动到滑块上
		Slider->Canvas->Brush->Color = CLR_SLIDER_HOVER;
		Slider->Canvas->FillRect(rect);

//		TRect rct(rect);
		Frame3D( Slider->Canvas, rect, clGray,clBlack, 1 );
//		rect = rct;
	}
	else{            //平常
		Slider->Canvas->Brush->Color = CLR_SLIDER_NORMAL;
		Slider->Canvas->FillRect(rect);

//		TRect rct(rect);
		Frame3D( Slider->Canvas, rect, clGray,clBlack, 1 );
//		rect = rct;
	}
}

void __fastcall TSkinTrackBar::DrawH(TWMMouse &Message)    // 横向
{
	int oldPosition = FPosition;

	if(Message.XPos<CHANNEL_LEFT+SLIDER_W/2){
		if(Slider->Left==CHANNEL_LEFT)
			return;

		Slider->Left = CHANNEL_LEFT;

		FPosition = FMin;
	}
	else if(Message.XPos>Width-CHANNEL_LEFT-SLIDER_W/2){
		if(Slider->Left==Width-CHANNEL_LEFT - SLIDER_W)
			return;

		Slider->Left = Width-CHANNEL_LEFT - SLIDER_W;

		FPosition = FMax;
	}
	else{
		FPosition = FMin+(double)(Message.XPos - CHANNEL_LEFT - SLIDER_W/2)/(Width-2*CHANNEL_LEFT-SLIDER_W)*(FMax-FMin) +0.5;

		Slider->Left = CHANNEL_LEFT+(double)(FPosition-FMin)*(Width-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin);
	}

	Hint = IntToStr(FPosition);
	if( oldPosition!=FPosition && FOnChange )
		FOnChange(this);
}

void __fastcall TSkinTrackBar::DrawV(TWMMouse &Message)
{
	int oldPosition = FPosition;

	if(Message.YPos<CHANNEL_LEFT+SLIDER_W/2){
		if(Slider->Top==CHANNEL_LEFT)
			return;

		Slider->Top = CHANNEL_LEFT;

		FPosition = FMax;

	}
	else if(Message.YPos>Height-CHANNEL_LEFT-SLIDER_W/2){
		if(Slider->Top==Height-CHANNEL_LEFT - SLIDER_W)
			return;

		Slider->Top = Height-CHANNEL_LEFT - SLIDER_W;

		FPosition = FMin;
	}
	else{
		FPosition = FMax-(double)(Message.YPos - CHANNEL_LEFT - SLIDER_W/2)/(Height-2*CHANNEL_LEFT-SLIDER_W)*(FMax-FMin);

		Slider->Top = Height-CHANNEL_LEFT-(double)(FPosition-FMin)*(Height-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin)-SLIDER_W;
	}

	if( oldPosition!=FPosition && FOnChange )
		FOnChange(this);
}

void __fastcall TSkinTrackBar::WMSize(TWMSize &Message)
{
	if(FOrientation){
        //确定横向滑块区域
		if( Width<PANEL_MIN_W )
			Width = PANEL_MIN_W;       //20

		if( Height<SLIDER_MIN_H )
			Height = SLIDER_MIN_H;

		if( Height>=SLIDER_MAX_H ){
			Slider->Left = CHANNEL_LEFT+(double)(FPosition-FMin)* (Width-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin);
			Slider->Top = Height/2-SLIDER_MAX_H/2;
			Slider->Width = SLIDER_W;
			Slider->Height = SLIDER_MAX_H;
		}
		else{
			Slider->Left = CHANNEL_LEFT+(double)(FPosition-FMin)*(Width-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin);
            Slider->Top = 1;
			Slider->Width = SLIDER_W;
			Slider->Height = Height-2;
		}
	}
	else
	{
		//确定纵向滑块区域
		if( Height<PANEL_MIN_W )
			Height = PANEL_MIN_W;       //20

		if( Width<SLIDER_MIN_H )
			Width = SLIDER_MIN_H;

		if( Width>=SLIDER_MAX_H ){
			Slider->Left = Width/2-SLIDER_MAX_H/2;
			Slider->Top = Height-CHANNEL_LEFT-(double)(FPosition-FMin)*(Height-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin)-SLIDER_W;
			Slider->Width = SLIDER_MAX_H;
			Slider->Height = SLIDER_W;
		}
		else{
			Slider->Left = 1;
			Slider->Top = Height-CHANNEL_LEFT-(double)(FPosition-FMin)*(Height-2*CHANNEL_LEFT-SLIDER_W)/(FMax-FMin)-SLIDER_W;
			Slider->Width = Width-2;
			Slider->Height = SLIDER_W;
		}
	}
}
