📄 ctrllibrarythumbview.cpp
字号:
CLibraryThumbItem* CLibraryThumbView::HitTest(const CPoint& point) const
{
CRect rcClient;
GetClientRect( &rcClient );
CPoint pt( rcClient.left, rcClient.top - m_nScroll );
CLibraryThumbItem** pList = m_pList;
for ( int nItem = m_nCount ; nItem && pt.y < rcClient.bottom ; nItem--, pList++ )
{
CLibraryThumbItem* pThumb = *pList;
CRect rcBlock( pt.x, pt.y, pt.x + m_szBlock.cx, pt.y + m_szBlock.cy );
if ( rcBlock.PtInRect( point ) ) return pThumb;
pt.x += m_szBlock.cx;
if ( pt.x + m_szBlock.cx > rcClient.right )
{
pt.x = rcClient.left;
pt.y += m_szBlock.cy;
}
}
return NULL;
}
BOOL CLibraryThumbView::GetItemRect(CLibraryThumbItem* pThumb, CRect* pRect)
{
CRect rcClient;
GetClientRect( &rcClient );
CPoint pt( rcClient.left, rcClient.top - m_nScroll );
CLibraryThumbItem** pList = m_pList;
for ( int nItem = m_nCount ; nItem ; nItem--, pList++ )
{
CRect rcBlock( pt.x, pt.y, pt.x + m_szBlock.cx, pt.y + m_szBlock.cy );
if ( pThumb == *pList )
{
*pRect = rcBlock;
return TRUE;
}
pt.x += m_szBlock.cx;
if ( pt.x + m_szBlock.cx > rcClient.right )
{
pt.x = rcClient.left;
pt.y += m_szBlock.cy;
}
}
return FALSE;
}
void CLibraryThumbView::OnLButtonDown(UINT nFlags, CPoint point)
{
CLibraryThumbItem* pHit = HitTest( point );
if ( SelectTo( pHit ) ) Invalidate();
SetFocus();
SetCapture();
if ( pHit && ( nFlags & MK_RBUTTON ) == 0 )
{
m_bDrag = TRUE;
m_ptDrag = point;
}
CLibraryFileView::OnLButtonDown( nFlags, point );
}
void CLibraryThumbView::OnMouseMove(UINT nFlags, CPoint point)
{
if ( m_bDrag & ( nFlags & MK_LBUTTON ) )
{
CSize szDiff = point - m_ptDrag;
if ( abs( szDiff.cx ) > 5 || abs( szDiff.cy ) > 5 )
{
m_bDrag = FALSE;
StartDragging( point );
}
}
CLibraryFileView::OnMouseMove( nFlags, point );
}
void CLibraryThumbView::OnLButtonUp(UINT nFlags, CPoint point)
{
ReleaseCapture();
m_bDrag = FALSE;
if ( ( nFlags & (MK_SHIFT|MK_CONTROL) ) == 0 && m_pFocus && m_pFocus->m_bSelected )
{
if ( DeselectAll( m_pFocus ) ) Invalidate();
}
}
void CLibraryThumbView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
SendMessage( WM_COMMAND, ID_LIBRARY_LAUNCH );
}
void CLibraryThumbView::OnRButtonDown(UINT nFlags, CPoint point)
{
OnLButtonDown( nFlags, point );
CLibraryFileView::OnRButtonDown( nFlags, point );
}
void CLibraryThumbView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch ( nChar )
{
case VK_LEFT:
SelectTo( - 1 );
break;
case VK_RIGHT:
SelectTo( 1 );
break;
case VK_UP:
SelectTo( -m_nColumns );
break;
case VK_DOWN:
SelectTo( m_nColumns );
break;
case VK_PRIOR:
SelectTo( m_nRows * -m_nColumns );
break;
case VK_NEXT:
SelectTo( m_nRows * m_nColumns );
break;
case VK_HOME:
SelectTo( -m_nCount );
break;
case VK_END:
SelectTo( m_nCount );
break;
}
CLibraryFileView::OnKeyDown( nChar, nRepCnt, nFlags );
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryThumbView drag setup
#define MAX_DRAG_SIZE 256
#define MAX_DRAG_SIZE_2 128
void CLibraryThumbView::StartDragging(CPoint& ptMouse)
{
CSingleLock pLock( &m_pSection, TRUE );
CImageList* pImage = CreateDragImage( ptMouse );
if ( ! pImage ) return;
ReleaseCapture();
ClientToScreen( &ptMouse );
DragObjects( pImage, ptMouse );
}
CImageList* CLibraryThumbView::CreateDragImage(const CPoint& ptMouse)
{
CRect rcClient, rcOne, rcAll( 32000, 32000, -32000, -32000 );
GetClientRect( &rcClient );
for ( POSITION pos = m_pSelThumb.GetHeadPosition() ; pos ; )
{
CLibraryThumbItem* pThumb = (CLibraryThumbItem*)m_pSelThumb.GetNext( pos );
GetItemRect( pThumb, &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( 0, 255, 0 ) );
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 );
}
CDC* pBuffer = CoolInterface.GetBuffer( dcClient, m_szBlock );
CRect rcBuffer( 0, 0, m_szBlock.cx, m_szBlock.cy );
CFont* pOldFont = (CFont*)pBuffer->SelectObject( &CoolInterface.m_fntNormal );
for ( pos = m_pSelThumb.GetHeadPosition() ; pos ; )
{
CLibraryThumbItem* pThumb = (CLibraryThumbItem*)m_pSelThumb.GetNext( pos );
GetItemRect( pThumb, &rcOne );
CRect rcDummy;
if ( rcDummy.IntersectRect( &rcAll, &rcOne ) )
{
pBuffer->FillSolidRect( &rcBuffer, RGB( 0, 255, 0 ) );
pThumb->Paint( pBuffer, rcBuffer, m_szThumb, &dcMem );
dcDrag.BitBlt( rcOne.left - rcAll.left, rcOne.top - rcAll.top,
m_szBlock.cx, m_szBlock.cy, pBuffer, 0, 0, SRCCOPY );
}
}
pBuffer->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( 0, 255, 0 ) );
bmDrag.DeleteObject();
pAll->BeginDrag( 0, ptMouse - rcAll.TopLeft() );
return pAll;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryThumbView thread builder
void CLibraryThumbView::StartThread()
{
if ( m_hThread != NULL && m_bThread ) return;
CSingleLock pLock( &m_pSection, TRUE );
CLibraryThumbItem** pList = m_pList;
int nCount = 0;
for ( int nItem = m_nCount ; nItem ; nItem--, pList++ )
{
if ( (*pList)->m_nThumb == CLibraryThumbItem::thumbWaiting ) nCount++;
}
if ( nCount == 0 ) return;
m_bThread = TRUE;
CWinThread* pThread = AfxBeginThread( ThreadStart, this, THREAD_PRIORITY_IDLE );
m_hThread = pThread->m_hThread;
}
void CLibraryThumbView::StopThread()
{
if ( m_hThread == NULL ) return;
m_bThread = FALSE;
for ( int nAttempt = 100 ; nAttempt > 0 ; nAttempt-- )
{
DWORD nCode;
if ( ! GetExitCodeThread( m_hThread, &nCode ) ) break;
if ( nCode != STILL_ACTIVE ) break;
Sleep( 100 );
}
if ( nAttempt == 0 )
{
TerminateThread( m_hThread, 0 );
theApp.Message( MSG_DEBUG, _T("WARNING: Terminating CLibraryThumbView thread.") );
Sleep( 100 );
}
m_hThread = NULL;
}
UINT CLibraryThumbView::ThreadStart(LPVOID pParam)
{
CLibraryThumbView* pView = (CLibraryThumbView*)pParam;
pView->OnRun();
return 0;
}
void CLibraryThumbView::OnRun()
{
CSingleLock pLock( &m_pSection );
CImageServices pServices;
CThumbCache pCache;
while ( m_bThread )
{
CLibraryThumbItem* pThumb = NULL;
DWORD nIndex = 0;
CString strPath;
BOOL bCache;
pLock.Lock();
CLibraryThumbItem** pList = m_pList;
for ( int nItem = m_nCount ; nItem ; nItem--, pList++ )
{
if ( (*pList)->m_nThumb == CLibraryThumbItem::thumbWaiting )
{
if ( CLibraryFile* pFile = Library.LookupFile( (*pList)->m_nIndex, TRUE ) )
{
pThumb = *pList;
nIndex = pFile->m_nIndex;
strPath = pFile->GetPath();
bCache = pFile->m_bCachedPreview;
Library.Unlock();
break;
}
}
}
pLock.Unlock();
if ( pThumb == NULL ) break;
pThumb = NULL;
DWORD tNow = GetTickCount();
CImageFile pFile( &pServices );
BOOL bSuccess = FALSE;
if ( pCache.Load( strPath, &m_szThumb, nIndex, &pFile ) )
{
bSuccess = TRUE;
}
else if ( pFile.LoadFromFile( strPath, FALSE, TRUE ) && pFile.EnsureRGB() )
{
int nSize = m_szThumb.cy * pFile.m_nWidth / pFile.m_nHeight;
if ( ! m_bThread ) break;
if ( nSize > m_szThumb.cx )
{
nSize = m_szThumb.cx * pFile.m_nHeight / pFile.m_nWidth;
pFile.Resample( m_szThumb.cx, nSize );
}
else
{
pFile.Resample( nSize, m_szThumb.cy );
}
if ( ! m_bThread ) break;
pCache.Store( strPath, &m_szThumb, nIndex, &pFile );
bSuccess = TRUE;
}
pLock.Lock();
pList = m_pList;
for ( nItem = m_nCount ; nItem ; nItem--, pList++ )
{
if ( (*pList)->m_nIndex == nIndex )
{
pThumb = *pList;
break;
}
}
if ( pThumb )
{
if ( pThumb->m_bmThumb.m_hObject ) pThumb->m_bmThumb.DeleteObject();
if ( bSuccess )
{
pThumb->m_bmThumb.Attach( pFile.CreateBitmap() );
pThumb->m_szThumb.cx = pFile.m_nWidth;
pThumb->m_szThumb.cy = pFile.m_nHeight;
pThumb->m_nThumb = CLibraryThumbItem::thumbValid;
}
else
{
pThumb->m_nThumb = CLibraryThumbItem::thumbError;
}
m_nInvalidate++;
}
pLock.Unlock();
if ( bSuccess && ! bCache )
{
if ( CLibraryFile* pFile = Library.LookupFile( nIndex, TRUE ) )
{
pFile->m_bCachedPreview = TRUE;
Library.Unlock();
}
}
if ( ! m_bRush )
{
DWORD tDelay = GetTickCount() - tNow;
if ( tDelay > 400 ) tDelay = 400;
if ( tDelay < 20 ) tDelay = 20;
while ( tDelay && m_bThread )
{
DWORD tNow = min( tDelay, 50 );
tDelay -= tNow;
Sleep( tNow );
}
}
}
pServices.Cleanup();
m_bThread = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryThumbItem construction
CLibraryThumbItem::CLibraryThumbItem(CLibraryFile* pFile)
{
m_nIndex = pFile->m_nIndex;
m_nCookie = pFile->m_nUpdateCookie;
m_sText = pFile->m_sName;
m_bShared = pFile->IsShared();
m_bSelected = FALSE;
m_nThumb = 0;
m_nShell = ShellIcons.Get( m_sText, THUMB_ICON );
}
CLibraryThumbItem::~CLibraryThumbItem()
{
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryThumbItem operations
BOOL CLibraryThumbItem::Update(CLibraryFile* pFile)
{
BOOL bShared = pFile->IsShared();
if ( m_nCookie == pFile->m_nUpdateCookie && m_bShared == bShared ) return FALSE;
m_nCookie = pFile->m_nUpdateCookie;
m_sText = pFile->m_sName;
m_bShared = bShared;
m_nThumb = thumbWaiting;
if ( m_bmThumb.m_hObject ) m_bmThumb.DeleteObject();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryThumbItem paint
void CLibraryThumbItem::Paint(CDC* pDC, const CRect& rcBlock, const CSize& szThumb, CDC* pMemDC)
{
CRect rcThumb;
rcThumb.left = ( rcBlock.left + rcBlock.right ) / 2 - szThumb.cx / 2;
rcThumb.right = rcThumb.left + szThumb.cx;
rcThumb.top = rcBlock.top + 7;
rcThumb.bottom = rcThumb.top + szThumb.cy;
CRect rcFrame( &rcThumb );
if ( m_bSelected )
{
for ( int nBorder = 3 ; nBorder ; nBorder-- )
{
rcFrame.InflateRect( 1, 1 );
pDC->Draw3dRect( &rcFrame, CoolInterface.m_crHighlight, CoolInterface.m_crHighlight );
}
}
else
{
rcFrame.InflateRect( 1, 1 );
pDC->Draw3dRect( &rcFrame, CoolInterface.m_crMargin, CoolInterface.m_crMargin );
}
if ( m_bmThumb.m_hObject != NULL )
{
pMemDC->SelectObject( &m_bmThumb );
CPoint ptImage( ( rcThumb.left + rcThumb.right ) / 2 - m_szThumb.cx / 2,
( rcThumb.top + rcThumb.bottom ) / 2 - m_szThumb.cy / 2 );
pDC->BitBlt( ptImage.x, ptImage.y, m_szThumb.cx, m_szThumb.cy,
pMemDC, 0, 0, SRCCOPY );
}
else
{
if ( m_nThumb == thumbWaiting )
pDC->FillSolidRect( &rcThumb, RGB( 255, 255, 255 ) );
else
pDC->FillSolidRect( &rcThumb, CoolInterface.m_crBackNormal );
ImageList_DrawEx( ShellIcons.GetHandle( THUMB_ICON ), m_nShell, pDC->GetSafeHdc(),
( rcThumb.left + rcThumb.right ) / 2 - THUMB_ICON / 2,
( rcThumb.top + rcThumb.bottom ) / 2 - THUMB_ICON / 2,
THUMB_ICON, THUMB_ICON, CLR_NONE, CLR_NONE, ILD_NORMAL );
}
if ( m_bSelected )
{
pDC->SetBkColor( CoolInterface.m_crHighlight );
pDC->SetTextColor( CoolInterface.m_crHiText );
}
else if ( ! m_bShared )
{
pDC->SetBkColor( CoolInterface.m_crWindow );
pDC->SetTextColor( CoolInterface.m_crHighlight );
}
else
{
pDC->SetBkColor( CoolInterface.m_crWindow );
pDC->SetTextColor( CoolInterface.m_crText );
}
rcThumb.top = rcThumb.bottom + 4;
rcThumb.bottom = rcThumb.top + 27;
rcThumb.left -= 3;
rcThumb.right += 3;
CSize szText = pDC->GetTextExtent( m_sText );
if ( szText.cx < rcThumb.Width() - 4 )
{
rcThumb.left = ( rcThumb.left + rcThumb.right ) / 2 - szText.cx / 2 - 2;
rcThumb.right = rcThumb.left + szText.cx + 4;
rcThumb.bottom = rcThumb.top + szText.cy + 2;
pDC->FillSolidRect( &rcThumb, pDC->GetBkColor() );
pDC->ExtTextOut( rcThumb.left + 2, rcThumb.top, ETO_CLIPPED|ETO_OPAQUE,
&rcThumb, m_sText, NULL );
}
else
{
int nSaveX = rcThumb.right;
int nSaveY = rcThumb.bottom;
int nHeight = pDC->DrawText( m_sText, &rcThumb, DT_CENTER|DT_WORDBREAK|DT_CALCRECT|DT_NOPREFIX );
rcThumb.bottom = min( nSaveY, rcThumb.top + nHeight + 2 );
rcThumb.right = nSaveX;
pDC->FillSolidRect( &rcThumb, pDC->GetBkColor() );
pDC->DrawText( m_sText, &rcThumb, DT_CENTER|DT_WORDBREAK|DT_NOPREFIX );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -