528 lines
12 KiB
C++
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();
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|