📄 ieshelllistctrl.cpp
字号:
//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// You may use this source code, compile or redistribute it as part of your application
// for free. You cannot redistribute it as a part of a software development
// library without the agreement of the author. If the sources are
// distributed along with the application, you should leave the original
// copyright notes in the source code without any changes.
// This code can be used WITHOUT ANY WARRANTIES at your own risk.
//
// For the latest updates to this code, check this site:
// http://www.masmex.com
// after Sept 2000
//
// Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
//*******************************************************************************
// IEShellListCtrl.cpp : implementation file
#include "stdafx.h"
#include "IEShellListCtrl.h"
#include "UIMessages.h"
#include "dirwalk.h"
#include "cbformats.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define UMAKEINT64(low,high) ((unsigned __int64)(((DWORD)(low)) | ((unsigned __int64)((DWORD)(high))) << 32))
/////////////////////////////////////////////////////////////////////////////
// CIEShellListCtrl
CIEShellListCtrl::CIEShellListCtrl()
{
SetEditSubItems(false);
SetDropFiles(false);
ZeroMemory(&m_tvid,sizeof(m_tvid));
m_psfSubFolder = NULL;
m_pMalloc = NULL;
m_bCallBack = false;
m_bNoExt = false;
m_nThreadCount = 0;
m_bRefreshAllowed = true;
m_bPopulateInit = false;
m_bInitiliazed = false;
m_bNotifyParent = false;
m_pidlInternet = NULL;
SHGetMalloc(&m_pMalloc);
SHGetSpecialFolderLocation(NULL,CSIDL_INTERNET,&m_pidlInternet);
m_sColumns = _T("Name|Size|Type|Modified");
}
CIEShellListCtrl::~CIEShellListCtrl()
{
FreeTVID();
AllItemsDeleted();
if (m_pidlInternet)
m_pMalloc->Release();
if (m_pMalloc)
m_pMalloc->Release();
}
void CIEShellListCtrl::PopupTheMenu(int nRow,CPoint point)
{
if (!GetSelectedCount())
return;
int nSel=-1;
LPLVITEMDATA lplvid=NULL;
LPITEMIDLIST *pidls=(LPITEMIDLIST*)GetShellPidl().GetMalloc()->Alloc(GetSelectedCount()*sizeof(LPITEMIDLIST));
int i=0;
while ((nSel = GetNextSel(nSel)) != -1)
{
lplvid=(LPLVITEMDATA)GetItemData(nSel);
pidls[i] = lplvid->lpi;
i++;
}
// at least one
if (pidls && i)
{
GetShellPidl().PopupTheMenu(m_hWnd, lplvid->lpsfParent, pidls, i, &point);
}
GetShellPidl().Free(pidls);
}
void CIEShellListCtrl::ShellExecute(int nRow,LPCTSTR pszVerb)
{
SHELLEXECUTEINFO si;
ZeroMemory(&si,sizeof(si));
si.cbSize = sizeof(si);
si.hwnd = GetSafeHwnd();
si.nShow = SW_SHOW;
si.lpIDList = (LPVOID)GetPathPidl(nRow);
si.fMask = SEE_MASK_INVOKEIDLIST;
if (pszVerb)
si.lpVerb = pszVerb;
ShellExecuteEx(&si);
}
void CIEShellListCtrl::SetNotificationObject(bool bNotify)
{
if (bNotify)
CreateFileChangeThread(GetSafeHwnd());
else
DestroyThreads();
}
void CIEShellListCtrl::FreeInterface(IUnknown *pInterface)
{
if (pInterface)
pInterface->Release();
}
void CIEShellListCtrl::DestroyThreads()
{
if (m_nThreadCount == 0)
return;
for (UINT i=0; i<m_nThreadCount; i++)
m_event[i].SetEvent();
::WaitForMultipleObjects (m_nThreadCount, m_hThreads, TRUE, INFINITE);
for (i=0; i<m_nThreadCount; i++)
delete m_pThreads[i];
m_nThreadCount = 0;
}
void CIEShellListCtrl::FreeTVID()
{
if (m_tvid.lpsfParent)
m_tvid.lpsfParent->Release();
if (m_tvid.lpi)
m_pMalloc->Free(m_tvid.lpi);
if (m_tvid.lpifq)
m_pMalloc->Free(m_tvid.lpifq);
ZeroMemory(&m_tvid,sizeof(m_tvid));
if (m_psfSubFolder)
m_psfSubFolder->Release();
m_psfSubFolder = NULL;
}
CString CIEShellListCtrl::GetCurrPathName()
{
return GetPathName(GetCurSel());
}
CString CIEShellListCtrl::GetPathName(int nRow)
{
if (nRow == -1)
nRow = GetCurSel();
CString sPath;
if (nRow == -1)
return sPath;
LPLVITEMDATA plvit = (LPLVITEMDATA)GetItemData(nRow);
ASSERT(plvit);
if (plvit == NULL)
return sPath;
SHGetPathFromIDList(plvit->lpifq,sPath.GetBuffer(MAX_PATH));
sPath.ReleaseBuffer();
return sPath;
}
LPCITEMIDLIST CIEShellListCtrl::GetPathPidl(int nRow)
{
if (nRow == -1)
return NULL;
LPLVITEMDATA plvit = (LPLVITEMDATA)GetItemData(nRow);
ASSERT(plvit);
if (plvit == NULL)
return NULL;
return plvit->lpifq;
}
void CIEShellListCtrl::FillExcludedFileTypes(CComboBox &cb)
{
cb.ResetContent();
for(POSITION pos=m_ExcludedLookup.GetHeadPosition();pos != NULL;m_ExcludedLookup.GetNext(pos))
{
cb.AddString(m_ExcludedLookup.GetAt(pos));
}
}
void CIEShellListCtrl::SetExcludedFileTypes(CComboBox &cb)
{
m_ExcludedLookup.RemoveAll();
CString sText;
for(int i=0;i < cb.GetCount();i++)
{
cb.GetLBText(i,sText);
m_ExcludedLookup.AddHead(sText);
}
}
void CIEShellListCtrl::LoadFilterFiles(const CString &sFileFilter)
{
m_FilterLookup.RemoveAll();
CFileFind ff;
CString sPath;
if (FAILED(GetShellPidl().SHPidlToPathEx(m_tvid.lpifq,sPath)))
return;
if (sPath.Right(1) != _T('\\'))
sPath += _T('\\');
CString sFindPath;
CString sMask;
LPCTSTR pszFilter=sFileFilter;
pszFilter = GetFilterMask(pszFilter,sMask);
while (pszFilter != NULL)
{
sFindPath = sPath;
sFindPath += sMask;
BOOL bFind = ff.FindFile(sFindPath);
while (bFind)
{
bFind = ff.FindNextFile();
m_FilterLookup.AddHead(ff.GetFilePath());
}
pszFilter = GetFilterMask(pszFilter,sMask);
}
}
LPCTSTR CIEShellListCtrl::GetFilterMask(LPCTSTR pszFilter,CString &sMask)
{
if (*pszFilter == '\0')
return NULL;
TCHAR szMask[MAX_PATH];
szMask[0] = 0;
for(int i=0;*pszFilter != '\0';i++)
{
if (*pszFilter == _T(';') || *pszFilter == _T(','))
{
pszFilter = _tcsinc(pszFilter);
break;
}
szMask[i] = *pszFilter;
pszFilter = _tcsinc(pszFilter);
}
szMask[i] = 0;
sMask = szMask;
return pszFilter;
}
void CIEShellListCtrl::AllItemsDeleted()
{
LPLVITEMDATA pItemData=NULL;
for(vecListItemData::iterator it=m_vecItemData.begin();it != m_vecItemData.end();it++)
{
pItemData = *it;
if (pItemData)
{
if (pItemData->lpsfParent)
pItemData->lpsfParent->Release();
if (pItemData->lpi)
m_pMalloc->Free(pItemData->lpi);
if (pItemData->lpifq)
m_pMalloc->Free(pItemData->lpifq);
if (pItemData->lParam)
{
PSLC_COLUMN_DATA pColData = (PSLC_COLUMN_DATA)pItemData->lParam;
if (pColData->pidl)
GetShellPidl().FreePidl(pColData->pidl);
delete pColData;
}
m_pMalloc->Free(pItemData);
}
}
m_vecItemData.erase(m_vecItemData.begin(),m_vecItemData.end());
}
void CIEShellListCtrl::StartPopulate()
{
m_bPopulateInit = true;
DeleteAllItems();
for(UINT i=0;i < m_nThreadCount;i++)
m_MonitorEvent[i].SetEvent();
if (m_sFileFilter.IsEmpty() || m_sFileFilter == _T("*.*") || m_sFileFilter == _T("*"))
return;
LoadFilterFiles(m_sFileFilter);
}
void CIEShellListCtrl::EndPopulate()
{
m_bPopulateInit = false;
Sort();
SetColumnWidths();
}
BOOL CIEShellListCtrl::Populate(LPTVITEMDATA lptvid)
{
IShellFolder *pFolder=NULL;
BOOL bRet=FALSE;
HRESULT hr=E_FAIL;
if (lptvid->lpsfParent)
{
hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,0,IID_IShellFolder,(LPVOID*)&pFolder);
}
else
{
LPSHELLFOLDER psfDesktop;
LPITEMIDLIST pidlDesktop=NULL;
hr=SHGetDesktopFolder(&psfDesktop);
SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOP,&pidlDesktop);
if (GetShellPidl().ComparePidls(NULL,lptvid->lpifq,pidlDesktop))
{
pFolder = psfDesktop;
}
else
{
hr=psfDesktop->BindToObject(lptvid->lpifq,0,IID_IShellFolder,(LPVOID*)&pFolder);
psfDesktop->Release();
}
if (pidlDesktop)
GetShellPidl().FreePidl(pidlDesktop);
}
if (SUCCEEDED(hr))
{
bRet = Populate(lptvid,pFolder,true);
pFolder->Release();
}
return bRet;
}
BOOL CIEShellListCtrl::Populate(LPCTSTR pszPath, bool bCallBack)
{
LPITEMIDLIST pidlfq=NULL;
LPITEMIDLIST pidl=NULL;
LPSHELLFOLDER pDesktop = NULL;
SHGetDesktopFolder(&pDesktop);
if (FAILED(GetShellPidl().SHPathToPidlEx(pszPath,&pidlfq,pDesktop)))
return FALSE;
LPSHELLFOLDER pSubFolder = NULL;
if (FAILED(pDesktop->BindToObject(pidl, 0, IID_IShellFolder,(LPVOID*)&pSubFolder)))
return FALSE;
pidl = GetShellPidl().CopyLastItemID(pidlfq);
TVITEMDATA tvid;
tvid.lpifq = pidlfq;
tvid.lpi = pidl;
tvid.lpsfParent = NULL;
BOOL bRet = Populate(&tvid,pSubFolder,bCallBack);
if (pDesktop)
pDesktop->Release();
if (pSubFolder)
pSubFolder->Release();
if (pidl)
m_pMalloc->Free(pidl);
if (pidlfq)
m_pMalloc->Free(pidlfq);
return bRet;
}
BOOL CIEShellListCtrl::Populate(LPTVITEMDATA lptvid,LPSHELLFOLDER psfFolder,bool bCallBack)
{
m_bCallBack = bCallBack;
FreeTVID();
m_tvid.lpi = GetShellPidl().CopyItemIDList(lptvid->lpi);
m_tvid.lpifq = GetShellPidl().CopyItemIDList(lptvid->lpifq);
#ifdef _DEBUG
CString sPath;
GetShellPidl().SHPidlToPathEx(m_tvid.lpifq,sPath,NULL);
TRACE1("Populating path %s in CIEShellListCtrl\n",sPath);
#endif
if (lptvid->lpsfParent)
{
m_tvid.lpsfParent = lptvid->lpsfParent;
m_tvid.lpsfParent->AddRef();
}
m_psfSubFolder = psfFolder;
m_psfSubFolder->AddRef();
Load();
return TRUE;
}
CString CIEShellListCtrl::GetColumns()
{
SHELLDETAILS sd;
LPTSTR pszHeader=NULL;
CString sColumns;
for(int i=0;SUCCEEDED(m_ShellDetails.GetDetailsOf(NULL,i,&sd));i++)
{
GetShellPidl().StrRetToStr(sd.str,&pszHeader,NULL);
if (pszHeader)
{
TRACE1("Column found %s\n",pszHeader);
if (!sColumns.IsEmpty())
sColumns += _T("|");
sColumns += pszHeader;
GetShellPidl().Free(pszHeader);
pszHeader= NULL;
}
}
return sColumns;
}
void CIEShellListCtrl::InitColumns()
{
CString sColumns = GetColumns();
if (sColumns.IsEmpty())
sColumns = m_sColumns;
InitListCtrl(sColumns);
}
void CIEShellListCtrl::SetColumnWidths()
{
if (!m_bCallBack)
{
for(int i=0;i < GetColumnCount();i++)
SetColumnWidth(i,LVSCW_AUTOSIZE);
}
}
void CIEShellListCtrl::Refresh()
{
if (m_psfSubFolder==NULL)
return;
SetRefreshAllowed(false);
SetRedraw(FALSE);
int nCurSel = GetCurSel();
TRACE(_T("Refreshing shell list control\n"));
Load();
SetCurSel(nCurSel);
LONG Result;
OnSelChanged(nCurSel,&Result);
SetRedraw(TRUE);
SetRefreshAllowed(true);
}
void CIEShellListCtrl::Load()
{
CWaitCursor w;
if (!InitItems(&m_tvid,m_bCallBack))
return;
}
void CIEShellListCtrl::Init()
{
if (m_bInitiliazed)
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -