⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctrllibrarythumbview.cpp

📁 p2p软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:

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 + -