📄 ctrllibrarytree.cpp
字号:
Select( m_pFocus, TS_TRUE, FALSE );
Highlight( m_pFocus );
NotifySelection();
return;
}
}
}
}
if ( pTo != NULL )
{
if ( ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 || m_pFocus == NULL )
{
bChanged |= DeselectAll( m_pFocus = pTo );
bChanged |= Select( m_pFocus );
}
else
{
bChanged |= Select( m_pFocus = pTo );
}
Highlight( m_pFocus );
}
if ( bChanged ) NotifySelection();
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeCtrl scrolling
void CLibraryTreeCtrl::UpdateScroll()
{
SCROLLINFO pInfo;
pInfo.cbSize = sizeof(pInfo);
pInfo.fMask = SIF_ALL & ~SIF_TRACKPOS;
pInfo.nMin = 0;
pInfo.nMax = m_nTotal * ITEM_HEIGHT;
pInfo.nPage = m_nVisible;
pInfo.nPos = m_nScroll = max( 0, min( m_nScroll, pInfo.nMax - (int)pInfo.nPage + 1 ) );
SetScrollInfo( SB_VERT, &pInfo, TRUE );
}
void CLibraryTreeCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
switch ( nSBCode )
{
case SB_BOTTOM:
ScrollTo( 0xFFFFFFFF );
break;
case SB_LINEDOWN:
ScrollBy( 16 );
break;
case SB_LINEUP:
ScrollBy( -16 );
break;
case SB_PAGEDOWN:
ScrollBy( m_nVisible );
break;
case SB_PAGEUP:
ScrollBy( -m_nVisible );
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
ScrollTo( nPos );
break;
case SB_TOP:
ScrollTo( 0 );
break;
}
}
BOOL CLibraryTreeCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
ScrollBy( zDelta * 3 * -ITEM_HEIGHT / WHEEL_DELTA );
return TRUE;
}
void CLibraryTreeCtrl::ScrollBy(int nDelta)
{
ScrollTo( max( 0, m_nScroll + nDelta ) );
}
void CLibraryTreeCtrl::ScrollTo(int nPosition)
{
if ( nPosition == m_nScroll ) return;
m_nScroll = nPosition;
UpdateScroll();
CRect rc;
GetClientRect( &rc );
RedrawWindow( &rc, NULL, RDW_INVALIDATE );
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeCtrl painting
BOOL CLibraryTreeCtrl::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CLibraryTreeCtrl::OnPaint()
{
CPaintDC dc( this );
CRect rcClient;
GetClientRect( &rcClient );
CPoint pt( rcClient.left, rcClient.top - m_nScroll );
CLibraryTreeItem** pChild = m_pRoot->m_pList;
CFont* pOldFont = (CFont*)dc.SelectObject( &CoolInterface.m_fntNormal );
for ( int nCount = m_pRoot->m_nCount ; nCount && pt.y < rcClient.bottom ; nCount--, pChild++ )
{
Paint( dc, rcClient, pt, *pChild );
}
dc.SelectObject( pOldFont );
dc.FillSolidRect( &rcClient, CoolInterface.m_crWindow );
}
void CLibraryTreeCtrl::Paint(CDC& dc, CRect& rcClient, CPoint& pt, CLibraryTreeItem* pItem)
{
CRect rc( pt.x, pt.y, pt.x, pt.y + ITEM_HEIGHT );
pt.y += ITEM_HEIGHT;
if ( rc.top >= rcClient.bottom )
{
return;
}
else if ( rc.bottom >= rcClient.top )
{
if ( pItem->m_bBold ) dc.SelectObject( &CoolInterface.m_fntBold );
rc.right += 32 + dc.GetTextExtent( pItem->m_sText ).cx + 6;
if ( dc.RectVisible( &rc ) )
{
pItem->Paint( dc, rc, m_pDropItem == pItem );
dc.ExcludeClipRect( &rc );
}
if ( pItem->m_bBold ) dc.SelectObject( &CoolInterface.m_fntNormal );
}
if ( pItem->m_bExpanded && pItem->m_nCount )
{
pt.x += 16;
CLibraryTreeItem** pChild = pItem->m_pList;
for ( int nCount = pItem->m_nCount ; nCount ; nCount--, pChild++ )
{
Paint( dc, rcClient, pt, *pChild );
if ( pt.y >= rcClient.bottom ) break;
}
pt.x -= 16;
}
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeCtrl hit testing
CLibraryTreeItem* CLibraryTreeCtrl::HitTest(const POINT& point, RECT* pRect) const
{
CRect rcClient;
GetClientRect( &rcClient );
CPoint pt( rcClient.left, rcClient.top - m_nScroll );
CLibraryTreeItem** pChild = m_pRoot->m_pList;
for ( int nCount = m_pRoot->m_nCount ; nCount && pt.y < rcClient.bottom ; nCount--, pChild++ )
{
CLibraryTreeItem* pItem = HitTest( rcClient, pt, *pChild, point, pRect );
if ( pItem ) return pItem;
}
return NULL;
}
CLibraryTreeItem* CLibraryTreeCtrl::HitTest(CRect& rcClient, CPoint& pt, CLibraryTreeItem* pItem, const POINT& point, RECT* pRect) const
{
CRect rc( rcClient.left, pt.y, rcClient.right, pt.y + ITEM_HEIGHT );
pt.y += ITEM_HEIGHT;
if ( rc.top >= rcClient.bottom + ITEM_HEIGHT )
{
return NULL;
}
else if ( rc.bottom >= rcClient.top - ITEM_HEIGHT )
{
if ( rc.PtInRect( point ) )
{
if ( pRect )
{
CopyMemory( pRect, &rc, sizeof(RECT) );
pRect->left = pt.x;
}
return pItem;
}
}
if ( pItem->m_bExpanded && pItem->m_nCount )
{
pt.x += 16;
CLibraryTreeItem** pChild = pItem->m_pList;
for ( int nCount = pItem->m_nCount ; nCount ; nCount--, pChild++ )
{
CLibraryTreeItem* pItem = HitTest( rcClient, pt, *pChild, point, pRect );
if ( pItem ) return pItem;
if ( pt.y >= rcClient.bottom + ITEM_HEIGHT ) break;
}
pt.x -= 16;
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeCtrl rect lookup
BOOL CLibraryTreeCtrl::GetRect(CLibraryTreeItem* pItem, RECT* pRect)
{
CRect rcClient;
GetClientRect( &rcClient );
CPoint pt( rcClient.left, rcClient.top - m_nScroll );
CLibraryTreeItem** pChild = m_pRoot->m_pList;
for ( int nCount = m_pRoot->m_nCount ; nCount ; nCount--, pChild++ )
{
if ( GetRect( pt, *pChild, pItem, pRect ) ) return TRUE;
}
return FALSE;
}
BOOL CLibraryTreeCtrl::GetRect(CPoint& pt, CLibraryTreeItem* pItem, CLibraryTreeItem* pFind, RECT* pRect)
{
if ( pItem == pFind )
{
pRect->left = pt.x;
pRect->top = pt.y;
pRect->right = pt.x;
pRect->bottom = pt.y = pRect->top + ITEM_HEIGHT;
CClientDC dc( this );
CFont* pOld = (CFont*)dc.SelectObject( pItem->m_bBold ?
&CoolInterface.m_fntBold : &CoolInterface.m_fntNormal );
pRect->right += 33 + dc.GetTextExtent( pItem->m_sText ).cx + 4;
dc.SelectObject( pOld );
return TRUE;
}
else
{
pt.y += ITEM_HEIGHT;
}
if ( pItem->m_bExpanded && pItem->m_nCount )
{
pt.x += 16;
CLibraryTreeItem** pChild = pItem->m_pList;
for ( int nCount = pItem->m_nCount ; nCount ; nCount--, pChild++ )
{
if ( GetRect( pt, *pChild, pFind, pRect ) ) return TRUE;
}
pt.x -= 16;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeCtrl drag setup
#define MAX_DRAG_SIZE 256
#define MAX_DRAG_SIZE_2 128
void CLibraryTreeCtrl::StartDragging(CPoint& ptMouse)
{
CImageList* pImage = CreateDragImage( ptMouse );
if ( pImage == NULL ) return;
ReleaseCapture();
ClientToScreen( &ptMouse );
CLibraryFrame* pFrame = (CLibraryFrame*)GetOwner();
CLibraryList* pList = new CLibraryList( m_nSelected );
for ( CLibraryTreeItem* pItem = m_pSelFirst ; pItem ;
pItem = pItem->m_pSelNext )
{
if ( pItem->m_pVirtual ) pList->AddTail( (DWORD)pItem->m_pVirtual );
}
pFrame->DragObjects( pList, pImage, ptMouse );
}
CImageList* CLibraryTreeCtrl::CreateDragImage(const CPoint& ptMouse)
{
CRect rcClient, rcOne, rcAll( 32000, 32000, -32000, -32000 );
GetClientRect( &rcClient );
for ( CLibraryTreeItem* pItem = m_pSelFirst ; pItem ;
pItem = pItem->m_pSelNext )
{
GetRect( pItem, &rcOne );
if ( rcOne.IntersectRect( &rcClient, &rcOne ) )
{
rcAll.left = min( rcAll.left, rcOne.left );
rcAll.top = min( rcAll.top, rcOne.top );
rcAll.right = max( rcAll.right, rcOne.right );
rcAll.bottom = max( rcAll.bottom, rcOne.bottom );
}
}
BOOL bClipped = rcAll.Height() > MAX_DRAG_SIZE;
if ( bClipped )
{
rcAll.left = max( rcAll.left, ptMouse.x - MAX_DRAG_SIZE_2 );
rcAll.right = max( rcAll.right, ptMouse.x + MAX_DRAG_SIZE_2 );
rcAll.top = max( rcAll.top, ptMouse.y - MAX_DRAG_SIZE_2 );
rcAll.bottom = max( rcAll.bottom, ptMouse.y + MAX_DRAG_SIZE_2 );
}
CClientDC dcClient( this );
CDC dcMem, dcDrag;
CBitmap bmDrag;
if ( ! dcMem.CreateCompatibleDC( &dcClient ) )
return NULL;
if ( ! dcDrag.CreateCompatibleDC( &dcClient ) )
return NULL;
if ( ! bmDrag.CreateCompatibleBitmap( &dcClient, rcAll.Width(), rcAll.Height() ) )
return NULL;
CBitmap *pOldDrag = dcDrag.SelectObject( &bmDrag );
dcDrag.FillSolidRect( 0, 0, rcAll.Width(), rcAll.Height(), RGB( 250, 255, 250 ) );
CRgn pRgn;
if ( bClipped )
{
CPoint ptMiddle( ptMouse.x - rcAll.left, ptMouse.y - rcAll.top );
pRgn.CreateEllipticRgn( ptMiddle.x - MAX_DRAG_SIZE_2, ptMiddle.y - MAX_DRAG_SIZE_2,
ptMiddle.x + MAX_DRAG_SIZE_2, ptMiddle.y + MAX_DRAG_SIZE_2 );
dcDrag.SelectClipRgn( &pRgn );
}
CFont* pOldFont = (CFont*)dcDrag.SelectObject( &CoolInterface.m_fntNormal );
for ( pItem = m_pSelFirst ; pItem ; pItem = pItem->m_pSelNext )
{
GetRect( pItem, &rcOne );
CRect rcDummy;
if ( rcDummy.IntersectRect( &rcAll, &rcOne ) )
{
rcOne.OffsetRect( -rcAll.left, -rcAll.top );
pItem->Paint( dcDrag, rcOne, FALSE, RGB( 250, 255, 250 ) );
}
}
dcDrag.SelectObject( pOldFont );
dcDrag.SelectObject( pOldDrag );
dcDrag.DeleteDC();
CImageList* pAll = new CImageList();
pAll->Create( rcAll.Width(), rcAll.Height(), ILC_COLOR16|ILC_MASK, 1, 1 );
pAll->Add( &bmDrag, RGB( 250, 255, 250 ) );
bmDrag.DeleteObject();
pAll->BeginDrag( 0, ptMouse - rcAll.TopLeft() );
return pAll;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeItem construction
CLibraryTreeItem::CLibraryTreeItem(CLibraryTreeItem* pParent)
{
m_pParent = pParent;
m_pList = NULL;
m_nCount = 0;
m_nBuffer = 0;
m_pSelPrev = NULL;
m_pSelNext = NULL;
m_nCleanCookie = 0;
m_bExpanded = FALSE;
m_bSelected = FALSE;
m_bContract1 = FALSE;
m_bContract2 = FALSE;
m_pPhysical = NULL;
m_pVirtual = NULL;
m_nCookie = 0;
m_bBold = FALSE;
m_bShared = TRUE;
m_bCollection = FALSE;
m_nIcon16 = -1;
}
CLibraryTreeItem::~CLibraryTreeItem()
{
if ( m_pList )
{
Clear();
delete [] m_pList;
}
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeItem add
CLibraryTreeItem* CLibraryTreeItem::Add(LPCTSTR pszName)
{
if ( m_nCount == m_nBuffer )
{
if ( m_nBuffer ) m_nBuffer += min( m_nBuffer, 16 ); else m_nBuffer = 4;
CLibraryTreeItem** pList = new CLibraryTreeItem*[ m_nBuffer ];
if ( m_nCount ) CopyMemory( pList, m_pList, m_nCount * 4 );
if ( m_pList ) delete [] m_pList;
m_pList = pList;
}
if ( m_nCount == 0 ) return m_pList[ m_nCount++ ] = new CLibraryTreeItem( this );
for ( int nFirst = 0, nLast = m_nCount - 1 ; nLast >= nFirst ; )
{
int nMiddle = ( nFirst + nLast ) >> 1;
CLibraryTreeItem* pItem = m_pList[ nMiddle ];
if ( _tcsicoll( pszName, pItem->m_sText ) >= 0 )
{
nFirst = nMiddle + 1;
}
else
{
nLast = nMiddle - 1;
}
}
MoveMemory( m_pList + nFirst + 1, m_pList + nFirst, ( m_nCount - nFirst ) << 2 );
m_nCount++;
return m_pList[ nFirst ] = new CLibraryTreeItem( this );
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeItem delete
void CLibraryTreeItem::Delete()
{
m_pParent->Delete( this );
}
void CLibraryTreeItem::Delete(CLibraryTreeItem* pItem)
{
ASSERT( pItem->m_bSelected == FALSE );
CLibraryTreeItem** pChild = m_pList;
for ( int nChild = m_nCount ; nChild ; nChild--, pChild++ )
{
if ( *pChild == pItem )
{
MoveMemory( pChild, pChild + 1, 4 * ( nChild - 1 ) );
m_nCount--;
break;
}
}
delete pItem;
}
void CLibraryTreeItem::Delete(int nItem)
{
if ( nItem < 0 || nItem >= m_nCount ) return;
ASSERT( m_pList[ nItem ]->m_bSelected == FALSE );
delete m_pList[ nItem ];
MoveMemory( m_pList + nItem, m_pList + nItem + 1, 4 * ( m_nCount - nItem - 1 ) );
m_nCount--;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeItem clear
void CLibraryTreeItem::Clear()
{
if ( m_pList )
{
for ( int nChild = 0 ; nChild < m_nCount ; nChild++ ) delete m_pList[ nChild ];
delete [] m_pList;
}
m_pList = NULL;
m_nCount = 0;
m_nBuffer = 0;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeItem visibility
BOOL CLibraryTreeItem::IsVisible() const
{
for ( CLibraryTreeItem* pRoot = m_pParent ; pRoot ; pRoot = pRoot->m_pParent )
{
if ( ! pRoot->m_bExpanded ) return FALSE;
}
return TRUE;
}
int CLibraryTreeItem::GetChildCount() const
{
int nCount = m_nCount;
CLibraryTreeItem** pChild = m_pList;
for ( int nChild = m_nCount ; nChild ; nChild--, pChild++ )
{
if ( (*pChild)->m_bExpanded ) nCount += (*pChild)->GetChildCount();
}
return nCount;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeItem paint
void CLibraryTreeItem::Paint(CDC& dc, CRect& rc, BOOL bTarget, COLORREF crBack) const
{
if ( crBack == CLR_NONE ) crBack = CoolInterface.m_crWindow;
if ( m_nCount )
{
ImageList_DrawEx( ShellIcons.GetHandle( 16 ),
m_bExpanded ? SHI_MINUS : SHI_PLUS,
dc.GetSafeHdc(), rc.left, rc.top, 16, 16,
crBack, CLR_NONE, ILD_NORMAL );
}
else
{
dc.FillSolidRect( rc.left, rc.top, 16, 16, crBack );
}
int nImage = ( m_bExpanded && m_nCount ) ? SHI_FOLDER_OPEN : SHI_FOLDER_CLOSED;
if ( m_nIcon16 >= 0 ) nImage = m_nIcon16;
UINT nIconStyle = ( m_bSelected || bTarget ) ? ILD_SELECTED : ILD_NORMAL;
if ( ! m_bShared ) nIconStyle |= INDEXTOOVERLAYMASK( SHI_O_LOCKED );
if ( m_bCollection ) nIconStyle |= INDEXTOOVERLAYMASK( SHI_O_COLLECTION );
ImageList_DrawEx( ShellIcons.GetHandle( 16 ), nImage,
dc.GetSafeHdc(), rc.left + 16, rc.top, 16, 16,
crBack, CLR_DEFAULT, nIconStyle );
crBack = ( m_bSelected || bTarget ) ? CoolInterface.m_crHighlight : crBack;
COLORREF crText = ( m_bSelected || bTarget ) ? CoolInterface.m_crHiText : CoolInterface.m_crText;
dc.SetTextColor( crText );
dc.SetBkColor( crBack );
dc.SetBkMode( OPAQUE );
rc.left += 32;
dc.ExtTextOut( rc.left + 3, rc.top + 1, ETO_OPAQUE|ETO_CLIPPED, &rc,
m_sText, NULL );
rc.left -= 32;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryTreeItem get child files
int CLibraryTreeItem::GetFileList(CLibraryList* pList, BOOL bRecursive) const
{
if ( LibraryFolders.CheckFolder( m_pPhysical, TRUE ) )
{
return m_pPhysical->GetFileList( pList, bRecursive );
}
else if ( LibraryFolders.CheckAlbum( m_pVirtual ) )
{
return m_pVirtual->GetFileList( pList, bRecursive );
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -