772 lines
39 KiB
C++
772 lines
39 KiB
C++
// OXShellObjectList.cpp : implementation file
|
||
//
|
||
// Version: 9.3
|
||
|
||
|
||
#include "stdafx.h"
|
||
#include "OXShellObjectList.h"
|
||
#include "OXMainRes.h"
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#undef THIS_FILE
|
||
static char THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
// delimiter for filter
|
||
const TCHAR OXSHELLLIST_EXT_DELIMITER=_T('|');
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// COXShellObjectList
|
||
|
||
COXShellObjectList::COXShellObjectList(BOOL bEnableContextMenu/*=TRUE*/,
|
||
BOOL bOnlyFileSystemItems/*=TRUE*/,
|
||
BOOL bNotifyError/*=TRUE*/,
|
||
LPCTSTR lpszFilter/*=_T("")*/)
|
||
{
|
||
SetEnableContextMenu(bEnableContextMenu);
|
||
SetOnlyFileSystemItems(bOnlyFileSystemItems);
|
||
SetNotifyError(bNotifyError);
|
||
|
||
SetFilter(lpszFilter);
|
||
|
||
m_lpsfCurrentParentFolder=NULL;
|
||
m_lpFullIDLCurrentParentFolder=NULL;
|
||
|
||
m_hShellImageListLarge=NULL;
|
||
m_hShellImageListSmall=NULL;
|
||
|
||
m_nRedraw=0;
|
||
|
||
m_bInitialized=FALSE;
|
||
}
|
||
|
||
COXShellObjectList::~COXShellObjectList()
|
||
{
|
||
}
|
||
|
||
|
||
BEGIN_MESSAGE_MAP(COXShellObjectList, CListCtrl)
|
||
//{{AFX_MSG_MAP(COXShellObjectList)
|
||
ON_NOTIFY_REFLECT_EX(NM_DBLCLK, OnDblClick)
|
||
ON_NOTIFY_REFLECT_EX(LVN_BEGINLABELEDIT, OnBeginLabelEdit)
|
||
ON_NOTIFY_REFLECT_EX(LVN_ENDLABELEDIT, OnEndLabelEdit)
|
||
#ifdef OXSHELLLIST_WATCHFORDIR
|
||
ON_MESSAGE(WM_OX_FILE_NOTIFY, OnDirChangeNotify)
|
||
#endif // OXSHELLLIST_WATCHFORDIR
|
||
ON_WM_CONTEXTMENU()
|
||
//}}AFX_MSG_MAP
|
||
END_MESSAGE_MAP()
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// COXShellObjectList message handlers
|
||
|
||
BOOL COXShellObjectList::PopulateList(const LPSHELLFOLDER lpFolder,
|
||
const LPITEMIDLIST lpFullIDL)
|
||
{
|
||
ASSERT_VALID(this);
|
||
ASSERT(lpFolder!=NULL);
|
||
|
||
if(!::IsWindow(GetSafeHwnd()))
|
||
return FALSE;
|
||
|
||
if(!m_bInitialized)
|
||
{
|
||
if(!Init())
|
||
return FALSE;
|
||
}
|
||
|
||
// Clean up ListCtrl
|
||
DeleteAllItems();
|
||
|
||
// Fill ListCtrl with objects in lpFolder folder.
|
||
FillListWithSubitems(lpFolder,lpFullIDL);
|
||
|
||
// We cannot sort item using just their display names. We have to
|
||
// request shell to sort items.
|
||
SortItems(COXShellNamespaceNavigator::CompareObjectsProc,NULL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL COXShellObjectList::PopulateList(CString sFolderStartFrom/*=_T("")*/)
|
||
{
|
||
ASSERT_VALID(this);
|
||
|
||
if(!::IsWindow(GetSafeHwnd()))
|
||
return FALSE;
|
||
|
||
if(!m_bInitialized)
|
||
{
|
||
if(!Init())
|
||
return FALSE;
|
||
}
|
||
|
||
// now let's fill ListCtrl with shell namespace objects that is located
|
||
// in sFolderStartFrom folder. If sFolderStartFrom is NULL then we use
|
||
// Desktop as start folder
|
||
|
||
// shell folder returned by that function have to be released afterwards
|
||
LPSHELLFOLDER lpFolder=m_navigator.GetShellFolder(sFolderStartFrom);
|
||
if(lpFolder==NULL)
|
||
return FALSE;
|
||
|
||
LPITEMIDLIST lpidlFull;
|
||
if(!m_navigator.GetShellFolderFullIDL(sFolderStartFrom,&lpidlFull))
|
||
{
|
||
// Release the folder
|
||
lpFolder->Release();
|
||
return FALSE;
|
||
}
|
||
|
||
// Clean up ListCtrl
|
||
DeleteAllItems();
|
||
|
||
// Fill ListCtrl with objects in lpFolder folder.
|
||
FillListWithSubitems(lpFolder,lpidlFull);
|
||
|
||
lpFolder->Release();
|
||
|
||
// We cannot sort item using just their display names. We have to
|
||
// request shell to sort items.
|
||
SortItems(COXShellNamespaceNavigator::CompareObjectsProc,NULL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
CString COXShellObjectList::GetFullPath(int nItem) const
|
||
{
|
||
ASSERT(nItem>=0 && nItem<GetItemCount());
|
||
|
||
// retrieve associated structure
|
||
LPNAMESPACEOBJECT lpNameSpaceObject=(LPNAMESPACEOBJECT)GetItemData(nItem);
|
||
if(lpNameSpaceObject==NULL)
|
||
return _T("");
|
||
|
||
return m_navigator.GetFullPath(lpNameSpaceObject->lpFullIDL);
|
||
}
|
||
|
||
|
||
BOOL COXShellObjectList::FillListWithSubitems(const LPSHELLFOLDER lpFolder,
|
||
const LPITEMIDLIST lpFullIDL)
|
||
{
|
||
ASSERT(lpFolder);
|
||
|
||
CWaitCursor wait;
|
||
|
||
// Initialize enumeration of objects within given folder
|
||
if(!m_navigator.InitObjectsEnumerator(lpFolder,lpFullIDL))
|
||
return FALSE;
|
||
|
||
// After we get pointer to IEnumIDList interface we can use its methods to
|
||
// retrieve information about all objects of given lpFolder
|
||
//
|
||
|
||
// structures for inserting new items in our ListCtrl
|
||
LV_ITEM lvi;
|
||
|
||
BOOL bLast;
|
||
// Loop through Shell Namespace items
|
||
LPNAMESPACEOBJECT lpNameSpaceObject=m_navigator.EnumerateObjectNext(bLast);
|
||
while(!bLast)
|
||
{
|
||
BOOL bQualified=lpNameSpaceObject!=NULL;
|
||
if(bQualified && GetOnlyFileSystemItems())
|
||
{
|
||
bQualified=(lpNameSpaceObject->dwFlags&SFGAO_FILESYSANCESTOR ||
|
||
lpNameSpaceObject->dwFlags&SFGAO_FILESYSTEM);
|
||
}
|
||
if(bQualified && (lpNameSpaceObject->dwFlags&SFGAO_FILESYSTEM) &&
|
||
!(lpNameSpaceObject->dwFlags&SFGAO_FOLDER))
|
||
{
|
||
bQualified=IsMatchingFilter(lpNameSpaceObject->szDisplayName);
|
||
}
|
||
if(bQualified && IsQualified(lpNameSpaceObject))
|
||
{
|
||
// We define text, image (including selected) and lParam value
|
||
// which is going to be a pointer to NAMESPACEOBJECT structure
|
||
lvi.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
|
||
// NAMESPACEOBJECT structure is already filled
|
||
lvi.lParam=(LPARAM)lpNameSpaceObject;
|
||
|
||
// display name
|
||
lvi.pszText=lpNameSpaceObject->szDisplayName;
|
||
|
||
// image
|
||
int nListImageIndex=-1;
|
||
if(!m_mapImageIndex.Lookup(lpNameSpaceObject->nImageSmall,nListImageIndex))
|
||
{
|
||
nListImageIndex=PtrToInt(m_mapImageIndex.GetCount());
|
||
m_mapImageIndex.SetAt(lpNameSpaceObject->nImageSmall,nListImageIndex);
|
||
HICON hIcon=ImageList_ExtractIcon(
|
||
0,m_hShellImageListLarge,lpNameSpaceObject->nImageSmall);
|
||
ASSERT(hIcon!=NULL);
|
||
lvi.iImage=m_imageListLarge.Add(hIcon);
|
||
ASSERT(lvi.iImage!=-1 && lvi.iImage==nListImageIndex);
|
||
VERIFY(::DestroyIcon(hIcon));
|
||
hIcon=ImageList_ExtractIcon(
|
||
0,m_hShellImageListSmall,lpNameSpaceObject->nImageSmall);
|
||
ASSERT(hIcon!=NULL);
|
||
VERIFY(m_imageListSmall.Add(hIcon)==lvi.iImage);
|
||
VERIFY(::DestroyIcon(hIcon));
|
||
}
|
||
else
|
||
{
|
||
lvi.iImage=nListImageIndex;
|
||
}
|
||
/////////////////////
|
||
|
||
// index and subitem
|
||
lvi.iItem=GetItemCount();
|
||
lvi.iSubItem=0;
|
||
|
||
// We collected all information we needed. It's time to insert
|
||
// new item in our ListCtrl.
|
||
int nItem=InsertItem(&lvi);
|
||
ASSERT(nItem!=-1);
|
||
|
||
// retrieve info about size, type and modification date of the
|
||
// file system object
|
||
if(lpNameSpaceObject->dwFlags&SFGAO_FILESYSTEM)
|
||
{
|
||
CString sFullPath=m_navigator.GetFullPath(lpNameSpaceObject->lpFullIDL);
|
||
ASSERT(!sFullPath.IsEmpty());
|
||
|
||
CFileStatus fileStatus;
|
||
if(CFile::GetStatus(sFullPath,fileStatus))
|
||
{
|
||
if((lpNameSpaceObject->dwFlags&SFGAO_FOLDER)!=SFGAO_FOLDER)
|
||
{
|
||
// request size
|
||
CString sFileSize;
|
||
sFileSize.Format(_T("%dKB"),
|
||
(fileStatus.m_size>1024 ? fileStatus.m_size/1024 : 1));
|
||
SetItem(nItem,1,LVIF_TEXT,sFileSize,0,0,0,0);
|
||
}
|
||
|
||
// modified
|
||
CString sModified=fileStatus.m_mtime.Format(_T("%c"));
|
||
SetItem(nItem,3,LVIF_TEXT,sModified,0,0,0,0);
|
||
}
|
||
|
||
SHFILEINFO shfi;
|
||
if(SHGetFileInfo(sFullPath,NULL,&shfi,sizeof(shfi),
|
||
SHGFI_TYPENAME)!=0)
|
||
{
|
||
// file type
|
||
CString sItemType(_T(""));
|
||
sItemType=(LPCTSTR)shfi.szTypeName;
|
||
SetItem(nItem,2,LVIF_TEXT,sItemType,0,0,0,0);
|
||
}
|
||
}
|
||
}
|
||
lpNameSpaceObject=m_navigator.EnumerateObjectNext(bLast);
|
||
}
|
||
|
||
// Release enumerator
|
||
m_navigator.ReleaseObjectsEnumerator();
|
||
|
||
#ifdef OXSHELLLIST_WATCHFORDIR
|
||
if(m_lpFullIDLCurrentParentFolder!=NULL)
|
||
{
|
||
CString sCurrentFolder=m_navigator.GetFullPath(m_lpFullIDLCurrentParentFolder);
|
||
if(!sCurrentFolder.IsEmpty())
|
||
m_fileWatcher.RemoveWatch(sCurrentFolder);
|
||
|
||
sCurrentFolder=m_navigator.GetFullPath(lpFullIDL);
|
||
if(!sCurrentFolder.IsEmpty())
|
||
{
|
||
if(m_fileWatcher.AddWatch(sCurrentFolder,FALSE,
|
||
COXFileWatcher::OXFileWatchChangeDirName|
|
||
COXFileWatcher::OXFileWatchChangeFileName))
|
||
{
|
||
m_fileWatcher.EnableWindowNotification(sCurrentFolder,this,TRUE);
|
||
}
|
||
else
|
||
{
|
||
TRACE(_T("COXShellObjectList::FillListWithSubitems: failed to set a file watcher for the current parent folder\n"));
|
||
}
|
||
}
|
||
}
|
||
#endif // OXSHELLLIST_WATCHFORDIR
|
||
|
||
m_lpsfCurrentParentFolder=lpFolder;
|
||
m_lpFullIDLCurrentParentFolder=lpFullIDL;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXShellObjectList::OnDblClick(NMHDR* pNMHDR, LRESULT* pResult)
|
||
{
|
||
UNREFERENCED_PARAMETER(pNMHDR);
|
||
|
||
// TODO: Add your control notification handler code here
|
||
*pResult = 0;
|
||
|
||
// if double click over a folder we expand it or otherwise invoke
|
||
// the default command for a file
|
||
//
|
||
|
||
// Get the item that was double clicked in screen coordinates
|
||
CPoint ptMouseCursor;
|
||
if(!::GetCursorPos(&ptMouseCursor))
|
||
{
|
||
TRACE(_T("COXShellObjectList::OnDblClick: GetCursorPos() failed\n"));
|
||
return FALSE;
|
||
}
|
||
ScreenToClient(&ptMouseCursor);
|
||
|
||
// Use HitTest function to define the list item by coordinate
|
||
UINT nFlags=NULL;
|
||
int nItem=HitTest(ptMouseCursor,&nFlags);
|
||
|
||
if(nItem!=-1 && (nFlags&LVHT_ONITEM)!=0)
|
||
{
|
||
// Get folder info associated with item
|
||
LPNAMESPACEOBJECT lpNameSpaceObject=
|
||
(LPNAMESPACEOBJECT)GetItemData(nItem);
|
||
ASSERT(lpNameSpaceObject!=NULL);
|
||
|
||
if((lpNameSpaceObject->dwFlags&SFGAO_FOLDER)!=SFGAO_FOLDER)
|
||
{
|
||
if(!m_navigator.InvokeDefaultCommand(lpNameSpaceObject->lpsfParent,
|
||
lpNameSpaceObject->lpRelativeIDL))
|
||
{
|
||
TRACE(_T("COXShellObjectList::OnDblClick: InvokeDefaultCommand() failed"));
|
||
}
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
BOOL COXShellObjectList::Init()
|
||
{
|
||
ASSERT_VALID(this);
|
||
|
||
if(!::IsWindow(GetSafeHwnd()))
|
||
return FALSE;
|
||
|
||
SetNotifyError(m_bNotifyError);
|
||
|
||
// use system image list as tree control's image list
|
||
//
|
||
m_mapImageIndex.RemoveAll();
|
||
|
||
// large images
|
||
if((HIMAGELIST)m_imageListLarge!=NULL)
|
||
m_imageListLarge.DeleteImageList();
|
||
// retrieve Shell image list
|
||
if(m_hShellImageListLarge==NULL)
|
||
{
|
||
m_hShellImageListLarge=m_navigator.GetShellImageList(FALSE);
|
||
if(m_hShellImageListLarge==NULL)
|
||
return FALSE;
|
||
}
|
||
IMAGEINFO imageInfo;
|
||
VERIFY(ImageList_GetImageInfo(m_hShellImageListLarge,0,&imageInfo));
|
||
CRect rect(imageInfo.rcImage);
|
||
VERIFY(m_imageListLarge.Create(rect.Width(),rect.Height(),ILC_COLOR32|ILC_MASK,0,0));
|
||
|
||
SetImageList(&m_imageListLarge,TVSIL_NORMAL);
|
||
////////////////////////////////////////////////
|
||
|
||
// small images
|
||
if((HIMAGELIST)m_imageListSmall!=NULL)
|
||
m_imageListSmall.DeleteImageList();
|
||
// retrieve Shell image list
|
||
if(m_hShellImageListSmall==NULL)
|
||
{
|
||
m_hShellImageListSmall=m_navigator.GetShellImageList(TRUE);
|
||
if(m_hShellImageListSmall==NULL)
|
||
return FALSE;
|
||
}
|
||
VERIFY(ImageList_GetImageInfo(m_hShellImageListSmall,0,&imageInfo));
|
||
rect=imageInfo.rcImage;
|
||
VERIFY(m_imageListSmall.Create(rect.Width(),rect.Height(),ILC_COLOR32|ILC_MASK,0,0));
|
||
|
||
SetImageList(&m_imageListSmall,LVSIL_SMALL);
|
||
////////////////////////////////////////////////
|
||
|
||
|
||
// Clean up ListCtrl
|
||
DeleteAllItems();
|
||
|
||
// check the columns
|
||
LVCOLUMN lvc={0};
|
||
lvc.mask=LVCF_FMT;
|
||
int nColumnCount=0;
|
||
while(GetColumn(nColumnCount,&lvc))
|
||
nColumnCount++;
|
||
if(nColumnCount!=4)
|
||
{
|
||
for(int nIndex=0; nIndex<nColumnCount; nIndex++)
|
||
DeleteColumn(0);
|
||
CString sItem;
|
||
VERIFY(sItem.LoadString(IDS_OX_SHELLOBJECTLISTNAME));
|
||
InsertColumn(0,sItem,LVCFMT_LEFT,200);
|
||
VERIFY(sItem.LoadString(IDS_OX_SHELLOBJECTLISTSIZE));
|
||
InsertColumn(1,sItem,LVCFMT_LEFT,70);
|
||
VERIFY(sItem.LoadString(IDS_OX_SHELLOBJECTLISTTYPE));
|
||
InsertColumn(2,sItem,LVCFMT_LEFT,120);
|
||
VERIFY(sItem.LoadString(IDS_OX_SHELLOBJECTLISTMODIFIED));
|
||
InsertColumn(3,sItem,LVCFMT_LEFT,120);
|
||
}
|
||
|
||
m_bInitialized=TRUE;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
void COXShellObjectList::SetRedraw(BOOL bRedraw/*=TRUE*/)
|
||
{
|
||
ASSERT(m_nRedraw>=0);
|
||
|
||
if(!bRedraw)
|
||
{
|
||
if(m_nRedraw==0)
|
||
{
|
||
CWnd::SetRedraw(FALSE);
|
||
}
|
||
m_nRedraw++;
|
||
}
|
||
else
|
||
{
|
||
if(m_nRedraw>=1)
|
||
m_nRedraw--;
|
||
if(m_nRedraw==0)
|
||
{
|
||
CWnd::SetRedraw(TRUE);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
BOOL COXShellObjectList::OnBeginLabelEdit(NMHDR* pNMHDR, LRESULT* pResult)
|
||
{
|
||
NMLVDISPINFO* plvdi=(NMLVDISPINFO*)pNMHDR;
|
||
ASSERT(plvdi!=NULL);
|
||
// TODO: Add your control notification handler code here
|
||
|
||
(*pResult)=FALSE;
|
||
|
||
// retrieve associated structure
|
||
LPNAMESPACEOBJECT lpNameSpaceObject=(LPNAMESPACEOBJECT)plvdi->item.lParam;
|
||
if(lpNameSpaceObject==NULL)
|
||
{
|
||
(*pResult)=TRUE;
|
||
return TRUE;
|
||
}
|
||
|
||
// check if item is allowed to be edited
|
||
if((lpNameSpaceObject->dwFlags&SFGAO_CANRENAME)!=SFGAO_CANRENAME)
|
||
{
|
||
(*pResult)=TRUE;
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
BOOL COXShellObjectList::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult)
|
||
{
|
||
NMLVDISPINFO* plvdi=(NMLVDISPINFO*)pNMHDR;
|
||
ASSERT(plvdi!=NULL);
|
||
// TODO: Add your control notification handler code here
|
||
|
||
*pResult=TRUE;;
|
||
|
||
CString sNewText=plvdi->item.pszText;
|
||
|
||
CWaitCursor waitCusor;
|
||
|
||
// retrieve associated structure
|
||
LPNAMESPACEOBJECT lpNameSpaceObject=(LPNAMESPACEOBJECT)plvdi->item.lParam;
|
||
ASSERT(lpNameSpaceObject!=NULL);
|
||
|
||
// rename the item
|
||
LPITEMIDLIST lpNewRelativeIDL=NULL;
|
||
if(sNewText.IsEmpty() ||
|
||
!m_navigator.RenameShellObject(lpNameSpaceObject->lpsfParent,
|
||
lpNameSpaceObject->lpRelativeIDL,&lpNewRelativeIDL,sNewText))
|
||
{
|
||
*pResult=FALSE;
|
||
}
|
||
else
|
||
{
|
||
ASSERT(lpNewRelativeIDL!=NULL);
|
||
lpNameSpaceObject->lpRelativeIDL=lpNewRelativeIDL;
|
||
*pResult=TRUE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXShellObjectList::Refresh()
|
||
{
|
||
SetRedraw(FALSE);
|
||
PopulateList(m_lpsfCurrentParentFolder,m_lpFullIDLCurrentParentFolder);
|
||
SetRedraw(TRUE);
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
#ifdef OXSHELLLIST_WATCHFORDIR
|
||
|
||
LRESULT COXShellObjectList::OnDirChangeNotify(WPARAM wParam, LPARAM lParam)
|
||
{
|
||
UNREFERENCED_PARAMETER(lParam);
|
||
|
||
CString str;
|
||
|
||
COXFileWatchNotifier fwNotifier;
|
||
fwNotifier=m_fileWatcher.GetFileWatchNotifier(wParam);
|
||
|
||
// If the wParam is an invalid ID then the notifier is empty
|
||
if(!fwNotifier.IsEmpty())
|
||
{
|
||
CString sDirPath=fwNotifier.GetPath();
|
||
ASSERT(!sDirPath.IsEmpty());
|
||
VERIFY(Refresh());
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
#endif // OXSHELLLIST_WATCHFORDIR
|
||
|
||
|
||
void COXShellObjectList::SetFilter(LPCTSTR lpszExtentions)
|
||
{
|
||
m_arrFilter.RemoveAll();
|
||
|
||
CString sExtentions=lpszExtentions;
|
||
if(sExtentions.IsEmpty())
|
||
return;
|
||
|
||
for(;;)
|
||
{
|
||
int nDelimiterPos=sExtentions.Find(OXSHELLLIST_EXT_DELIMITER);
|
||
if(nDelimiterPos==-1)
|
||
{
|
||
m_arrFilter.Add(sExtentions);
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
if(nDelimiterPos>0)
|
||
m_arrFilter.Add(sExtentions.Left(nDelimiterPos));
|
||
sExtentions=sExtentions.Mid(nDelimiterPos+1);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
CString COXShellObjectList::GetFilter() const
|
||
{
|
||
TCHAR sDelimiter[2];
|
||
sDelimiter[0]=OXSHELLLIST_EXT_DELIMITER;
|
||
sDelimiter[1]=_T('\0');
|
||
// special case
|
||
if(m_arrFilter.GetSize()==1 && m_arrFilter[0].IsEmpty())
|
||
return sDelimiter;
|
||
|
||
CString sExtentions(_T(""));
|
||
for(int nIndex=0; nIndex<m_arrFilter.GetSize(); nIndex++)
|
||
{
|
||
sExtentions=(nIndex==0 ? _T("") : sDelimiter)+m_arrFilter[nIndex];
|
||
}
|
||
return sExtentions;
|
||
}
|
||
|
||
|
||
BOOL COXShellObjectList::IsMatchingFilter(LPCTSTR lpszFileName)
|
||
{
|
||
ASSERT(lpszFileName!=NULL);
|
||
|
||
if(m_arrFilter.GetSize()==0)
|
||
return TRUE;
|
||
|
||
CString sFileName=lpszFileName;
|
||
CString sExtention(_T(""));
|
||
int nDelimeterPos=sFileName.Find(_T('.'));
|
||
if(nDelimeterPos!=0)
|
||
sExtention=sFileName.Mid(nDelimeterPos+1);
|
||
|
||
BOOL bFoundMatch=FALSE;
|
||
for(int nIndex=0; nIndex<m_arrFilter.GetSize(); nIndex++)
|
||
{
|
||
if(sExtention.CompareNoCase(m_arrFilter[nIndex])==0)
|
||
{
|
||
bFoundMatch=TRUE;
|
||
break;
|
||
}
|
||
}
|
||
return bFoundMatch;
|
||
}
|
||
|
||
|
||
void COXShellObjectList::OnContextMenu(CWnd* pWnd, CPoint pos)
|
||
{
|
||
UNREFERENCED_PARAMETER(pWnd);
|
||
|
||
// TODO: Add your control notification handler code here
|
||
if(GetEnableContextMenu())
|
||
{
|
||
// On right click we display context menu for any item
|
||
//
|
||
|
||
// Get the item that was right clicked in screen coordinates
|
||
CPoint ptMouseCursor=pos;
|
||
ScreenToClient(&ptMouseCursor);
|
||
|
||
// Use HitTest function to define the list item by coordinate
|
||
UINT nFlags=NULL;
|
||
int nItem=HitTest(ptMouseCursor,&nFlags);
|
||
|
||
if(nItem!=-1 && (nFlags&LVHT_ONITEM)!=0)
|
||
{
|
||
// select the item
|
||
VERIFY(SetItemState(nItem,LVIS_SELECTED,LVIS_SELECTED));
|
||
// Get folder info associated with item
|
||
LPNAMESPACEOBJECT lpNameSpaceObject=
|
||
(LPNAMESPACEOBJECT)GetItemData(nItem);
|
||
ASSERT(lpNameSpaceObject!=NULL);
|
||
|
||
DWORD dwMenuFlags=CMF_EXPLORE |
|
||
((((GetStyle()&LVS_EDITLABELS)==LVS_EDITLABELS) &&
|
||
((lpNameSpaceObject->dwFlags&SFGAO_CANRENAME)==SFGAO_CANRENAME)) ?
|
||
CMF_CANRENAME : NULL);
|
||
HMENU hMenu=m_navigator.GetObjectContextMenu(lpNameSpaceObject->lpsfParent,
|
||
lpNameSpaceObject->lpRelativeIDL,dwMenuFlags);
|
||
if(hMenu==NULL)
|
||
{
|
||
TRACE(_T("COXShellObjectList::OnContextMenu: GetObjectContextMenu() failed\n"));
|
||
return;
|
||
}
|
||
|
||
// Display popup menu using Windows API TrackPopupMenu function because
|
||
// it provides easy way of getting selected menu item. We need to set
|
||
// screen coordinates of the point where popup menu should be displayed.
|
||
ClientToScreen(&ptMouseCursor);
|
||
BOOL nCmdID=::TrackPopupMenu(hMenu,
|
||
TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON,
|
||
ptMouseCursor.x,ptMouseCursor.y,0,GetSafeHwnd(),NULL);
|
||
|
||
if(nCmdID)
|
||
{
|
||
switch(nCmdID)
|
||
{
|
||
case IDCMD_RENAME:
|
||
{
|
||
EditLabel(nItem);
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
if(!m_navigator.InvokeCommand(lpNameSpaceObject->lpsfParent,
|
||
lpNameSpaceObject->lpRelativeIDL,nCmdID,dwMenuFlags))
|
||
{
|
||
TRACE(_T("COXShellObjectList::OnContextMenu: InvokeCommand() failed"));
|
||
}
|
||
else
|
||
{
|
||
switch(nCmdID)
|
||
{
|
||
case IDCMD_DELETE:
|
||
{
|
||
DeleteItem(nItem);
|
||
break;
|
||
}
|
||
case IDCMD_PASTE:
|
||
{
|
||
Refresh();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
::DestroyMenu(hMenu);
|
||
}
|
||
else if(m_lpsfCurrentParentFolder!=NULL)
|
||
{
|
||
LPITEMIDLIST lpRelativeIDL=NULL;
|
||
LPSHELLFOLDER pShellFolder= m_navigator.GetParentShellFolder(
|
||
m_lpFullIDLCurrentParentFolder,&lpRelativeIDL);
|
||
if(pShellFolder==NULL)
|
||
{
|
||
TRACE(_T("COXShellObjectList::OnContextMenu: GetParentShellFolder() failed\n"));
|
||
return;
|
||
}
|
||
ASSERT(lpRelativeIDL!=NULL || m_lpFullIDLCurrentParentFolder==NULL);
|
||
|
||
DWORD dwMenuFlags=CMF_EXPLORE;
|
||
HMENU hMenu=m_navigator.GetObjectContextMenu(
|
||
pShellFolder,lpRelativeIDL,dwMenuFlags);
|
||
if(hMenu==NULL)
|
||
{
|
||
TRACE(_T("COXShellObjectList::OnContextMenu: GetObjectContextMenu() failed\n"));
|
||
return;
|
||
}
|
||
|
||
CMenu menuPopup;
|
||
VERIFY(menuPopup.Attach(hMenu));
|
||
|
||
// Display popup menu using Windows API TrackPopupMenu function because
|
||
// it provides easy way of getting selected menu item. We need to set
|
||
// screen coordinates of the point where popup menu should be displayed.
|
||
ClientToScreen(&ptMouseCursor);
|
||
BOOL nCmdID=::TrackPopupMenu(menuPopup.m_hMenu,
|
||
TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON,
|
||
ptMouseCursor.x,ptMouseCursor.y,0,GetSafeHwnd(),NULL);
|
||
|
||
if(nCmdID)
|
||
{
|
||
switch(nCmdID)
|
||
{
|
||
case IDCMD_RENAME:
|
||
{
|
||
ASSERT(FALSE);
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
if(!m_navigator.InvokeCommand(pShellFolder,lpRelativeIDL,
|
||
nCmdID,dwMenuFlags))
|
||
{
|
||
TRACE(_T("COXShellObjectList::OnContextMenu: InvokeCommand() failed"));
|
||
}
|
||
else
|
||
{
|
||
switch(nCmdID)
|
||
{
|
||
case IDCMD_DELETE:
|
||
{
|
||
ASSERT(FALSE);
|
||
break;
|
||
}
|
||
case IDCMD_PASTE:
|
||
{
|
||
Refresh();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
VERIFY(menuPopup.DestroyMenu());
|
||
}
|
||
}
|
||
}
|
||
|
||
|