📄 ctrlbrowsetree.cpp
字号:
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 CBrowseTreeCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
ScrollBy( zDelta * 3 * -ITEM_HEIGHT / WHEEL_DELTA );
return TRUE;
}
void CBrowseTreeCtrl::ScrollBy(int nDelta)
{
ScrollTo( max( 0, m_nScroll + nDelta ) );
}
void CBrowseTreeCtrl::ScrollTo(int nPosition)
{
if ( nPosition == m_nScroll ) return;
m_nScroll = nPosition;
UpdateScroll();
CRect rc;
GetClientRect( &rc );
RedrawWindow( &rc, NULL, RDW_INVALIDATE );
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeCtrl painting
BOOL CBrowseTreeCtrl::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CBrowseTreeCtrl::OnPaint()
{
CPaintDC dc( this );
CRect rcClient;
GetClientRect( &rcClient );
CPoint pt( rcClient.left, rcClient.top - m_nScroll );
CBrowseTreeItem** 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 CBrowseTreeCtrl::Paint(CDC& dc, CRect& rcClient, CPoint& pt, CBrowseTreeItem* 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, FALSE );
dc.ExcludeClipRect( &rc );
}
if ( pItem->m_bBold ) dc.SelectObject( &CoolInterface.m_fntNormal );
}
if ( pItem->m_bExpanded && pItem->m_nCount )
{
pt.x += 16;
CBrowseTreeItem** 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;
}
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeCtrl hit testing
CBrowseTreeItem* CBrowseTreeCtrl::HitTest(const POINT& point, RECT* pRect) const
{
CRect rcClient;
GetClientRect( &rcClient );
CPoint pt( rcClient.left, rcClient.top - m_nScroll );
CBrowseTreeItem** pChild = m_pRoot->m_pList;
for ( int nCount = m_pRoot->m_nCount ; nCount && pt.y < rcClient.bottom ; nCount--, pChild++ )
{
CBrowseTreeItem* pItem = HitTest( rcClient, pt, *pChild, point, pRect );
if ( pItem ) return pItem;
}
return NULL;
}
CBrowseTreeItem* CBrowseTreeCtrl::HitTest(CRect& rcClient, CPoint& pt, CBrowseTreeItem* 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;
CBrowseTreeItem** pChild = pItem->m_pList;
for ( int nCount = pItem->m_nCount ; nCount ; nCount--, pChild++ )
{
CBrowseTreeItem* pItem = HitTest( rcClient, pt, *pChild, point, pRect );
if ( pItem ) return pItem;
if ( pt.y >= rcClient.bottom + ITEM_HEIGHT ) break;
}
pt.x -= 16;
}
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeCtrl rect lookup
BOOL CBrowseTreeCtrl::GetRect(CBrowseTreeItem* pItem, RECT* pRect)
{
CRect rcClient;
GetClientRect( &rcClient );
CPoint pt( rcClient.left, rcClient.top - m_nScroll );
CBrowseTreeItem** 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 CBrowseTreeCtrl::GetRect(CPoint& pt, CBrowseTreeItem* pItem, CBrowseTreeItem* 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;
CBrowseTreeItem** 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;
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeCtrl virtual tree
void CBrowseTreeCtrl::OnTreePacket(CG2Packet* pPacket)
{
BOOL bNotify = m_nSelected != 0;
Clear();
pPacket->Seek( 0 );
OnTreePacket( pPacket, pPacket->m_nLength, m_pRoot );
m_nTotal = m_pRoot->GetChildCount();
Invalidate();
if ( bNotify ) NotifySelection();
}
void CBrowseTreeCtrl::OnTreePacket(CG2Packet* pPacket, DWORD nFinish, CBrowseTreeItem* pItem)
{
BOOL bCompound;
CHAR szType[9];
DWORD nLength;
while ( pPacket->m_nPosition < nFinish &&
pPacket->ReadPacket( szType, nLength, &bCompound ) )
{
DWORD nNext = pPacket->m_nPosition + nLength;
if ( ( strcmp( szType, "PF" ) == 0 || strcmp( szType, "VF" ) == 0 ) && bCompound == TRUE )
{
CBrowseTreeItem* pChild = new CBrowseTreeItem( pItem );
OnTreePacket( pPacket, nNext, pChild );
pChild->m_bExpanded = ( pItem == m_pRoot );
pItem->Add( pChild );
}
else if ( strcmp( szType, "DN" ) == 0 && bCompound == FALSE )
{
pItem->m_sText = pPacket->ReadString( nLength );
}
else if ( strcmp( szType, "MD" ) == 0 && bCompound == FALSE )
{
CXMLElement* pXML = CXMLElement::FromString( pPacket->ReadString( nLength ) );
if ( pXML != NULL ) pItem->AddXML( pXML );
}
else if ( strcmp( szType, "FILES" ) == 0 && bCompound == FALSE )
{
if ( pItem->m_pFiles != NULL ) delete [] pItem->m_pFiles;
pItem->m_nFiles = nLength / 4;
pItem->m_pFiles = new DWORD[ pItem->m_nFiles ];
for ( DWORD nCount = pItem->m_nFiles ; nCount ; nCount-- )
{
pItem->m_pFiles[ nCount - 1 ] = pPacket->ReadLongBE();
}
}
pPacket->m_nPosition = nNext;
}
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeItem construction
CBrowseTreeItem::CBrowseTreeItem(CBrowseTreeItem* 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_nCookie = 0;
m_bBold = FALSE;
m_nIcon16 = -1;
m_pSchema = NULL;
m_pFiles = NULL;
m_nFiles = 0;
}
CBrowseTreeItem::~CBrowseTreeItem()
{
if ( m_pFiles != NULL )
{
delete [] m_pFiles;
}
if ( m_pList != NULL )
{
Clear();
delete [] m_pList;
}
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeItem add
CBrowseTreeItem* CBrowseTreeItem::Add(LPCTSTR pszName)
{
if ( m_nCount == m_nBuffer )
{
if ( m_nBuffer ) m_nBuffer += min( m_nBuffer, 16 ); else m_nBuffer = 4;
CBrowseTreeItem** pList = new CBrowseTreeItem*[ 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 CBrowseTreeItem( this );
for ( int nFirst = 0, nLast = m_nCount - 1 ; nLast >= nFirst ; )
{
int nMiddle = ( nFirst + nLast ) >> 1;
CBrowseTreeItem* 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 CBrowseTreeItem( this );
}
CBrowseTreeItem* CBrowseTreeItem::Add(CBrowseTreeItem* pNewItem)
{
if ( m_nCount == m_nBuffer )
{
if ( m_nBuffer ) m_nBuffer += min( m_nBuffer, 16 ); else m_nBuffer = 4;
CBrowseTreeItem** pList = new CBrowseTreeItem*[ 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++ ] = pNewItem;
for ( int nFirst = 0, nLast = m_nCount - 1 ; nLast >= nFirst ; )
{
int nMiddle = ( nFirst + nLast ) >> 1;
CBrowseTreeItem* pItem = m_pList[ nMiddle ];
if ( _tcsicoll( pNewItem->m_sText, 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 ] = pNewItem;
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeItem delete
void CBrowseTreeItem::Delete()
{
m_pParent->Delete( this );
}
void CBrowseTreeItem::Delete(CBrowseTreeItem* pItem)
{
ASSERT( pItem->m_bSelected == FALSE );
CBrowseTreeItem** 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 CBrowseTreeItem::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--;
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeItem clear
void CBrowseTreeItem::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;
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeItem visibility
BOOL CBrowseTreeItem::IsVisible() const
{
for ( CBrowseTreeItem* pRoot = m_pParent ; pRoot ; pRoot = pRoot->m_pParent )
{
if ( ! pRoot->m_bExpanded ) return FALSE;
}
return TRUE;
}
int CBrowseTreeItem::GetChildCount() const
{
int nCount = m_nCount;
CBrowseTreeItem** pChild = m_pList;
for ( int nChild = m_nCount ; nChild ; nChild--, pChild++ )
{
if ( (*pChild)->m_bExpanded ) nCount += (*pChild)->GetChildCount();
}
return nCount;
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeItem paint
void CBrowseTreeItem::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;
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;
}
/////////////////////////////////////////////////////////////////////////////
// CBrowseTreeItem add XML
void CBrowseTreeItem::AddXML(CXMLElement* pXML)
{
CString strURI = pXML->GetAttributeValue( CXMLAttribute::schemaName );
if ( m_pSchema = SchemaCache.Get( strURI ) )
{
m_bBold = strURI == CSchema::uriFavouritesFolder;
m_nIcon16 = m_pSchema->m_nIcon16;
if ( CXMLElement* pBody = pXML->GetFirstElement() )
{
m_sText = pBody->GetAttributeValue( m_pSchema->GetFirstMemberName() );
}
}
if ( m_sText.IsEmpty() ) m_sText = _T("Unnamed");
if ( pXML != NULL ) delete pXML;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -