//--------------------------------------------------------------------------- #include #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(); } } //---------------------------------------------------------------------------