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

📄 ctrlsearchdetailpanel.cpp

📁 p2p软件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	
	CRect rcThumb( rcClient.left + 8, rcClient.top + 8,
		rcClient.left + 8 + nThumbSize, rcClient.top + 8 + nThumbSize );
	
	rcWork.CopyRect( &rcThumb );
	
	pDC->Draw3dRect( &rcWork, CoolInterface.m_crMargin, CoolInterface.m_crMargin );
	rcWork.DeflateRect( 1, 1 );
	m_nThumbSize = rcWork.Width();
	
	DrawThumbnail( pDC, rcWork );
	
	pDC->ExcludeClipRect( &rcThumb );
	
	rcWork.SetRect( rcThumb.right + 8, rcThumb.top, rcClient.right - 8, rcClient.bottom );
}

void CSearchDetailPanel::DrawThumbnail(CDC* pDC, CRect& rcThumb)
{
	m_rcThumb = rcThumb;
	
	if ( m_bmThumb.m_hObject != NULL &&
		 m_szThumb.cx != m_nThumbSize && m_szThumb.cy != m_nThumbSize )
	{
		CSingleLock pLock( &m_pMatches->m_pSection, TRUE );
		
		if ( m_pMatches->FileToItem( m_pFile ) < 0xFFFFFFFF )
		{
			if ( m_pFile->m_pPreview != NULL && m_pFile->m_nPreview > 0 )
			{
				CImageServices pServices;
				CImageFile pImage( &pServices );
				
				if ( pImage.LoadFromMemory( _T(".jpg"), (LPCVOID)m_pFile->m_pPreview, m_pFile->m_nPreview, FALSE, TRUE ) )
				{
					pLock.Unlock();
					OnPreviewLoaded( &m_pSHA1, &pImage );
				}
			}
		}
	}
	
	if ( m_bmThumb.m_hObject &&
			( m_szThumb.cx == m_nThumbSize || m_szThumb.cy == m_nThumbSize ) )
	{
		CDC dcMem;
		dcMem.CreateCompatibleDC( pDC );
		
		CBitmap* pOld = (CBitmap*)dcMem.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,
			&dcMem, 0, 0, SRCCOPY );
		pDC->ExcludeClipRect( ptImage.x, ptImage.y,
			ptImage.x + m_szThumb.cx, ptImage.y + m_szThumb.cy );
		
		dcMem.SelectObject( pOld );
		
		pDC->FillSolidRect( &rcThumb, m_crLight );
	}
	else
	{
		CPoint pt(	( rcThumb.left + rcThumb.right ) / 2 - 24,
					( rcThumb.top + rcThumb.bottom ) / 2 - 24 );
		
		if ( m_bCanPreview )
		{
			CString str;
			LoadString( str, m_bIsPreviewing ? IDS_SEARCH_DETAILS_PREVIEWING : IDS_SEARCH_DETAILS_PREVIEW );
			
			pDC->SetBkColor( m_crLight );
			pDC->SetTextColor( m_bIsPreviewing ? RGB( 255, 0, 0 ) : RGB( 0, 0, 255 ) );
			pDC->SelectObject( m_bIsPreviewing ? &theApp.m_gdiFontBold : &theApp.m_gdiFontLine );
			
			CSize sz = pDC->GetTextExtent( str );
			
			if ( sz.cx + 4 < rcThumb.Width() )
			{
				pt.y -= sz.cy / 2;
				CPoint ptText(
					( rcThumb.left + rcThumb.right ) / 2 - sz.cx / 2,
					pt.y + 50 );
				DrawText( pDC, ptText.x, ptText.y, str );
			}
		}
		
		if ( m_nIcon48 >= 0 )
		{
			ShellIcons.Draw( pDC, m_nIcon48, 48, pt.x, pt.y, m_crLight );
		}
		else if ( m_nIcon32 >= 0 )
		{
			pt.x += 8; pt.y += 8;
			ShellIcons.Draw( pDC, m_nIcon32, 32, pt.x, pt.y, m_crLight );
		}
		
		pDC->FillSolidRect( &rcThumb, m_crLight );
	}
}

BOOL CSearchDetailPanel::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	CPoint point;
	
	GetCursorPos( &point );
	ScreenToClient( &point );
	
	if ( m_bValid && m_bCanPreview && ! m_bIsPreviewing && m_rcThumb.PtInRect( point ) )
	{
		SetCursor( AfxGetApp()->LoadCursor( IDC_HAND ) );
		return TRUE;
	}
	
	point.y += GetScrollPos( SB_VERT );
	
	if ( m_bValid && m_pReviews.GetCount() > 0 && m_rcStatus.PtInRect( point ) )
	{
		SetCursor( AfxGetApp()->LoadCursor( IDC_HAND ) );
		return TRUE;
	}
	
	if ( m_bValid && m_pMetadata.HitTest( point, TRUE ) != NULL )
	{
		SetCursor( AfxGetApp()->LoadCursor( IDC_HAND ) );
		return TRUE;
	}
	
	return CWnd::OnSetCursor( pWnd, nHitTest, message );
}

void CSearchDetailPanel::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if ( m_bValid && m_bCanPreview && ! m_bIsPreviewing && m_rcThumb.PtInRect( point ) )
	{
		RequestPreview();
	}
	
	point.y += GetScrollPos( SB_VERT );
	
	if ( m_bValid && m_pReviews.GetCount() > 0 && m_rcStatus.PtInRect( point ) )
	{
		int nHeight = 54 + m_pMetadata.m_nHeight;
		SetScrollPos( SB_VERT, nHeight );
		OnVScroll( SB_THUMBPOSITION, nHeight, NULL );
		Invalidate();
	}
	
	m_pMetadata.OnClick( point );
	
	CWnd::OnLButtonUp( nFlags, point );
}

/////////////////////////////////////////////////////////////////////////////
// CSearchDetailPanel::Review construction

CSearchDetailPanel::Review::Review(GGUID* pGUID, IN_ADDR* pAddress, LPCTSTR pszNick, int nRating, LPCTSTR pszComments)
{
	m_pGUID		= *pGUID;
	m_nRating	= nRating;
	
	if ( pszNick != NULL && *pszNick != 0 )
	{
		m_sNick.Format( _T("%s (%s)"), pszNick,
			(LPCTSTR)CString( inet_ntoa( *pAddress ) ) );
	}
	else
	{
		m_sNick = inet_ntoa( *pAddress );
	}
	
	if ( pszComments != NULL )
	{
		m_pComments.m_szMargin = CSize( 6, 0 );
		Emoticons.FormatText( &m_pComments, pszComments, TRUE );
	}
}

CSearchDetailPanel::Review::~Review()
{
	if ( m_wndComments.m_hWnd != NULL ) m_wndComments.DestroyWindow();
}

void CSearchDetailPanel::Review::Layout(CSearchDetailPanel* pParent, CRect* pRect)
{
	pRect->bottom += 22;
	
	if ( m_pComments.GetCount() )
	{
		if ( m_wndComments.m_hWnd == NULL )
		{
			m_wndComments.Create( WS_CHILD, *pRect, pParent, IDC_REVIEW_VIEW );
			m_wndComments.SetSelectable( TRUE );
			m_wndComments.SetDocument( &m_pComments );
		}
		
		pRect->bottom += m_wndComments.FullHeightMove( pRect->left, pRect->bottom, pRect->Width(), TRUE );
		pRect->bottom += 4;
	}
	else
	{
		pRect->bottom += 2;
	}
	
	m_rc.CopyRect( pRect );
}

void CSearchDetailPanel::Review::Reposition(int nScroll)
{
	if ( m_wndComments.m_hWnd != NULL )
	{
		m_wndComments.SetWindowPos( NULL, m_rc.left, m_rc.top - nScroll + 22, 0, 0,
			SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE );
	}
}

void CSearchDetailPanel::Review::Paint(CDC* pDC, int nScroll)
{
	CRect rc( &m_rc );
	rc.OffsetRect( 0, -nScroll );
	
	pDC->FillSolidRect( rc.left, rc.top, rc.Width(), 1, CoolInterface.m_crMargin );
	pDC->ExcludeClipRect( rc.left, rc.top, rc.right, rc.top + 1 );
	rc.top += 4;
	
	CString strFormat, strCaption;
	
	LoadString( strFormat, m_pComments.GetCount() > 0 ? IDS_SEARCH_DETAILS_WRITES : IDS_SEARCH_DETAILS_RATES );
	strCaption.Format( strFormat, (LPCTSTR)m_sNick );
	
	pDC->SetBkColor( CoolInterface.m_crWindow );
	DrawText( pDC, rc.left, rc.top, strCaption );
	
	CPoint ptStar( rc.right - 3, rc.top );
	
	if ( m_nRating > 1 )
	{
		for ( int nRating = m_nRating - 1 ; nRating ; nRating-- )
		{
			ptStar.x -= 16;
			ShellIcons.Draw( pDC, SHI_STAR, 16, ptStar.x, ptStar.y, CoolInterface.m_crWindow );
		}
	}
	else if ( m_nRating == 1 )
	{
		ptStar.x -= 16;
		ShellIcons.Draw( pDC, SHI_FAKE, 16, ptStar.x, ptStar.y, CoolInterface.m_crWindow );
	}
	
	rc.top += 20;
}

void CSearchDetailPanel::OnClickReview(RVN_ELEMENTEVENT* pNotify, LRESULT *pResult)
{
	if ( CRichElement* pElement = pNotify->pElement )
	{
		theApp.InternalURI( pElement->m_sLink );
	}
}

/////////////////////////////////////////////////////////////////////////////
// CSearchDetailPanel previewing functionality

BOOL CSearchDetailPanel::RequestPreview()
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	if ( ! m_bValid || ! m_bCanPreview || m_pPreviewURLs.IsEmpty() ) return FALSE;
	
	if ( m_hThread == NULL )
	{
		m_bThread = TRUE;
		CWinThread* pThread = AfxBeginThread( ThreadStart, this, THREAD_PRIORITY_IDLE );
		m_hThread = pThread->m_hThread;
	}
	
	m_bRunPreview = TRUE;
	
	pLock.Unlock();
	
	m_pWakeup.SetEvent();
	
	return TRUE;
}

void CSearchDetailPanel::CancelPreview()
{
	CSingleLock pLock( &m_pSection, TRUE );
	
	m_bRunPreview = FALSE;
	m_pPreviewURLs.RemoveAll();
	
	if ( m_bmThumb.m_hObject != NULL )
	{
		m_bmThumb.DeleteObject();
		Invalidate();
	}
	
	if ( m_bIsPreviewing )
	{
		m_bIsPreviewing = FALSE;
		Invalidate();
	}
	
	m_pRequest.Cancel();
}

UINT CSearchDetailPanel::ThreadStart(LPVOID pParam)
{
	CSearchDetailPanel* pPanel = (CSearchDetailPanel*)pParam;
	pPanel->OnRun();
	return 0;
}

void CSearchDetailPanel::OnRun()
{
	CSingleLock pLock( &m_pSection );
	CImageServices pServices;
	
	while ( m_bThread )
	{
		pLock.Lock();
		
		if ( ! m_bValid || ! m_bRunPreview || m_pPreviewURLs.IsEmpty() )
		{
			if ( m_bIsPreviewing )
			{
				m_bIsPreviewing = FALSE;
				Invalidate();
			}
			
			pLock.Unlock();
			WaitForSingleObject( m_pWakeup, INFINITE );
			
			continue;
		}
		
		CString strURL	= m_pPreviewURLs.RemoveHead();
		SHA1 pSHA1		= m_pSHA1;
		
		if ( ! m_bIsPreviewing )
		{
			m_bIsPreviewing = TRUE;
			Invalidate();
		}
		
		pLock.Unlock();
		
		BYTE* pBuffer;
		DWORD nBuffer;
		
		if ( ExecuteRequest( strURL, &pBuffer, &nBuffer ) )
		{
			CImageFile pImage( &pServices );
			
			if ( pImage.LoadFromMemory( _T(".jpg"), (LPCVOID)pBuffer, nBuffer, FALSE, TRUE ) )
			{
				OnPreviewLoaded( &pSHA1, &pImage );
				CachePreviewImage( &pSHA1, pBuffer, nBuffer );
			}
			else
			{
				theApp.Message( MSG_ERROR, IDS_SEARCH_DETAILS_PREVIEW_FAILED, (LPCTSTR)strURL );
			}
			
			free( pBuffer );
		}
		else
		{
			theApp.Message( MSG_ERROR, IDS_SEARCH_DETAILS_PREVIEW_FAILED, (LPCTSTR)strURL );
		}
	}
}

