Windows2000/private/shell/ext/thumbvw/thisfv.cpp
2020-09-30 17:12:32 +02:00

588 lines
13 KiB
C++

/* sample source code for IE4 view extension
* Copyright Microsoft 1996
* This file implements the IShellFolderView interface
*/
#include "precomp.h"
STDMETHODIMP CThumbnailView::Rearrange ( LPARAM lParamSort)
{
SortBy( lParamSort, TRUE );
m_iSortBy = (int) lParamSort;
return NOERROR;
}
STDMETHODIMP CThumbnailView::GetArrangeParam ( LPARAM *plParamSort)
{
if ( plParamSort == NULL )
{
return E_INVALIDARG;
}
*plParamSort = (LPARAM) m_iSortBy;
return NOERROR;
}
STDMETHODIMP CThumbnailView::ArrangeGrid ()
{
ListView_Arrange( m_hWndListView, LVA_SNAPTOGRID );
return NOERROR;
}
STDMETHODIMP CThumbnailView::AutoArrange ()
{
DWORD dwMainStyle = GetWindowLongWrapW( m_hWndListView, GWL_STYLE );
DWORD dwArrange = dwMainStyle & LVS_AUTOARRANGE;
dwMainStyle = dwMainStyle & ~LVS_AUTOARRANGE;
dwArrange = ~dwArrange;
SetWindowLongWrapW( m_hWndListView, GWL_STYLE,
dwMainStyle | ( dwArrange & LVS_AUTOARRANGE ) );
return NOERROR;
}
STDMETHODIMP CThumbnailView::GetAutoArrange ()
{
DWORD dwMainStyle = GetWindowLongWrapW( m_hWndListView, GWL_STYLE );
DWORD dwArrange = dwMainStyle & LVS_AUTOARRANGE;
HRESULT hr = S_FALSE;
if ( dwArrange != 0 )
{
hr = S_OK;
}
return hr;
}
STDMETHODIMP CThumbnailView::AddObject(LPITEMIDLIST pidl, UINT *puItem)
{
int iItem = FindInView( m_hWndListView, m_pFolder, pidl );
if ( iItem == -1 )
{
LPITEMIDLIST pidlCopy = ILClone( pidl );
if (pidlCopy)
{
iItem = AddItem( pidlCopy );
if ( iItem == -1 )
SHFree(pidlCopy);
}
else
return E_OUTOFMEMORY;
}
*puItem = iItem;
return ( iItem != - 1) ? NOERROR : E_FAIL ;
}
STDMETHODIMP CThumbnailView::GetObject(LPITEMIDLIST *ppidl, UINT uItem)
{
// should we return a pointer to our cached pidl, or should we duplicate it ?
// Worse hack, if -42 then return our own pidl...
if (uItem == (UINT)-42)
{
*ppidl = (LPITEMIDLIST) m_pidl;
return *ppidl ? NOERROR : E_UNEXPECTED;
}
// Hack, if item is -2, this implies return the focused item
if (uItem == (UINT)-2)
uItem = ListView_GetNextItem(m_hWndListView, -1, LVNI_FOCUSED);
LV_ITEMW rgItem;
ZeroMemory( &rgItem, sizeof( rgItem ));
rgItem.mask = LVIF_PARAM;
rgItem.iItem = uItem;
BOOL fFetch = ListView_GetItemWrapW( m_hWndListView, & rgItem );
if ( fFetch )
{
*ppidl = (LPITEMIDLIST) rgItem.lParam;
return NOERROR;
}
return E_UNEXPECTED;
}
STDMETHODIMP CThumbnailView::RemoveObject ( LPITEMIDLIST pidl, UINT *puItem)
{
// Non null go look for item.
int iItem = FindInView( m_hWndListView, m_pFolder, pidl );
int iFocus = -1;
if ( iItem < 0 )
{
return E_UNEXPECTED;
}
if ( puItem != NULL )
{
*puItem = (UINT) iItem;
}
UINT uState = ListView_GetItemState( m_hWndListView, iItem, LVIS_ALL);
RECT rc;
if (uState & LVIS_FOCUSED)
{
ListView_GetItemRect( m_hWndListView, iItem, &rc, LVIR_ICON );
}
LV_ITEMW rgItem;
ZeroMemory( &rgItem, sizeof( rgItem ));
rgItem.mask = LVIF_PARAM | LVIF_IMAGE;
rgItem.iItem = iItem;
BOOL fFetch = ListView_GetItemWrapW( m_hWndListView, &rgItem );
Assert( fFetch );
// do the actual delete
ListView_DeleteItem( m_hWndListView, iItem );
// we deleted the focused item.. replace the focus to the nearest item.
if (uState & LVIS_FOCUSED)
{
int iFocus = iItem;
LV_FINDINFO lvfi;
lvfi.flags = LVFI_NEARESTXY;
lvfi.pt.x = rc.left;
lvfi.pt.y = rc.top;
lvfi.vkDirection = 0;
iFocus = ListView_FindItem( m_hWndListView, -1, &lvfi );
}
else
{
if ( ListView_GetItemCount( m_hWndListView ) >= iFocus )
{
iFocus --;
}
}
if ( iFocus != -1 )
{
ListView_SetItemState( m_hWndListView, iFocus, LVIS_FOCUSED, LVIS_FOCUSED );
ListView_EnsureVisible( m_hWndListView, iFocus, FALSE );
}
SHFree( (LPITEMIDLIST) rgItem.lParam );
if ( rgItem.iImage != I_IMAGECALLBACK )
m_pImageCache->FreeImage( rgItem.iImage );
return NOERROR;
}
STDMETHODIMP CThumbnailView::GetObjectCount ( UINT *puCount)
{
if ( puCount == NULL )
{
return E_INVALIDARG;
}
*puCount = ListView_GetItemCount( m_hWndListView );
return NOERROR;
}
STDMETHODIMP CThumbnailView::SetObjectCount ( UINT uCount, UINT dwFlags)
{
DWORD dw = dwFlags;
if ((dwFlags & SFVSOC_INVALIDATE_ALL) == 0)
dw |= LVSICF_NOINVALIDATEALL; // gross transform
return (HRESULT) SendMessageA ( m_hWndListView,
LVM_SETITEMCOUNT,
(WPARAM)uCount,
(LPARAM)dw );
}
STDMETHODIMP CThumbnailView::UpdateObject ( LPITEMIDLIST pidlOld, LPITEMIDLIST pidlNew,UINT *puItem)
{
HRESULT hr = E_INVALIDARG;
int iItem = FindInView( m_hWndListView, m_pFolder, pidlOld );
if ( iItem >= 0 )
{
*puItem = iItem;
LV_ITEMW rgItem;
ZeroMemory( &rgItem, sizeof( rgItem ));
rgItem.mask = LVIF_PARAM | LVIF_IMAGE | LVIF_NORECOMPUTE;
rgItem.iItem = iItem;
BOOL fRes = ListView_GetItemWrapW( m_hWndListView, &rgItem );
Assert( fRes );
// save the old pidl...
LPITEMIDLIST pidlSave = (LPITEMIDLIST) rgItem.lParam;
if ( rgItem.iImage != I_IMAGECALLBACK )
{
// force the image to be refected so the icon is right ...
Assert( m_pImageCache );
m_pImageCache->DeleteImage( rgItem.iImage );
}
rgItem.mask = LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE;
rgItem.iItem = iItem;
rgItem.iImage = I_IMAGECALLBACK;
rgItem.iSubItem = 0; // REVIEW: bug in listview?
rgItem.lParam = (LPARAM)pidlNew;
WCHAR szTextBuffer[MAX_PATH];
rgItem.pszText = szTextBuffer;
// use IShellFolder to get the display name .....
STRRET rgStringRet;
hr = m_pFolder->GetDisplayNameOf( pidlNew, SHGDN_NORMAL, &rgStringRet );
if ( FAILED( hr ) )
{
// NOTE: if we failed to get the name of a element, then
// NOTE: don't change the display name....
// NOTE: a name....
rgItem.mask &= ~LVIF_TEXT;
}
szTextBuffer[0] = 0;
StrRetToBufW( &rgStringRet, pidlNew, szTextBuffer, ARRAYSIZE(szTextBuffer) );
fRes = ListView_SetItemWrapW(m_hWndListView, &rgItem);
Assert( fRes );
if ( fRes )
{
// Free the old pidl after we've added the new one
SHFree( pidlSave );
}
hr = NOERROR;
}
return hr;
}
STDMETHODIMP CThumbnailView::RefreshObject ( LPITEMIDLIST pidl, UINT *puItem)
{
if ( puItem == NULL )
{
return E_INVALIDARG;
}
int iItem = FindInView( m_hWndListView, m_pFolder, pidl );
if (iItem >= 0)
{
ListView_RedrawItems( m_hWndListView, iItem, iItem );
}
*puItem = iItem;
return (iItem >= 0) ? NOERROR : E_INVALIDARG;
}
STDMETHODIMP CThumbnailView::SetRedraw ( BOOL bRedraw)
{
SendMessageA( m_hWndListView, WM_SETREDRAW, (WPARAM)bRedraw, 0);
return NOERROR;
}
STDMETHODIMP CThumbnailView::GetSelectedCount ( UINT *puSelected )
{
if ( puSelected == NULL )
{
return E_INVALIDARG;
}
* puSelected = ListView_GetSelectedCount( m_hWndListView );
return NOERROR;
}
STDMETHODIMP CThumbnailView::GetSelectedObjects(LPCITEMIDLIST **pppidl, UINT *puItems)
{
HRESULT hr;
int iCount = ListView_GetSelectedCount( m_hWndListView );
if (iCount)
{
*pppidl = (LPCITEMIDLIST *) LocalAlloc(LPTR, sizeof(LPCITEMIDLIST) * iCount);
if (*pppidl)
{
int iFocused = ListView_GetNextItem( m_hWndListView, -1, LVNI_FOCUSED );
hr = GetSelectionPidlList( m_hWndListView, iCount, *pppidl, iFocused );
if (FAILED( hr ))
{
LocalFree(*pppidl);
*pppidl = NULL;
}
}
else
hr = E_OUTOFMEMORY;
}
else
*pppidl = NULL;
*puItems = iCount;
return hr;
}
STDMETHODIMP CThumbnailView::IsDropOnSource ( IDropTarget *pDropTarget)
{
return ( m_pDropTarget->GetBackgrndDT() == pDropTarget && m_fDragStarted ) ? S_OK : S_FALSE;
}
STDMETHODIMP CThumbnailView::GetDragPoint ( POINT *ppt)
{
if ( ppt == NULL )
{
return E_INVALIDARG;
}
if ( m_pDropTarget == NULL )
{
return E_UNEXPECTED;
}
if ( m_fDragStarted == FALSE )
{
return E_FAIL;
}
*ppt = m_ptDragStart;
return NOERROR;
}
STDMETHODIMP CThumbnailView::GetDropPoint ( POINT *ppt)
{
if ( ppt == NULL )
{
return E_INVALIDARG;
}
if ( m_pDropTarget == NULL )
{
return E_UNEXPECTED;
}
if ( m_pDropTarget->DropOnBackGrnd() == FALSE )
{
return E_FAIL;
}
m_pDropTarget->DropPoint( ppt );
return NOERROR;
}
STDMETHODIMP CThumbnailView::MoveIcons ( IDataObject *pDataObject)
{
m_fItemsMoved = TRUE;
return E_NOTIMPL;
}
STDMETHODIMP CThumbnailView::SetItemPos ( LPCITEMIDLIST pidl, POINT *ppt)
{
if ( ppt == NULL )
{
return E_INVALIDARG;
}
int iItem = FindInView( m_hWndListView, m_pFolder, pidl );
if ( iItem >= 0 )
{
m_fItemsMoved = TRUE;
ListView_SetItemPosition32( m_hWndListView, iItem, ppt->x, ppt->y );
}
return ( iItem < 0 ? E_INVALIDARG : NOERROR );
}
STDMETHODIMP CThumbnailView::IsBkDropTarget ( IDropTarget *pDropTarget)
{
if ( m_pDropTarget == NULL )
{
return E_UNEXPECTED;
}
return ( m_pDropTarget->DropOnBackGrnd() ? S_OK : S_FALSE);
}
STDMETHODIMP CThumbnailView::SetClipboard ( BOOL bMove)
{
if ( bMove )
{
// mark all selected items as being "cut"
int i = -1;
while ((i = ListView_GetNextItem( m_hWndListView, i, LVIS_SELECTED )) != -1)
{
ListView_SetItemState( m_hWndListView, i, LVIS_CUT, LVIS_CUT );
}
}
return NOERROR;
}
STDMETHODIMP CThumbnailView::SetPoints ( IDataObject *pDataObject)
{
return E_NOTIMPL;
}
STDMETHODIMP CThumbnailView::GetItemSpacing ( ITEMSPACING *pSpacing)
{
DWORD dwSize;
dwSize = ListView_GetItemSpacing(m_hWndListView, FALSE);
pSpacing->cxLarge = GetSystemMetrics( SM_CXICONSPACING );
pSpacing->cyLarge = GetSystemMetrics( SM_CYICONSPACING );
pSpacing->cxSmall = GET_X_LPARAM(dwSize);
pSpacing->cySmall = GET_Y_LPARAM(dwSize);
// we are always in large icon mode..
return S_OK;
}
STDMETHODIMP CThumbnailView::SetCallback ( IShellFolderViewCB* pNewCB,IShellFolderViewCB** ppOldCB)
{
if ( pNewCB == NULL )
{
return E_INVALIDARG;
}
if ( ppOldCB != NULL )
{
*ppOldCB = m_pFolderCB;
}
// if we had a ref on an old Callback, it goes out in the out param.
m_pFolderCB = pNewCB;
m_pFolderCB->AddRef();
return NOERROR;
}
STDMETHODIMP CThumbnailView::Select ( UINT dwFlags )
{
HRESULT hr = NOERROR;
switch( dwFlags )
{
case SFVS_SELECT_ALLITEMS:
{
DECLAREWAITCURSOR;
if (m_pFolderCB->MessageSFVCB( SFVM_SELECTALL, 0, 0) != (S_FALSE))
{
SetWaitCursor();
SetFocus( m_hWndListView );
ListView_SetItemState(m_hWndListView, -1, LVIS_SELECTED, LVIS_SELECTED );
ResetWaitCursor();
}
break;
}
case SFVS_SELECT_NONE:
ListView_SetItemState(m_hWndListView, -1, 0, LVIS_SELECTED);
break;
case SFVS_SELECT_INVERT:
{
DECLAREWAITCURSOR;
SetWaitCursor();
SetFocus(m_hWndListView);
int iItem = -1;
while ((iItem = ListView_GetNextItem(m_hWndListView, iItem, 0)) != -1)
{
UINT flag;
// flip the selection bit on each item
flag = ListView_GetItemState( m_hWndListView, iItem, LVIS_SELECTED );
flag ^= LVNI_SELECTED;
ListView_SetItemState( m_hWndListView, iItem, flag, LVIS_SELECTED );
}
ResetWaitCursor();
break;
}
default:
hr = E_INVALIDARG;
break;
}
return hr;
}
STDMETHODIMP CThumbnailView::QuerySupport (UINT * pdwSupport )
{
if ( pdwSupport == NULL )
{
return E_INVALIDARG;
}
*pdwSupport &= ( SFVQS_SELECT_ALL | SFVQS_SELECT_NONE
| SFVQS_SELECT_INVERT | SFVQS_AUTO_ARRANGE
| SFVQS_ARRANGE_GRID );
return (*pdwSupport ? S_OK : S_FALSE);
}
STDMETHODIMP CThumbnailView::SetAutomationObject ( IDispatch* pdisp)
{
// Release any previous automation objects we may have...
if (m_pAuto)
ATOMICRELEASE(m_pAuto);
if (pdisp)
{
// Hold onto the object...
m_pAuto = pdisp;
pdisp->AddRef();
}
return NOERROR;
}