//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "BtnPanelUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
VCTBtnPanel::iterator vc_pFindVCTBtnPanel;
//---------------------------------------------------------------------------
__fastcall TBtnPanel::TBtnPanel(TWinControl *pTWnCtl)
: TComponent(pTWnCtl)
{
	m_pTWnCtl = pTWnCtl;

	m_pAppEvents = new TApplicationEvents(this);
	m_pAppEvents->OnMessage = OnAppEvents;


	m_bPalEn  = false;
	m_bPalLD  = false;
	m_bPalRD  = false;

	m_bBtnEn = m_bBtnLD = m_bBtnRD = false;
	m_pParentBtn     = NULL;

	FLeft = FTop = FWidth = FHeight = 0;
	FEnabled		  = true;
	FDown			  = false;
	FStateEnter       = true;
	FStateCount       = 3;
	FBtnCurState      = Bs_NORMAL;
	FTransparent      = false;
	FTransparentValue = 255;

	m_BtnCurStateBac = Bs_NORMAL;
}
//---------------------------------------------------------------------------
__fastcall TBtnPanel::~TBtnPanel()
{
  	SAFE_DELETE(m_pAppEvents)
}
//---------------------------------------------------------------------------
bool __fastcall TBtnPanel::IsPtInSubtn(int XPos, int YPos)
{
	for(vc_pFindVCTBtnPanel =m_VCSubtn.begin();
		vc_pFindVCTBtnPanel!=m_VCSubtn.end();
		vc_pFindVCTBtnPanel++ )
	{
		TRect TRectTmpSubView
		= TRect((*vc_pFindVCTBtnPanel)->Left, (*vc_pFindVCTBtnPanel)->Top,
				(*vc_pFindVCTBtnPanel)->Left+(*vc_pFindVCTBtnPanel)->Width,
				(*vc_pFindVCTBtnPanel)->Top+(*vc_pFindVCTBtnPanel)->Height);
		if( PtInRect(TRectTmpSubView, TPoint(XPos, YPos) ) ) {
			return true;
		}
	}

	return false;
}
//---------------------------------------------------------------------------
bool __fastcall TBtnPanel::IsBtnHandleAppEvent(unsigned int message, int XPos, int YPos)
{
	if( IsPtInSubtn(XPos, YPos) ) {

		if( Bs_NORMAL==FBtnCurState )
			return false;
	}

	return true;
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::OnAppEvents(tagMSG &Msg, bool &Handled)
{
	// -----
	if(  false    == FEnabled ||
		 false    == m_pTWnCtl->Enabled ||
		(false    == m_bPalEn &&
		 Msg.hwnd != m_pTWnCtl->Handle) )
		 return;

	if( WM_LBUTTONDOWN   == Msg.message ||
		WM_LBUTTONUP     == Msg.message ||
		WM_LBUTTONDBLCLK == Msg.message ||
		WM_RBUTTONDOWN   == Msg.message ||
		WM_RBUTTONUP     == Msg.message ||
		WM_MOUSEMOVE     == Msg.message )
	{

	}else return;

	// -----
	TRect rtSelf = TRect(Left, Top, Left+Width, Top+Height);
	TPoint pt = m_pTWnCtl->ScreenToClient(TPoint(Msg.pt.x, Msg.pt.y));

	TWMMouse Message;
	Message.Msg  = Msg.message;
	Message.XPos = pt.x;
	Message.YPos = pt.y;

	if( false==IsBtnHandleAppEvent(Message.Msg, Message.XPos, Message.YPos) ) return;

	// -----
	MsState MsStatus = Ms_NONE;
	//刚离开区域
	if( m_bPalEn && !PtInRect( rtSelf, pt ) ) {

		if( WM_MOUSEMOVE != Msg.message ) {

			return;

		}else if( WM_MOUSEMOVE==Msg.message ) {

			m_bPalEn = false;
			MsStatus = Ms_LEAVE;
			BtnHandleAppEvent(MsStatus, Message.XPos, Message.YPos);

			return;
		}
	//已经离开了区域
	} else if(!m_bPalEn && !PtInRect( rtSelf, pt ) ) {

		if( m_bPalLD ) { //处理拖动事件
			MsStatus = Ms_DRAG;
			BtnHandleAppEvent(MsStatus, Message.XPos, Message.YPos);
		}

		//除了 WM_LBUTTONUP WM_RBUTTONUP 都不再处理
		if((WM_LBUTTONUP != Msg.message && WM_RBUTTONUP != Msg.message) ||
		   (false==m_bPalLD && WM_LBUTTONUP == Msg.message ) || //没有按下键 不再处理
		   (false==m_bPalRD && WM_RBUTTONUP == Msg.message ) )
			return;
	}

	// -----
	switch( Msg.message )
	{
		case WM_LBUTTONDOWN:
		{
			MsStatus = Ms_LDOWN;
			m_bPalLD = true;

		} break;
		case WM_LBUTTONUP:
		{
			if( m_bPalLD ) {
				MsStatus = Ms_LUP;
				m_bPalLD = false;
			}

		} break;
		case WM_LBUTTONDBLCLK:
		{
			MsStatus = Ms_LLDOWN;

		} break;
		case WM_RBUTTONDOWN:
		{
			MsStatus = Ms_RDOWN;
			m_bPalRD = true;

		} break;
		case WM_RBUTTONUP:
		{
			if(m_bPalRD) {

				MsStatus = Ms_RUP;
				m_bPalRD = false;
			}

		} break;
		case WM_MOUSEMOVE:
		{
			if( m_bPalEn )
			{
				if(m_bPalLD)
					MsStatus = Ms_DRAG;
				else
					MsStatus = Ms_MOVE;

			}else            MsStatus = Ms_ENTER;

			m_bPalEn = true;

		} break;
    	default: break;
	}

	if(Ms_NONE!=MsStatus ) BtnHandleAppEvent(MsStatus, Message.XPos, Message.YPos);
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::BtnHandleAppEvent(MsState MsSrcTmp, int XPos, int YPos)
{
	MsState  MsTmp = Ms_NONE;
	BtnState BsTmp = Bs_NONE;

	switch( MsSrcTmp )
	{
		case Ms_LDOWN:
		{
			m_bBtnLD     = true;
			BsTmp        = Bs_DOWN;
			FBtnCurState = BsTmp;

			MsTmp        = Ms_LDOWN;

		} break;
		case Ms_LLDOWN:
		{
			MsTmp        = Ms_LLDOWN;

		} break;
		case Ms_LUP:
		{
			m_bBtnLD     = false;
			if( PtInRect( TRect(Left, Top, Left+Width, Top+Height),
						  TPoint(XPos, YPos) ) )
				BsTmp    = Bs_ENTER;
			else
				BsTmp    = Bs_NORMAL;
			FBtnCurState = BsTmp;

			MsTmp        = Ms_LUP;

		} break;
		case Ms_RDOWN:
		{
			MsTmp = Ms_RDOWN;

		} break;
		case Ms_RUP:
		{
			MsTmp = Ms_RUP;

		} break;
		case Ms_ENTER:
		{
			if( true!=m_bBtnLD ) {

				m_bBtnEn     = true;
				BsTmp        = Bs_ENTER;
				FBtnCurState = BsTmp;

				MsTmp        = Ms_ENTER;
			}
		} break;
		case Ms_LEAVE:
		{
			if( true!=m_bBtnLD ) {

				m_bBtnEn     = false;
				BsTmp        = Bs_NORMAL;
				FBtnCurState = BsTmp;

				MsTmp        = Ms_LEAVE;
			}

		} break;
		case Ms_MOVE:
		{
			if( m_bBtnEn ) {

				bool bIsPtInSubtn = IsPtInSubtn(XPos, YPos);
				if( bIsPtInSubtn ) {

					m_bBtnEn     = false;
					BsTmp        = Bs_NORMAL;
					FBtnCurState = BsTmp;

					MsTmp        = Ms_LEAVE;

				}else {

					MsTmp = Ms_MOVE;
				}

			}else{

				m_bBtnEn     = true;
				BsTmp        = Bs_ENTER;
				FBtnCurState = BsTmp;

				MsTmp        = Ms_ENTER;
			}

		} break;
		case Ms_DRAG:
		{
			MsTmp = Ms_DRAG;

		} break;
		default: break;
	}

	if( Ms_NONE != MsTmp ) BtnMsEvent(MsTmp, XPos, YPos);
	if( Bs_NONE != BsTmp ) BtnDrEvent(FBtnCurState, XPos, YPos);
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::BtnHandleState()
{
	BtnState BtnStateTmp = this->FBtnCurState;
	if( false==m_pTWnCtl->Enabled ||
		false==FEnabled ) {

		BtnStateTmp = Bs_DISABLE;

	}else {

		if( false==FStateEnter && Bs_ENTER==this->FBtnCurState )
			BtnStateTmp = Bs_NORMAL;

		if( FDown ) BtnStateTmp = Bs_DOWN;

		if( FStateCount<=BtnStateTmp ) BtnStateTmp = FStateCount-1;
	}

	m_BtnCurStateBac = FBtnCurState = BtnStateTmp;
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::BtnDrEvent(BtnState BsTmp, int XPos, int YPos)
{
	if( Bs_DOWN   == BsTmp ||
		Bs_ENTER  == BsTmp ||
		Bs_NORMAL == BsTmp )
	{
		int BtnCurStateBac = m_BtnCurStateBac;
		BtnHandleState();
		if( BtnCurStateBac==m_BtnCurStateBac ) return;

		Paint();
	}
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::BtnMsEvent(MsState MsTmp, int XPos, int YPos)
{
	if( Ms_LDOWN  == MsTmp ||
		Ms_LUP    == MsTmp ||
		Ms_LLDOWN == MsTmp ||
		Ms_RDOWN  == MsTmp ||
		Ms_RUP    == MsTmp ||
		Ms_ENTER  == MsTmp ||
		Ms_LEAVE  == MsTmp ||
		Ms_MOVE   == MsTmp ||
		Ms_DRAG   == MsTmp )
	{
		if( OnPanelMsEvent ) OnPanelMsEvent(MsTmp, XPos, YPos);
	}
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::AddSubPanel(TBtnPanel *pTBtnPanel)
{
	m_VCSubtn.push_back(pTBtnPanel);
	pTBtnPanel->m_pParentBtn = this;
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::SetBounds(int nLeft, int nTop, int nWidth, int nHeight)
{
	FLeft   = nLeft;
	FTop    = nTop;
	FWidth  = nWidth;
	FHeight = nHeight;
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::PaintParent(TCanvas *CanvasDrawCus)
{
	if( this->m_pParentBtn ) {
		this->m_pParentBtn->Paint(CanvasDrawCus, false);
	}
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::PaintSub(TCanvas *CanvasParent)
{
	if( m_VCSubtn.size() ) {

		for(vc_pFindVCTBtnPanel =m_VCSubtn.begin();
			vc_pFindVCTBtnPanel!=m_VCSubtn.end();
			vc_pFindVCTBtnPanel++ )
		{
			((TBtnPanel *)(*vc_pFindVCTBtnPanel))->Paint(CanvasParent, false);
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::Paint(TCanvas *Canvas, bool bParent)
{
	TCanvas *CanvasDraw = Canvas;

	TRect rtThis = TRect(this->Left, this->Top,
						 this->Left+this->Width,
						 this->Top +this->Height);

	TRect rtCreate = TRect(this->m_pTWnCtl->Left, this->m_pTWnCtl->Top,
						   this->m_pTWnCtl->Left+this->m_pTWnCtl->Width,
						   this->m_pTWnCtl->Top +this->m_pTWnCtl->Height);

	//自身创建
    HDC      ParentDC = GetDC(this->m_pTWnCtl->Handle);
	HDC      DCCreate;
	HBITMAP  BmpCreate;
	TCanvas *CanvasCreate;
	if( NULL==Canvas ) {

		DCCreate  = CreateCompatibleDC(ParentDC);
		BmpCreate = CreateCompatibleBitmap(ParentDC,
										   rtCreate.Width(),
										   rtCreate.Height());
		SelectObject(DCCreate, BmpCreate);
		PerformEraseBackground(this->m_pTWnCtl, DCCreate);
		CanvasCreate = new TCanvas();
		CanvasCreate->Handle = DCCreate;

		CanvasDraw = CanvasCreate;
		if( FTransparent ) {
			SetBkMode( CanvasDraw->Handle, TRANSPARENT);
			StyleServices()->DrawParentBackground(
				this->m_pTWnCtl->Handle,
				CanvasDraw->Handle,
				NULL, false, rtThis);
		}
	}

	//绘制
	if( FPanelDrEvent )
	{
		BtnHandleState();

		//新建绘制
		TCanvas *CanvasCusDraw = new TCanvas();
		HDC DCCusDraw;
		HBITMAP BmpCusDraw;
		DCCusDraw = CreateCompatibleDC(ParentDC);
		BmpCusDraw = CreateCompatibleBitmap(ParentDC, rtCreate.Width(),
													  rtCreate.Height());
		SelectObject(DCCusDraw, BmpCusDraw);
		PerformEraseBackground(this->m_pTWnCtl, DCCusDraw);
		CanvasCusDraw->Handle = DCCusDraw;

		if( FTransparent ) {

			SetBkMode( CanvasCusDraw->Handle, TRANSPARENT);
			StyleServices()->DrawParentBackground(
				this->m_pTWnCtl->Handle,
				CanvasCusDraw->Handle,
				NULL, false, rtThis);

			//parent贴图到自身区域
			if( this->m_pParentBtn  ) {

				if( true==bParent ) {

					if( NULL==Canvas )  PaintParent(CanvasDraw);
				}

				StretchBlt(CanvasCusDraw->Handle,
					rtThis.Left, rtThis.Top,
					rtThis.Width(), rtThis.Height(),
					CanvasDraw->Handle,
					rtThis.Left, rtThis.Top,
					rtThis.Width(), rtThis.Height(),
					SRCCOPY);
			}
		}

		FPanelDrEvent(FBtnCurState, rtThis, CanvasCusDraw);

		if( FTransparent ) {

			BLENDFUNCTION BFun;
			BFun.BlendOp              = AC_SRC_OVER;
			BFun.BlendFlags           = 0;
			BFun.SourceConstantAlpha  = FTransparentValue;
			BFun.AlphaFormat 		  = 0;

			::AlphaBlend( CanvasDraw->Handle,
				rtThis.Left, rtThis.Top,
				rtThis.Width(), rtThis.Height(),
				CanvasCusDraw->Handle,
				rtThis.Left, rtThis.Top,
				rtThis.Width(), rtThis.Height(),
				BFun);

		}else{

			StretchBlt(CanvasDraw->Handle,
				rtThis.Left, rtThis.Top,
				rtThis.Width(), rtThis.Height(),
				CanvasCusDraw->Handle,
				rtThis.Left, rtThis.Top,
				rtThis.Width(), rtThis.Height(),
				SRCCOPY);
		}

		if( true==bParent )
			PaintSub(CanvasDraw);

		DeleteDC(DCCusDraw);
		DeleteObject(BmpCusDraw);
		SAFE_DELETE(CanvasCusDraw)
	}

	if( NULL==Canvas ) {

		StretchBlt(ParentDC,
			this->Left,  this->Top,
			this->Width, this->Height,
			CanvasDraw->Handle,
			this->Left,  this->Top,
			this->Width, this->Height,
			SRCCOPY);

		DeleteDC(DCCreate);
		DeleteObject(BmpCreate);
		SAFE_DELETE(CanvasCreate)
	}
}
//---------------------------------------------------------------------------
void __fastcall TBtnPanel::Update(bool bEreaseBkg)
{
	if( m_pParentBtn && bEreaseBkg ) {

		((TBtnPanel *)m_pParentBtn)->Update(bEreaseBkg);

	}else {

		Paint();
	}
}
//---------------------------------------------------------------------------