BOOL CSearchDetailPanel::ExecuteRequest(CString strURL, BYTE** ppBuffer, DWORD* pnBuffer)
{
	m_pRequest.Clear();
	m_pRequest.SetURL( strURL );
	m_pRequest.AddHeader( _T("Accept"), _T("image/jpeg") );
	m_pRequest.LimitContentLength( Settings.Search.MaxPreviewLength );
	
	if ( ! m_pRequest.Execute( FALSE ) )
	{
		theApp.Message( MSG_DEBUG, _T("Preview failed: unable to execute request.") );
		return FALSE;
	}
	
	int nCode = m_pRequest.GetStatusCode();
	
	if ( m_pRequest.GetStatusSuccess() == FALSE )
	{
		theApp.Message( MSG_DEBUG, _T("Preview failed: HTTP status code %i"),
			m_pRequest.GetStatusCode() );
		return FALSE;
	}
	
	CString strURN = m_pRequest.GetHeader( _T("X-Previewed-URN") );
	
	if ( strURN.GetLength() )
	{
		SHA1 pSHA1;
		
		if ( CSHA::HashFromURN( strURN, &pSHA1 ) && pSHA1 != m_pSHA1 )
		{
			theApp.Message( MSG_DEBUG, _T("Preview failed: wrong URN.") );
			return FALSE;
		}
	}
	
	CString strMIME = m_pRequest.GetHeader( _T("Content-Type") );
	
	if ( strMIME.CompareNoCase( _T("image/jpeg") ) != 0 )
	{
		theApp.Message( MSG_DEBUG, _T("Preview failed: unacceptable content type.") );
		return FALSE;
	}
	
	CBuffer* pBuffer = m_pRequest.GetResponseBuffer();
	if ( pBuffer == NULL ) return FALSE;
	
	*pnBuffer = pBuffer->m_nLength;
	*ppBuffer = (BYTE*)malloc( *pnBuffer );
	CopyMemory( *ppBuffer, pBuffer->m_pBuffer, *pnBuffer );
	
	return TRUE;
}

void CSearchDetailPanel::OnPreviewLoaded(SHA1* pSHA1, CImageFile* pImage)
{
	if ( m_nThumbSize == 0 ) return;
	
	int nSize = m_nThumbSize * pImage->m_nWidth / pImage->m_nHeight;
	
	if ( nSize > m_nThumbSize )
	{
		nSize = m_nThumbSize * pImage->m_nHeight / pImage->m_nWidth;
		pImage->Resample( m_nThumbSize, nSize );
	}
	else
	{
		pImage->Resample( nSize, m_nThumbSize );
	}
	
	CSingleLock pLock( &m_pSection, TRUE );
	
	if ( m_pSHA1 != *pSHA1 ) return;
	
	m_bCanPreview = m_bRunPreview = m_bIsPreviewing = FALSE;
	
	if ( m_bmThumb.m_hObject ) m_bmThumb.DeleteObject();
	
	m_bmThumb.Attach( pImage->CreateBitmap() );
	m_szThumb.cx = pImage->m_nWidth;
	m_szThumb.cy = pImage->m_nHeight;
	
	pLock.Unlock();
	Invalidate();
}

BOOL CSearchDetailPanel::CachePreviewImage(SHA1* pSHA1, LPBYTE pBuffer, DWORD nBuffer)
{
	CSingleLock pLock( &m_pMatches->m_pSection, TRUE );
	
	if ( m_pMatches->FileToItem( m_pFile ) != 0xFFFFFFFF )
	{
		if ( m_pFile->m_pPreview != NULL ) delete [] m_pFile->m_pPreview;
		
		m_pFile->m_nPreview = nBuffer;
		m_pFile->m_pPreview = new BYTE[ nBuffer ];
		CopyMemory( m_pFile->m_pPreview, pBuffer, nBuffer );
		
		return TRUE;
	}
	
	return FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -