//--------------------------------------------------------------------------- #include #pragma hdrstop #include #include "SkinScrollBarUnit.h" //--------------------------------------------------------------------------- #pragma package(smart_init) TBitmap *u_pPicLineUp = NULL, *u_pPicLineDown = NULL, // 上下箭头和滑块3态:正常,高亮,按下 *u_pPicThumbTop = NULL, *u_pPicThumbMid = NULL, *u_pPicThumbBottom = NULL, *u_pPicThumbTile = NULL, *u_pPicPageUpTile = NULL, // 上轨 *u_pPicPageDownTile = NULL; // 下轨 int u_nPicRef = 0; //--------------------------------------------------------------------------- void InitialPictures() { if( u_nPicRef==0 ){ u_pPicLineUp = new TBitmap(); u_pPicLineUp->LoadFromResourceName(int(HInstance), L"SBLineUp"); u_pPicLineDown = new TBitmap(); u_pPicLineDown->LoadFromResourceName(int(HInstance), L"SBLineDown"); u_pPicPageUpTile = new TBitmap(); u_pPicPageUpTile->LoadFromResourceName(int(HInstance), L"SBPageUpTile"); u_pPicPageDownTile = new TBitmap(); u_pPicPageDownTile->LoadFromResourceName(int(HInstance), L"SBPageDownTile"); u_pPicThumbTop = new TBitmap(); u_pPicThumbTop->LoadFromResourceName(int(HInstance), L"SBThumbTop"); u_pPicThumbMid = new TBitmap(); u_pPicThumbMid->LoadFromResourceName(int(HInstance), L"SBThumbMid"); u_pPicThumbBottom = new TBitmap(); u_pPicThumbBottom->LoadFromResourceName(int(HInstance), L"SBThumbBottom"); u_pPicThumbTile = new TBitmap(); u_pPicThumbTile->LoadFromResourceName(int(HInstance), L"SBThumbTile"); } u_nPicRef++; } void ReleasePictures() { u_nPicRef--; if( u_nPicRef==0 ){ delete u_pPicLineUp; delete u_pPicLineDown; delete u_pPicPageUpTile; delete u_pPicPageDownTile; delete u_pPicThumbTop; delete u_pPicThumbMid; delete u_pPicThumbBottom; delete u_pPicThumbTile; } } //--------------------------------------------------------------------------- __fastcall TSkinScrollBar::TSkinScrollBar(TComponent* AOwner) : TScrollBar(AOwner) { InitialPictures(); m_wBar = u_pPicLineUp->Width / 3; Kind = sbVertical; Width = m_wBar; DoubleBuffered = TRUE; m_nThumbHeight = 0; m_nThumbTop = m_wBar;// Width; m_nPreThumbTop = m_wBar;// Width; m_nTileHeight = u_pPicPageUpTile->Height; m_nTrackPos = m_nMax = m_nMin = m_nPos = m_nPage = 0; m_iClicked = -1; m_iHitPrev = -1; m_bAction = m_bPause = m_bNotify = m_bDrag = m_bTrace = false; m_pCanvas = new TControlCanvas(); ((TControlCanvas*)m_pCanvas)->Control = this; Ctl3D = false; //鼠标长期按下的计时器 m_pTimer = new TTimer(this); m_pTimer->Enabled = false; m_pTimer->OnTimer = TimerProc; } //--------------------------------------------------------------------------- __fastcall TSkinScrollBar::~TSkinScrollBar() { if( m_pCanvas ){ delete m_pCanvas; m_pCanvas = NULL; } if( m_pTimer ){ delete m_pTimer; m_pTimer = NULL; } ReleasePictures(); } //--------------------------------------------------------------------------- int TSkinScrollBar::HitTest( int X, int Y ) { if( Y<0 || X<0 || X>m_wBar ) return -1; else if( YWidth/3 ) // m_pCanvas->Draw( x, y, pPic ); // else{ // TRect tmpRect; // tmpRect.Left = x; // tmpRect.Right = tmpRect.Left + Width*3; // tmpRect.Top = y; // tmpRect.Bottom = tmpRect.top + Width; // m_pCanvas->StretchDraw( tmpRect, pPic); // } m_pCanvas->Draw( x, y, pPic ); if( Width>m_wBar ){ TRect tmpRect; tmpRect.Left = m_wBar; tmpRect.Right = Width; tmpRect.Top = y; tmpRect.Bottom = tmpRect.top + m_wBar;//Width; m_pCanvas->Brush->Bitmap = u_pPicPageDownTile; m_pCanvas->FillRect( tmpRect ); } } //--------------------------------------------------------------------------- void TSkinScrollBar::DrawThumb( int iState, bool bEraseBk ) { TRect rectDraw, tmpRect; TBitmap *pBmp = NULL; int wBar = m_wBar; //Width; rectDraw.Left = 0; rectDraw.Right = rectDraw.Left + wBar;// Width; // 需要拉伸 // if( Width!=u_pPicPageUpTile->Width ){ // pBmp = new TBitmap(); // pBmp->Width = Width; // pBmp->Height = m_nTileHeight; // tmpRect.Left = 0; // tmpRect.Top = 0; // tmpRect.Right = Width; // tmpRect.Bottom = m_nTileHeight; // pBmp->Canvas->StretchDraw( tmpRect, u_pPicPageUpTile ); // } // 绘制上轨道 if( bEraseBk ) rectDraw.Top = wBar; //Width; else if( m_nPreThumbTopBrush->Bitmap = u_pPicPageUpTile; else{ m_pCanvas->Brush->Bitmap = pBmp; } m_pCanvas->FillRect( rectDraw ); } // 绘制下轨道 rectDraw.Top = m_nThumbTop + m_nThumbHeight; if( bEraseBk ) rectDraw.bottom = Height - wBar;// Width; else if( m_nPreThumbTop>m_nThumbTop ){ rectDraw.bottom = m_nThumbHeight+m_nPreThumbTop; if( rectDraw.bottom>Height-wBar ){// Width ){ rectDraw.bottom = Height-wBar; //Width; } } else rectDraw.Bottom = rectDraw.Top; if( rectDraw.Height()>0 ){ if( !pBmp ) m_pCanvas->Brush->Bitmap = u_pPicPageDownTile; else{ tmpRect.Left = 0; tmpRect.Top = 0; tmpRect.Right = wBar; //Width; tmpRect.Bottom = m_nTileHeight; pBmp->Canvas->StretchDraw( tmpRect, u_pPicPageDownTile ); m_pCanvas->Brush->Bitmap = pBmp; } m_pCanvas->FillRect( rectDraw ); } // 绘制滑块 if( m_nThumbHeight>0 ){ int x = - iState * wBar,// Width, y = m_nThumbTop, hTileUp, hTileDown; if( m_nThumbHeight>=THUMB_MINSIZE*2 ){ hTileUp = (m_nThumbHeight-THUMB_MINSIZE*2+1)/2, hTileDown = m_nThumbHeight - THUMB_MINSIZE*2 - hTileUp; } else{ hTileUp = (m_nThumbHeight-THUMB_MINSIZE+1)/2, hTileDown = m_nThumbHeight - THUMB_MINSIZE - hTileUp; } rectDraw.left = x; rectDraw.right = rectDraw.left + wBar*3; //Width*3; if( !pBmp ){ //滑块顶部圆弧 m_pCanvas->Draw( x, y, u_pPicThumbTop ); y += THUMB_BORDER; //滑块上部平铺 if( hTileUp>0 ){ for( int i=0; iHeight+1; i++ ){ m_pCanvas->Draw( x, y+u_pPicThumbTile->Height*i, u_pPicThumbTile ); } y += hTileUp; } //滑块中部条纹 if( m_nThumbHeight>=THUMB_MINSIZE*2 ){ m_pCanvas->Draw( x, y, u_pPicThumbMid ); y += THUMB_BORDER * 2; } //滑块下部平铺 if( hTileDown>0 ){ for( int i=0; iHeight+1; i++ ){ m_pCanvas->Draw( x, y+u_pPicThumbTile->Height*i, u_pPicThumbTile ); } y += hTileDown; } //滑块底部圆弧 m_pCanvas->Draw( x, y, u_pPicThumbBottom ); } else{ /* tmpRect.Left = x; tmpRect.Top = m_nThumbTop; tmpRect.Right = tmpRect.Left + Width*3; tmpRect.Bottom = tmpRect.Top + m_nThumbHeight; m_pCanvas->StretchDraw( tmpRect, u_pPicThumbTop ); */ } } if( Width>wBar ){ tmpRect.Left = wBar; tmpRect.Right = Width; tmpRect.Top = wBar; tmpRect.Bottom = Height - wBar; m_pCanvas->Brush->Bitmap = u_pPicPageDownTile; m_pCanvas->FillRect( tmpRect ); } // 清除临时图画 if( pBmp ){ delete pBmp; pBmp = NULL; } m_nPreThumbTop = m_nThumbTop; } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::PaintWindow(HDC DC) { if( !m_pCanvas->Handle ) m_pCanvas->Handle = DC; // 绘制上箭头 DrawArrow( SB_LINEUP, STATE_NORMAL ); // 绘制滑块 DrawThumb( STATE_NORMAL, true ); // 绘制下箭头 DrawArrow( SB_LINEDOWN, STATE_NORMAL ); } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::WMPaint(TWMPaint &Message) { PaintHandler(Message); } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::SetPosition(int Value, bool bRedraw) { if( m_nPos!=Value ){ m_nPos = Value; CalcThumbTop(); if( bRedraw ) DrawThumb( STATE_NORMAL, false ); } } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::SetPageSize(int Value, bool bRedraw) { if( m_nPage!=Value ){ m_nPage = Value; CalcThumbHeight(); if( bRedraw ){ DrawThumb( STATE_NORMAL, true ); Invalidate(); } } } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::SetRange(int AMin, int AMax, bool bRedraw) { if( m_nMin!=AMin || m_nMax!=AMax ){ m_nMin = AMin; m_nMax = AMax; CalcThumbHeight(); if( bRedraw ){ DrawThumb( STATE_NORMAL, true ); Invalidate(); } } } //--------------------------------------------------------------------------- int __fastcall TSkinScrollBar::GetScrollPos() { return m_nPos; } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::GetScrollRange(int* nMin, int* nMax) { *nMin = m_nMin; *nMax = m_nMax; } //--------------------------------------------------------------------------- int __fastcall TSkinScrollBar::GetPageSize() { return m_nPage; } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::SBMSetScrollInfo(TMessage &Message) { bool bRedraw = bool(Message.WParam) && Visible; PScrollInfo pSi = PScrollInfo(Message.LParam); if( pSi->fMask & SIF_RANGE ) SetRange( pSi->nMin, pSi->nMax, bRedraw ); if( pSi->fMask & SIF_PAGE ) SetPageSize( pSi->nPage, bRedraw ); if( pSi->fMask & SIF_POS ) SetPosition( pSi->nPos, bRedraw ); } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::SBMGetScrollInfo(TMessage &Message) { PScrollInfo pSi = PScrollInfo(Message.LParam); if( pSi->fMask & SIF_PAGE ) pSi->nPage = m_nPage; if( pSi->fMask & SIF_POS ) pSi->nPos = m_nPos; if( pSi->fMask & SIF_TRACKPOS ) pSi->nTrackPos = m_nTrackPos; if( pSi->fMask & SIF_RANGE ){ pSi->nMin = m_nMin; pSi->nMax = m_nMax; } } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::WMLButtonDown(TWMMouse &Message) { SetCapture(Handle); m_bAction = true; m_pWndCtrl->SetFocus(); int iHit = HitTest( Message.XPos, Message.YPos ); if( iHit==SB_THUMBTRACK ){ m_bDrag = TRUE; m_nDragPoint = Message.YPos; m_nDragPos = m_nPos; m_nTrackPos = m_nDragPos; DrawThumb( STATE_PUSH, false ); } else{ m_iClicked = iHit; m_pWndCtrl->Perform( WM_VSCROLL, MAKELONG(m_iClicked,0), LPARAM(Handle) ); m_pTimer->Interval = TIME_DELAY; m_pTimer->Enabled = true; m_bPause = false; int nNewPos = m_nPos; if( iHit==SB_LINEUP || iHit==SB_LINEDOWN ){ DrawArrow( iHit, STATE_PUSH ); nNewPos += (iHit==SB_LINEUP) ? -1 : 1; } else if( iHit==SB_PAGEUP || iHit==SB_PAGEDOWN ){ nNewPos += (iHit==SB_PAGEUP) ? -m_nPage+1 : m_nPage-1; } int nLenInSi = m_nMax-m_nMin-m_nPage+1; if( nNewPosnLenInSi ) nNewPos = nLenInSi; if( nNewPos!=m_nPos ){ m_nPos = nNewPos; CalcThumbTop(); DrawThumb( STATE_NORMAL, false ); } } } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::WMLButtonUp(TWMMouse &Message) { ReleaseCapture(); if( m_bDrag ){ m_bDrag = false; m_pWndCtrl->Perform(WM_VSCROLL, MAKELONG(SB_THUMBPOSITION, m_nTrackPos), LPARAM(Handle) ); if( m_nTrackPos!=m_nPos ){ // ?????? m_nPos = m_nTrackPos; } m_nTrackPos = 0; CalcThumbTop(); int iHit = HitTest( Message.XPos, Message.YPos ); if( iHit==SB_THUMBTRACK ) DrawThumb( STATE_HIGHLIGHT, false ); else DrawThumb( STATE_NORMAL, false ); } else if( m_iClicked!=-1 ){ m_pTimer->Enabled = false; if( m_bNotify ){ m_bNotify = false; } if( m_iClicked==SB_LINEUP || m_iClicked==SB_LINEDOWN ) DrawArrow( m_iClicked, STATE_NORMAL ); m_iClicked = -1; } m_bAction = false; } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::WMLButtonDblClk(TWMMouse &Message) { int uHit = HitTest( Message.XPos, Message.YPos ); if( uHit!=SB_THUMBTRACK ){ m_iClicked = uHit; WMLButtonDown( Message ); m_bAction = false; } } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::WMMouseMove(TWMMouse &Message) { if( ((TListBox*)m_pWndCtrl)->OnMouseLeave ){ ((TListBox*)m_pWndCtrl)->OnMouseLeave(NULL); } Windows::TTrackMouseEvent tme; int nDragLen, nLenInSi, nSlide, nTrackLen, nNewPos, iHit, iState; if( !m_bTrace && (Message.Keys & MK_LBUTTON) ){ tme.cbSize = sizeof(tme); tme.hwndTrack = Handle; tme.dwFlags = TME_LEAVE; tme.dwHoverTime = 1; m_bTrace = _TrackMouseEvent(&tme); } if( m_bDrag ){ nTrackLen = Height - m_nThumbHeight - 2 * m_wBar;//Width; nLenInSi = m_nMax-m_nMin-m_nPage+1; nDragLen = Message.YPos - m_nDragPoint; if( nTrackLen==0 ) nSlide = 0; else nSlide = nDragLen * nLenInSi / nTrackLen; nNewPos = m_nDragPos + nSlide; if( nNewPosnLenInSi ) nNewPos = nLenInSi; if( nNewPos!=m_nTrackPos ){ m_nTrackPos = nNewPos; CalcThumbTop(); DrawThumb( STATE_PUSH, false ); m_pWndCtrl->Perform(WM_VSCROLL, MAKELONG(SB_THUMBTRACK, m_nTrackPos), LPARAM(Handle) ); } } else if( m_iClicked!=-1 ){ iHit = HitTest( Message.XPos, Message.YPos ); if( iHit==m_iClicked ){ m_bPause = false; iState = STATE_HIGHLIGHT; } else{ m_bPause = true; iState = STATE_NORMAL; } if( m_iClicked==SB_LINEUP || m_iClicked==SB_LINEDOWN ) DrawArrow( m_iClicked, iState ); } else{ iHit = HitTest( Message.XPos, Message.YPos ); if( iHit!=m_iHitPrev ){ if( m_iHitPrev!=-1 ){ if( m_iHitPrev==SB_THUMBTRACK ) DrawThumb( STATE_NORMAL, FALSE ); else if( m_iHitPrev==SB_LINEUP || m_iHitPrev==SB_LINEDOWN ) DrawArrow( m_iHitPrev, STATE_NORMAL ); } if( iHit!=-1 ){ if( iHit==SB_THUMBTRACK ) DrawThumb( STATE_HIGHLIGHT, FALSE ); else if( iHit==SB_LINEUP || iHit==SB_LINEDOWN ) DrawArrow( iHit, STATE_HIGHLIGHT ); } m_iHitPrev = iHit; } } } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::CMMouseLeave(TMessage &Message) { if( m_iHitPrev!=-1 ){ if( m_iHitPrev==SB_THUMBTRACK ) DrawThumb( STATE_NORMAL, false ); else if( m_iHitPrev==SB_LINEUP || m_iHitPrev==SB_LINEDOWN ) DrawArrow( m_iHitPrev, STATE_NORMAL ); m_iHitPrev = -1; } } //--------------------------------------------------------------------------- void __fastcall TSkinScrollBar::TimerProc(TObject* Sender) { if( m_pTimer->Interval==TIME_DELAY ){ m_bNotify = true; m_pTimer->Enabled = false; m_pTimer->Interval = TIME_NOTIFY; m_pTimer->Enabled = true; } else if( m_pTimer->Interval==TIME_NOTIFY && !m_bPause ){ int nNewPos = m_nPos; switch( m_iClicked ){ case SB_LINEUP: nNewPos -= 1; if( m_nPos==m_nMin ){ m_pTimer->Enabled = false; return; } break; case SB_LINEDOWN: nNewPos += 1; if( m_nPos==m_nMax ){ m_pTimer->Enabled = false; return; } break; case SB_PAGEUP: case SB_PAGEDOWN: { TPoint pt; GetCursorPos(&pt); pt = ScreenToClient(pt); int iHit = HitTest( pt.X, pt.Y ); if( iHit==SB_THUMBTRACK ){ m_pTimer->Enabled = false; return; } nNewPos += (m_iClicked==SB_PAGEUP) ? -m_nPage+1 : m_nPage-1; } break; } int nLenInSi = m_nMax-m_nMin-m_nPage+1; if( nNewPosnLenInSi ) nNewPos = nLenInSi; if( nNewPos!=m_nPos ){ m_nPos = nNewPos; CalcThumbTop(); DrawThumb( STATE_NORMAL, false ); } m_pWndCtrl->Perform( WM_VSCROLL, MAKELONG(m_iClicked,0), LPARAM(Handle) ); } }