588 lines
13 KiB
C++
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;
|
|
}
|
|
|