2020-09-30 17:12:32 +02:00

195 lines
4.2 KiB
C++

#include "precomp.h"
WCHAR const c_szDefault[] = L"Default";
HRESULT CImgCacheTidyup_Create( IImageCache * pCache,
BOOL fMultiple,
HWND hWndListView,
int * piItemPos,
LPRUNNABLETASK * ppTask )
{
if ( !ppTask || !pCache )
{
return E_INVALIDARG;
}
CImgCacheTidyup *pTask = new CComObject<CImgCacheTidyup>;
if ( pTask == NULL )
{
return E_OUTOFMEMORY;
}
// not ref-counted as it is not a COM object...
pTask->m_pCache = pCache;
pTask->m_fMultiple = fMultiple;
pTask->m_piItemPos = piItemPos;
pTask->m_hWndListView = hWndListView;
pCache->AddRef();
pTask->AddRef();
*ppTask = (LPRUNNABLETASK) pTask;
return NOERROR;
}
STDMETHODIMP CImgCacheTidyup::Run( )
{
if ( m_lState == IRTIR_TASK_FINISHED || m_lState == IRTIR_TASK_RUNNING )
{
return S_FALSE;
}
if ( m_lState == IRTIR_TASK_PENDING )
{
return E_FAIL;
}
LONG lRes = InterlockedExchange( & m_lState, IRTIR_TASK_RUNNING );
if ( lRes == IRTIR_TASK_PENDING )
{
m_lState = IRTIR_TASK_FINISHED;
return NOERROR;
}
BOOL fReset = FALSE;
int iItem = *m_piItemPos;
do
{
iItem = ListView_GetNextItem( m_hWndListView, iItem, LVNI_ALL);
if ( iItem == -1 )
{
if ( fReset == FALSE && *m_piItemPos != -1)
{
fReset = TRUE;
continue;
}
else
{
break;
}
}
LV_ITEMW rgItem;
ZeroMemory( &rgItem, sizeof(rgItem));
rgItem.iItem = iItem;
rgItem.mask = LVIF_IMAGE | LVIF_NORECOMPUTE;
ListView_GetItemWrapW( m_hWndListView, &rgItem);
UINT uUsage;
if ( SUCCEEDED( m_pCache->GetUsage( rgItem.iImage, &uUsage )))
{
// single usage....
if ( uUsage == 1 )
{
// check to see if it is visible...
if (!ImageIsInView( iItem ))
{
UINT uImage = rgItem.iImage;
// free it then ....
rgItem.mask = LVIF_IMAGE;
rgItem.iImage = I_IMAGECALLBACK;
rgItem.iItem = iItem;
ListView_SetItemWrapW( m_hWndListView, &rgItem);
// free it in the cache...
m_pCache->FreeImage( uImage );
*m_piItemPos = iItem;
if ( !m_fMultiple )
{
break;
}
}
}
}
} while ( TRUE );
m_lState = IRTIR_TASK_FINISHED;
return NOERROR;
}
STDMETHODIMP CImgCacheTidyup::Kill( BOOL fWait )
{
if ( fWait == TRUE )
{
return E_NOTIMPL;
}
if ( m_lState == IRTIR_TASK_RUNNING )
{
LONG lRes = InterlockedExchange( & m_lState, IRTIR_TASK_PENDING);
if ( lRes == IRTIR_TASK_FINISHED )
{
m_lState = lRes;
return NOERROR;
}
return E_PENDING;
}
else
{
return S_FALSE;
}
return E_PENDING;
}
STDMETHODIMP CImgCacheTidyup::Suspend( void )
{
// not supported....
return E_NOTIMPL;
}
STDMETHODIMP CImgCacheTidyup::Resume( void )
{
// not supported....
return E_NOTIMPL;
}
STDMETHODIMP_(ULONG) CImgCacheTidyup::IsRunning()
{
return (ULONG) m_lState;
}
CImgCacheTidyup::CImgCacheTidyup()
{
m_lState = IRTIR_TASK_NOT_RUNNING;
m_pCache = NULL;
}
CImgCacheTidyup::~CImgCacheTidyup()
{
if ( m_pCache )
{
m_pCache->Release();
}
}
BOOL CImgCacheTidyup::ImageIsInView( int iIndex )
{
RECT rectListView, rectItem;
GetClientRect( m_hWndListView, &rectListView );
// get the view and item dimensions.
ListView_GetItemRect( m_hWndListView, iIndex, &rectItem, LVIR_ICON );
// check if they overlap.
return !(( rectItem.left >= rectListView.right ) ||
( rectItem.right <= rectListView.left ) ||
( rectItem.top >= rectListView.bottom ) ||
( rectItem.bottom <= rectListView.top ));
}