//--------------------------------------------------------------------------- #include #pragma hdrstop #include "TransSkinScrollBar.h" //--------------------------------------------------------------------------- #pragma package(smart_init) //--------------------------------------------------------------------------- #include "BtnPanelUnit.h" #include #include #include #define PERIOD (200) #define THUMB_MIN (14) #define THUMB_LEFT (1) #define THUMB_GKG (Height-2*Width) #define THUMB_BKGLEFT (THUMB_GKG-THUMB_MIN) #define THUMB_WIDTH (Width-2*THUMB_LEFT) #define H_THUMB_GKG (Width-2*Height) #define H_THUMB_BKGLEFT (H_THUMB_GKG-THUMB_MIN) #define H_THUMB_HEIGHT (Height-2*THUMB_LEFT) //--------------------------------------------------------------------------- // ValidCtrCheck is used to assure that the components created do not have // any pure virtual functions. // static inline void ValidCtrCheck(TTransSkinScollBar *) { new TTransSkinScollBar(NULL); } //--------------------------------------------------------------------------- //__fastcall TTransSkinScollBar::TTransSkinScollBar(TComponent* Owner) // : TPaintBox(Owner) //{ //} ////--------------------------------------------------------------------------- namespace Transskinscrollbar { void __fastcall PACKAGE Register() { TComponentClass classes[1] = {__classid(TTransSkinScollBar)}; RegisterComponents(L"Samples", classes, 0); } } //--------------------------------------------------------------------------- __fastcall TTransSkinScollBar::TTransSkinScollBar(TComponent* Owner) : Vcl::Extctrls::TPanel(Owner) { ControlStyle >> csOpaque; DoubleBuffered = true; Width = 14; Height = 80; FVertial = true; FSBShow = 0; FSBTotal = 0; FSBTop = 0; m_BtnBKG = new TBtnPanel(this); m_BtnBKG->OnPanelDrEvent = BtnPaintBKG; m_BtnBKG->OnPanelMsEvent = BtnEventBKG; m_BtnBKG->StateCount = 1; m_BtnBKG->Transparent = true; m_BtnBKG->TransparentValue = 150; m_BtnThumb = new TBtnPanel(this); m_BtnThumb->OnPanelDrEvent = BtnPaintThumb; m_BtnThumb->OnPanelMsEvent = BtnEventThumb; m_BtnThumb->StateCount = 1; m_BtnThumb->Transparent = true; m_BtnBKG->AddSubPanel(m_BtnThumb); m_BtnLINEUp = new TBtnPanel(this); m_BtnLINEUp->OnPanelDrEvent = BtnPaintLINEUp; m_BtnLINEUp->OnPanelMsEvent = BtnEventLINEUp; m_BtnLINEUp->StateEnter = false; m_BtnLINEDown = new TBtnPanel(this); m_BtnLINEDown->OnPanelDrEvent = BtnPaintLINEDown; m_BtnLINEDown->OnPanelMsEvent = BtnEventLINEDown; m_BtnLINEDown->StateEnter = false; m_bLineUp = true; m_bPageUp = true; m_pTTimerLine = new TTimer(this); m_pTTimerLine->Interval = PERIOD; m_pTTimerLine->OnTimer = EventTimerThumb; m_pTTimerLine->Enabled = false; m_pTTimerPage = new TTimer(this); m_pTTimerPage->Interval = PERIOD; m_pTTimerPage->OnTimer = EventTimerThumb; m_pTTimerPage->Enabled = false; FThumbWidth = -1; m_bPices = false; } //--------------------------------------------------------------------------- __fastcall TTransSkinScollBar::~TTransSkinScollBar(void) { SAFE_DELETE(m_BtnBKG) SAFE_DELETE(m_BtnThumb) SAFE_DELETE(m_BtnLINEUp) SAFE_DELETE(m_BtnLINEDown) SAFE_DELETE(m_pTTimerLine) SAFE_DELETE(m_pTTimerPage) } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::SetSBTop(int nTop) { if(nTop<0) nTop = 0; else if(nTop>FSBTotal-FSBShow+1) nTop = nTop>FSBTotal-FSBShow+1; FSBTop = nTop; TWMSize tmp; WMSize(tmp); } //--------------------------------------------------------------------------- int __fastcall TTransSkinScollBar::CalThumbHeight() { if(FSBTotal==0) return 0; int nHeight = 0; if( -1==FThumbWidth ) { int nPosS = THUMB_BKGLEFT; int nPosV = FSBTotal-FSBShow+1; if( nPosS>=nPosV ) { int nLenPiece = nPosS/nPosV; if( 0!=nPosS%nPosV ) { nLenPiece += nPosS%nLenPiece; } nHeight = nLenPiece; if( THUMB_GKG/nPosV>=nHeight ) { int nLenPiece = THUMB_GKG/nPosV; if( 0!=THUMB_GKG%nPosV ) { nLenPiece += THUMB_GKG%nLenPiece; } nHeight = nLenPiece; m_bPices = true; } } if( nHeightHeight> m_BtnBKG->Top+m_BtnBKG->Height ) { nTop = m_BtnBKG->Top+m_BtnBKG->Height - CalThumbHeight(); } return nTop; } //--------------------------------------------------------------------------- int __fastcall TTransSkinScollBar::CalThumbWidth() { if(FSBTotal==0) return 0; int nWidth = 0; if( -1==FThumbWidth ) { int nPosS = H_THUMB_BKGLEFT; int nPosV = FSBTotal-FSBShow+1; if( nPosS>=nPosV ) { int nLenPiece = nPosS/nPosV; if( 0!=nPosS%nPosV ) { nLenPiece += nPosS%nLenPiece; } nWidth = nLenPiece; if( H_THUMB_GKG/nPosV>=nWidth ) { int nLenPiece = H_THUMB_GKG/nPosV; if( 0!=H_THUMB_GKG%nPosV ) { nLenPiece += H_THUMB_GKG%nLenPiece; } nWidth = nLenPiece; m_bPices = true; } } if( nWidthWidth> m_BtnBKG->Left+m_BtnBKG->Width ) { nLeft = m_BtnBKG->Left+m_BtnBKG->Width - CalThumbWidth(); } return nLeft; } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::SetVertial(bool bFVertial) { FVertial = bFVertial; int WidthTmp = Width; int HeightTmp = Height; if( FVertial ) { Width = (WidthTmpHeightTmp)?WidthTmp:HeightTmp; Height = (WidthTmp>HeightTmp)?HeightTmp:WidthTmp; } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::CreateWnd(void) { Vcl::Extctrls::TPanel::CreateWnd(); SetWindowLong( Parent->Handle, GWL_STYLE, GetWindowLong(Parent->Handle, GWL_STYLE) & ~WS_CLIPCHILDREN ); // SetBkMode( Canvas->Handle, TRANSPARENT); } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::CreateParams(Controls::TCreateParams &Params) { Vcl::Extctrls::TPanel::CreateParams(Params); Params.ExStyle |= WS_EX_TRANSPARENT; } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::WMSize(Winapi::Messages::TWMSize &Message) { int WidthTmp = Width; int HeightTmp = Height; if( FVertial ) { Width = (WidthTmpHeightTmp)?WidthTmp:HeightTmp; Height = (WidthTmp>HeightTmp)?HeightTmp:WidthTmp; } int nLeft, nTop, nWidth, nHeight; if( FVertial ) { m_BtnBKG->Left = 0; m_BtnBKG->Top = Width; m_BtnBKG->Width = Width; m_BtnBKG->Height = Height-2*Width; if(FSBTotal<=FSBShow) { nLeft = 0; nTop = 0; nWidth = 0; nHeight = 0; }else{ nLeft = THUMB_LEFT; nTop = CalThumbTop(); nWidth = THUMB_WIDTH; nHeight = CalThumbHeight(); } m_BtnThumb->Left = nLeft; m_BtnThumb->Top = nTop; m_BtnThumb->Width = nWidth; m_BtnThumb->Height = nHeight; m_BtnLINEUp->Left = 0; m_BtnLINEUp->Top = 0; m_BtnLINEUp->Width = Width; m_BtnLINEUp->Height = Width; m_BtnLINEDown->Left = 0; m_BtnLINEDown->Top = Height-Width; m_BtnLINEDown->Width = Width; m_BtnLINEDown->Height = Width; }else{ m_BtnBKG->Left = Height; m_BtnBKG->Top = 0; m_BtnBKG->Width = Width-2*Height; m_BtnBKG->Height = Height; if(FSBTotal<=FSBShow) { nLeft = 0; nTop = 0; nWidth = 0; nHeight = 0; }else{ nLeft = CalThumbLeft(); nTop = THUMB_LEFT; nWidth = CalThumbWidth(); nHeight = H_THUMB_HEIGHT; } m_BtnThumb->Left = nLeft; m_BtnThumb->Top = nTop; m_BtnThumb->Width = nWidth; m_BtnThumb->Height = nHeight; m_BtnLINEUp->Left = 0; m_BtnLINEUp->Top = 0; m_BtnLINEUp->Width = Height; m_BtnLINEUp->Height = Height; m_BtnLINEDown->Left = Width-Height; m_BtnLINEDown->Top = 0; m_BtnLINEDown->Width = Height; m_BtnLINEDown->Height = Height; } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::WMEraseBkgnd(TWMEraseBkgnd &Message) { Message.Result = true; } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::AddThumbTop(int nAdd, bool bEraseBKG, TTimer *pTTimer) { int nTop = FSBTop; nTop += nAdd; SetThumbTop(nTop, bEraseBKG, pTTimer); } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::SetThumbTop(int nTop, bool bEraseBKG, TTimer *pTTimer) { if( nTop<0 ) { nTop = 0; if( pTTimer ) pTTimer->Enabled = false; } if( nTop>=FSBTotal-FSBShow ) { nTop = FSBTotal-FSBShow; if( pTTimer ) pTTimer->Enabled = false; } FSBTop = nTop; if( FVertial ) m_BtnThumb->Top = CalThumbTop(); else m_BtnThumb->Left = CalThumbLeft(); if( FChangePos ) FChangePos(this); if( bEraseBKG ) { // m_BtnThumb->Update(); // this->Invalidate(); } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::EventTimerThumb(System::TObject* Sender) { int nAdd = 0; if( Sender==(TObject *)m_pTTimerLine ) { if( m_bLineUp ) { nAdd = -1; }else { nAdd = 1; } }else if( Sender==(TObject *)m_pTTimerPage ) { TPoint ptCur; GetCursorPos(&ptCur); ptCur = this->ScreenToClient(ptCur); if( FVertial ) { if( m_bPageUp ) { if( ptCur.Y>=m_BtnThumb->Top ) { m_pTTimerPage->Enabled = false; return; } nAdd = -FSBShow; }else { if( ptCur.Y<=m_BtnThumb->Top+m_BtnThumb->Height ) { m_pTTimerPage->Enabled = false; return; } nAdd = FSBShow; } }else { if( m_bPageUp ) { if( ptCur.X>=m_BtnThumb->Left ) { m_pTTimerPage->Enabled = false; return; } nAdd = -FSBShow; }else { if( ptCur.X<=m_BtnThumb->Left+m_BtnThumb->Width ) { m_pTTimerPage->Enabled = false; return; } nAdd = FSBShow; } } } AddThumbTop(nAdd, true, (TTimer *)Sender); } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::BtnEventLINEUp(int MsTmp, int XPos, int YPos) { if( Ms_LDOWN==MsTmp ) { m_bLineUp = true; AddThumbTop(-1, true); m_pTTimerLine->Enabled = true; }else if( Ms_LUP==MsTmp ) { m_pTTimerLine->Enabled = false; }else if( Ms_LLDOWN==MsTmp ) { m_pTTimerLine->Enabled = false; AddThumbTop(-1, true); } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::BtnEventLINEDown(int MsTmp, int XPos, int YPos) { if( Ms_LDOWN==MsTmp ) { m_bLineUp = false; AddThumbTop(1, true); m_pTTimerLine->Enabled = true; }else if( Ms_LUP==MsTmp ) { m_pTTimerLine->Enabled = false; }else if( Ms_LLDOWN==MsTmp ) { m_pTTimerLine->Enabled = false; AddThumbTop(1, true); } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::BtnEventBKG(int MsTmp, int XPos, int YPos) { TPoint pt = TPoint(XPos, YPos); TRect TRectUp, TRectDn; if( Ms_LDOWN==MsTmp || Ms_LLDOWN==MsTmp ) { int nLeft, nTop, nWidth, nHeight; if( FVertial ) { nLeft = m_BtnBKG->Left; nTop = m_BtnBKG->Top; nWidth = m_BtnBKG->Width; nHeight = m_BtnThumb->Top - m_BtnBKG->Top; TRectUp = TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight); nTop = m_BtnThumb->Top+m_BtnThumb->Height; nHeight = m_BtnBKG->Top+m_BtnBKG->Height-nTop; TRectDn = TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight); }else { nLeft = m_BtnBKG->Left; nTop = m_BtnBKG->Top; nWidth = m_BtnThumb->Left - m_BtnBKG->Left; nHeight = m_BtnBKG->Height; TRectUp = TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight); nLeft = m_BtnThumb->Left+m_BtnThumb->Width; nWidth = m_BtnBKG->Left+m_BtnBKG->Width-nLeft; TRectDn = TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight); } } if( Ms_LDOWN==MsTmp ) { m_pTTimerPage->Enabled = true; if( PtInRect(TRectUp, pt ) ) { m_bPageUp = true; if( 1==m_BtnBKG->StateCount ) AddThumbTop(-FSBShow, true); else AddThumbTop(-FSBShow); }else if( PtInRect(TRectDn, pt) ){ m_bPageUp = false; if( 1==m_BtnBKG->StateCount ) AddThumbTop(FSBShow, true); else AddThumbTop(FSBShow); } }else if( Ms_LUP==MsTmp ) { m_pTTimerPage->Enabled = false; }else if( Ms_LLDOWN==MsTmp ) { m_pTTimerPage->Enabled = false; if( PtInRect(TRectUp, pt ) ) { m_bPageUp = true; AddThumbTop(-FSBShow, true); }else if( PtInRect(TRectDn, pt) ){ m_bPageUp = false; AddThumbTop(FSBShow, true); } } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::BtnEventThumb(int MsTmp, int XPos, int YPos) { static bool bBKGEnter = false; if( Ms_DRAG==MsTmp ) { int nCurPos, nAdd; if( FVertial ) { nCurPos = YPos; nAdd =(FSBTotal-FSBShow+1)*(nCurPos-14)/THUMB_BKGLEFT; }else { nCurPos = XPos; nAdd =(FSBTotal-FSBShow+1)*(nCurPos-14)/H_THUMB_BKGLEFT; } if( m_BtnBKG->StateEnter ) { m_BtnBKG->StateEnter = false; bBKGEnter = true; } SetThumbTop(nAdd, true); }else if( Ms_LUP==MsTmp ){ if( bBKGEnter ) m_BtnBKG->StateEnter = true; } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::Paint() { SetBkMode( Canvas->Handle, TRANSPARENT); StyleServices()->DrawParentBackground( Handle, Canvas->Handle, NULL, false); HDC ParentDC = GetDC(Handle); //创建一个与显示设备兼容的内存设备 HDC BufDC = CreateCompatibleDC(ParentDC); // 创建一个与显示设备兼容的位图 HBITMAP BufBitmap = CreateCompatibleBitmap(Canvas->Handle, Width, Height); // 将设备与位图关联 SelectObject(BufDC, BufBitmap); // CreateCompatibleBitmap创建位图后数据初始化为0,而RGB(0,0,0)则表示是黑色 // 这里需要清除其黑色背景,使其变为透明 PerformEraseBackground(this, BufDC); // 临时的Canvas,用来画图用,但它并不是必须的,可以直接使用GDI函数来画图 TCanvas *CanvasDraw = new TCanvas(); // 关联到内存设备 CanvasDraw->Handle = BufDC; //-------------------------------------- SetBkMode( CanvasDraw->Handle, TRANSPARENT); StyleServices()->DrawParentBackground( Handle, CanvasDraw->Handle, NULL, false); m_BtnLINEUp->Paint(CanvasDraw); m_BtnBKG->Paint(CanvasDraw); m_BtnLINEDown->Paint(CanvasDraw); // 一次性将内存图像数据覆盖过去,因为跳过了擦除背景过程,所以避免了闪烁的问题 BitBlt(Canvas->Handle, 0, 0, ClientWidth, ClientHeight, CanvasDraw->Handle, 0, 0, SRCCOPY); // 释放资源 DeleteDC(BufDC); DeleteObject(BufBitmap); SAFE_DELETE(CanvasDraw) } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::BtnPaintLINEUp(int BsTmp, TRect TRectTmp, TCanvas *pCanvas) { int nLeft, nTop, nWidth, nHeight; if( Bs_NORMAL==BsTmp ) { pCanvas->Brush->Color = RGB(156, 156, 156); pCanvas->FillRect(TRectTmp); pCanvas->Brush->Color = RGB(76, 76, 76); nLeft = TRectTmp.Width()/2/2+1; nTop = TRectTmp.Height()/2 - 1; nWidth = TRectTmp.Width()/2; nHeight = 2; pCanvas->FillRect(TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight)); }else if( Bs_DOWN==BsTmp ) { pCanvas->Brush->Color = RGB(156, 156, 156); pCanvas->FillRect(TRectTmp); pCanvas->Brush->Color = RGB(0, 0, 0); nLeft = TRectTmp.Width()/2/2+1; nTop = TRectTmp.Height()/2 - 1; nWidth = TRectTmp.Width()/2; nHeight = 2; pCanvas->FillRect(TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight)); } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::BtnPaintLINEDown(int BsTmp, TRect TRectTmp, TCanvas *pCanvas) { int nLeft, nTop, nWidth, nHeight; if( Bs_NORMAL==BsTmp ) { pCanvas->Brush->Color = RGB(156, 156, 156); pCanvas->FillRect(TRectTmp); pCanvas->Brush->Color = RGB(76, 76, 76); nLeft = TRectTmp.Left+TRectTmp.Width()/2/2; nTop = TRectTmp.Height()/2 - 1; nWidth = TRectTmp.Width()/2+1; nHeight = 2; TRect rtMinus = TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight); pCanvas->FillRect( rtMinus ); nLeft = TRectTmp.Left+TRectTmp.Width()/2-1; nTop = TRectTmp.Height()/2/2; nWidth = 2; nHeight = TRectTmp.Height()/2+1; pCanvas->FillRect(TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight)); }else if( Bs_DOWN==BsTmp ) { pCanvas->Brush->Color = RGB(156, 156, 156); pCanvas->FillRect(TRectTmp); pCanvas->Brush->Color = RGB(0, 0, 0); nLeft = TRectTmp.Left+TRectTmp.Width()/2/2; nTop = TRectTmp.Height()/2 - 1; nWidth = TRectTmp.Width()/2+1; nHeight = 2; TRect rtMinus = TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight); pCanvas->FillRect( rtMinus ); nLeft = TRectTmp.Left+TRectTmp.Width()/2-1; nTop = TRectTmp.Height()/2/2; nWidth = 2; nHeight = TRectTmp.Height()/2+1; pCanvas->FillRect(TRect(nLeft, nTop, nLeft+nWidth, nTop+nHeight)); } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::BtnPaintBKG(int BsTmp, TRect TRectTmp, TCanvas *pCanvas) { if( Bs_NORMAL==BsTmp ) { pCanvas->Brush->Color = RGB(123, 123, 123); pCanvas->FillRect(TRectTmp); pCanvas->Pen->Color = RGB(233, 233, 233); pCanvas->Rectangle(TRectTmp); } } //--------------------------------------------------------------------------- void __fastcall TTransSkinScollBar::BtnPaintThumb(int BsTmp, TRect TRectTmp, TCanvas *pCanvas) { if( Bs_NORMAL==BsTmp ) { TPngImage *png = new TPngImage(); png->LoadFromResourceName(int(HInstance), L"round"); pCanvas->StretchDraw(TRectTmp, png); SAFE_DELETE(png) } } //---------------------------------------------------------------------------