Files
AC_Pro/BtnPanelUnit.cpp
2026-06-13 00:05:19 +08:00

528 lines
12 KiB
C++

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