📄 ieshelllistctrl.cpp
字号:
if (fs > 1024)
{
kb = fs / 1024;
if (fs % 1024)
kb++;
}
_ui64tot(kb,szText,10);
sSize = szText;
AddThousandSeps(sSize);
sSize += _T(" KB");
}
if ((FindFileData.ftLastWriteTime.dwLowDateTime != 0) || (FindFileData.ftLastWriteTime.dwHighDateTime != 0))
{
sDateTime = CLocaleInfo::Instance()->FormatDateTime(FindFileData.ftLastWriteTime);
}
else
{
sDateTime = CLocaleInfo::Instance()->FormatDateTime(FindFileData.ftCreationTime);
}
FindClose(hFind);
}
}
void CIEShellListCtrl::RemoveExt(LPTSTR pszFileName)
{
if (pszFileName == NULL)
return;
LPTSTR pExtPos=NULL;
LPTSTR pEndPos = pszFileName+lstrlen(pszFileName);
LPTSTR pStartPos = pszFileName;
while (pEndPos > pStartPos)
{
if (*pEndPos == '.')
{
pExtPos = pEndPos;
break;
}
pEndPos = _tcsdec(pStartPos,pEndPos);
}
if (pExtPos)
*pExtPos = '\0';
}
int CALLBACK ShellCompareFunc(LPARAM lparam1,
LPARAM lparam2,
LPARAM lparamSort);
PFNLVCOMPARE CIEShellListCtrl::GetCompareFunc()
{
if (m_bCallBack)
return ShellCompareFunc;
return CUIODListCtrl::GetCompareFunc();
}
int CALLBACK ShellCompareFunc(LPARAM lParam1,
LPARAM lParam2,
LPARAM lParamSort)
{
CUIListCtrlData *pData1 = (CUIListCtrlData*)lParam1;
CUIListCtrlData *pData2 = (CUIListCtrlData*)lParam2;
LPLVITEMDATA lplvid1=(LPLVITEMDATA)pData1->GetExtData();
LPLVITEMDATA lplvid2=(LPLVITEMDATA)pData2->GetExtData();
CUIODListCtrlSortInfo *pSortInfo = (CUIODListCtrlSortInfo*)lParamSort;
int nRet=0;
HRESULT hr = lplvid1->lpsfParent->CompareIDs(pSortInfo->GetColumn(),lplvid1->lpi,lplvid2->lpi);
if (SUCCEEDED(hr))
nRet = (short)hr;
if (!pSortInfo->Ascending())
nRet = -nRet;
return nRet;
}
/////////////////////////////////////////////////////////////////////////
// Thread function for detecting file system changes
UINT CIEShellListCtrl::ThreadFunc (LPVOID pParam)
{
///////////////////////
PFC_THREADINFO pThreadInfo = (PFC_THREADINFO)pParam;
HANDLE hEvent = pThreadInfo->hEvent;
HANDLE hMonitorEvent = pThreadInfo->hMonitorEvent;
CIEShellListCtrl *pListCtrl = pThreadInfo->pListCtrl;
HWND hWnd = pListCtrl->GetSafeHwnd();
delete pThreadInfo;
////////////////////////
TCHAR szPath[MAX_PATH];
int nHandles=2;
int nRet=0;
HANDLE hFileChange=NULL;
HANDLE aHandles[3];
aHandles[0] = hMonitorEvent;
aHandles[1] = hEvent;
aHandles[2] = NULL;
BOOL bContinue = TRUE;
// Sleep until a file change notification wakes this thread or
// m_event becomes set indicating it's time for the thread to end.
while (bContinue)
{
TRACE(_T("ListControl waiting for %u multiple objects\n"),nHandles);
DWORD dw = ::WaitForMultipleObjects (nHandles, aHandles, FALSE, INFINITE);
if (dw >= WAIT_ABANDONED && dw <= (WAIT_ABANDONED+(nHandles-1)))
{
TRACE(_T("ListControl waiting abandoned\n"),nHandles);
break;
}
// Reset Event
if(dw - WAIT_OBJECT_0 == 0)
{
if (hFileChange && hFileChange != INVALID_HANDLE_VALUE)
::FindCloseChangeNotification(hFileChange);
if (::SendMessage(hWnd, WM_APP_FILE_CHANGE_NEW_PATH, (WPARAM)szPath, 0))
{
if (szPath[0] == 0)
{
TRACE(_T("File notify path was returned empty\n"));
hFileChange = NULL;
aHandles[2] = hFileChange;
continue;
}
TRACE(_T("File notify path returned %s\n"),szPath);
hFileChange = ::FindFirstChangeNotification (szPath, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE);
if (hFileChange == INVALID_HANDLE_VALUE)
{
TRACE(_T("File notify thread was unable to create notification object\n"));
hFileChange = NULL;
aHandles[2] = hFileChange;
continue;
}
else
{
if (nHandles == 2)
{
TRACE(_T("File notify thread has created the notification object for the first time\n"));
nHandles++;
}
TRACE(_T("File notify thread has created the notification object\n"));
aHandles[2] = hFileChange;
}
}
}
// End Event
else if(dw - WAIT_OBJECT_0 == 1)
{
bContinue = FALSE;
TRACE(_T("File Notify Thread was signalled to stop\n"));
}
// File Change Event
else if (dw - WAIT_OBJECT_0 == 2)
{ // Respond to a change notification.
::FindNextChangeNotification (hFileChange);
TRACE(_T("-- File notify event was fired in CIEShellListCtrl --\n"));
if (pListCtrl->RefreshAllowed())
{
::PostMessage (hWnd, WM_APP_FILE_CHANGE_EVENT,0,0);
}
else
{
TRACE(_T("but not sending as refreshing\n"));
pListCtrl->SetRefreshAllowed(true);
TRACE(_T("Refresh is now allowed\n"));
}
}
}
if (hFileChange && hFileChange != INVALID_HANDLE_VALUE)
::FindCloseChangeNotification (hFileChange);
TRACE(_T("File Notify Thread is ending\n"));
return nRet;
}
LRESULT CIEShellListCtrl::OnAppFileChangeNewPath(WPARAM wParam, LPARAM lParam)
{
ASSERT(wParam);
SHGetPathFromIDList(m_tvid.lpifq,(LPTSTR)wParam);
return 1;
}
LRESULT CIEShellListCtrl::OnAppFileChangeEvent(WPARAM wParam, LPARAM lParam)
{
if (!RefreshAllowed())
return 1L;
Refresh();
if (m_bNotifyParent)
GetParent()->SendMessage(WM_APP_UPDATE_ALL_VIEWS,(WPARAM)HINT_SHELL_FILE_CHANGED,(LPARAM)(LPCTSTR)m_sMonitorPath);
return 1L;
}
void CIEShellListCtrl::PreSubclassWindow()
{
CUIODListCtrl::PreSubclassWindow();
CreateFileChangeThread(GetSafeHwnd());
}
void CIEShellListCtrl::CreateFileChangeThread(HWND hwnd)
{
if (m_nThreadCount >= MAX_THREADS)
return;
PFC_THREADINFO pThreadInfo = new FC_THREADINFO; // Thread will delete
pThreadInfo->hMonitorEvent = m_MonitorEvent[m_nThreadCount].m_hObject;
pThreadInfo->hEvent = m_event[m_nThreadCount].m_hObject;
pThreadInfo->pListCtrl = this;
CWinThread* pThread = AfxBeginThread (ThreadFunc, pThreadInfo,
THREAD_PRIORITY_IDLE);
pThread->m_bAutoDelete = FALSE;
m_hThreads[m_nThreadCount] = pThread->m_hThread;
m_pThreads[m_nThreadCount++] = pThread;
}
bool CIEShellListCtrl::DragDrop(CDD_OleDropTargetInfo *pInfo)
{
// TODO: Add your specialized code here and/or call the base class
return m_ShellDragDrop.DragDrop(pInfo,m_tvid.lpsfParent,m_tvid.lpi);
}
bool CIEShellListCtrl::DragEnter(CDD_OleDropTargetInfo *pInfo)
{
// TODO: Add your specialized code here and/or call the base class
return m_ShellDragDrop.DragEnter(pInfo,m_tvid.lpsfParent,m_tvid.lpi);
}
bool CIEShellListCtrl::DragLeave(CDD_OleDropTargetInfo *pInfo)
{
// TODO: Add your specialized code here and/or call the base class
return m_ShellDragDrop.DragLeave(pInfo);
}
bool CIEShellListCtrl::DragOver(CDD_OleDropTargetInfo *pInfo)
{
// TODO: Add your specialized code here and/or call the base class
return m_ShellDragDrop.DragOver(pInfo,m_tvid.lpsfParent,m_tvid.lpi);
}
// When the use starts a drag drop source
DROPEFFECT CIEShellListCtrl::DoDragDrop(int *pnRows,COleDataSource *pOleDataSource)
{
CShellPidl pidl;
CCF_ShellIDList sl;
CCF_HDROP cf_hdrop;
CCF_String cf_text;
cf_hdrop.AddDropPoint(CPoint(),FALSE);
CString sPath;
CString sText;
LPLVITEMDATA plvid=NULL;
if (GetShellPidl().IsDesktopFolder(m_psfSubFolder))
sl.AddPidl(GetShellPidl().GetEmptyPidl());
else
sl.AddPidl(m_tvid.lpifq);
for(int i=0;*pnRows != -1;i++)
{
plvid = (LPLVITEMDATA)GetItemData(*pnRows);
ASSERT(plvid);
sl.AddPidl(plvid->lpi);
pidl.SHPidlToPathEx(plvid->lpi,sPath,plvid->lpsfParent);
cf_hdrop.AddFileName(sPath);
sText += sPath;
sText += _T("\n");
pnRows++;
}
cf_text.SetString(sText);
if (i > 0)
{
CWDClipboardData::Instance()->SetData(pOleDataSource,&cf_text,CWDClipboardData::e_cfString);
CWDClipboardData::Instance()->SetData(pOleDataSource,&sl,CWDClipboardData::e_cfShellIDList);
CWDClipboardData::Instance()->SetData(pOleDataSource,&cf_hdrop,CWDClipboardData::e_cfHDROP);
}
return GetShellPidl().GetDragDropAttributes(plvid);
}
LRESULT CIEShellListCtrl::OnAppUpdateAllViews(WPARAM wParam, LPARAM lParam)
{
if (wParam == HINT_TREE_SEL_CHANGED)
{
ASSERT(lParam);
const CRefreshShellFolder *pRefresh = reinterpret_cast<CRefreshShellFolder*>(lParam);
if (pRefresh)
{
LPTVITEMDATA lptvid = reinterpret_cast<LPTVITEMDATA>(pRefresh->GetItemData());
ASSERT(lptvid);
if (lptvid == NULL)
return 1L;
bool bInternet=GetShellPidl().ComparePidls(NULL,lptvid->lpifq,m_pidlInternet);
if (GetParent())
GetParent()->SendMessage(WM_APP_UPDATE_ALL_VIEWS,HINT_TREE_INTERNET_FOLDER_SELECTED,(LPARAM)(bInternet ? 1 : 0));
if (bInternet == false)
Populate(lptvid);
}
}
return 1L;
}
LRESULT CIEShellListCtrl::OnSettingChange(WPARAM wParam,LPARAM lParam)
{
InitShellSettings();
Refresh();
LPCTSTR lpszSection=(LPCTSTR)lParam;
TRACE1("OnSettingsChange in CIEShellListCtrl with %s\n",lpszSection ? lpszSection : _T("null"));
return 1L;
}
BOOL CIEShellListCtrl::DoubleClick(NM_LISTVIEW* pNMListView)
{
// TODO: Add your specialized code here and/or call the base class
if (m_ShellSettings.DoubleClickInWebView())
{
ShellExecute(pNMListView->iItem);
return TRUE;
}
return CUIODListCtrl::DoubleClick(pNMListView);
}
BOOL CIEShellListCtrl::OnEnter(NM_LISTVIEW* pNMListView)
{
// TODO: Add your specialized code here and/or call the base class
ShellExecute(pNMListView->iItem);
return TRUE;
}
LRESULT CIEShellListCtrl::OnAppDeleteKey(WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
UINT nSize = GetSelectedCount()*MAX_PATH;
if (nSize == 0)
return 0L;
SetRefreshAllowed(false);
SHFILEOPSTRUCT shf;
ZeroMemory(&shf,sizeof(shf));
LPTSTR pszFrom=new TCHAR[nSize];
LPTSTR pszStartFrom=pszFrom;
ZeroMemory(pszFrom,nSize*sizeof(TCHAR));
CString sPath;
int item=-1;
while ((item = GetNextSel(item)) != -1)
{
sPath = GetPathName(item);
lstrcpy(pszFrom,(LPCTSTR)sPath);
pszFrom += sPath.GetLength()+1;
}
shf.hwnd = GetSafeHwnd();
shf.wFunc = FO_DELETE;
shf.pFrom = (LPCTSTR)pszStartFrom;
shf.fFlags = GetKeyState(VK_SHIFT) < 0 ? 0 : FOF_ALLOWUNDO;
if (SHFileOperation(&shf) != 0)
SetRefreshAllowed(true);
delete []pszStartFrom;
return 1L;
}
LRESULT CIEShellListCtrl::OnAppPropertiesKey(WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
if (GetSelectedCount() == 0)
return 0L;
SHELLEXECUTEINFO si;
ZeroMemory(&si,sizeof(si));
si.cbSize = sizeof(si);
si.hwnd = GetSafeHwnd();
si.nShow = SW_SHOW;
si.fMask = SEE_MASK_INVOKEIDLIST;
si.lpVerb = _T("properties");
int item=GetCurSel();
while ((item = GetNextSel(item)) != -1)
{
CString sPath(GetPathName(item));
si.lpFile = (LPCTSTR)sPath;
ShellExecuteEx(&si);
}
return 1L;
}
bool CIEShellListCtrl::EndLabelEdit(int nRow,int nCol,LPCTSTR pszText)
{
// TODO: Add your specialized code here and/or call the base class
if (nCol != 0)
return CUIODListCtrl::EndLabelEdit(nRow,nCol,pszText);
CString sFromPath(GetPathName(nRow));
CString sToPath;
CSplitPath path(sFromPath);
if (GetShellSettings().ShowExtensions())
{
CSplitPath file(pszText);
path.SetFileName(file.GetFileName());
path.SetExt(file.GetExt());
}
else
{
path.SetFileName(pszText);
}
path.Make();
sToPath = path.GetPath();
SHFILEOPSTRUCT shf;
TCHAR szFrom[MAX_PATH+1];
TCHAR szTo[MAX_PATH+1];
ZeroMemory(szFrom,sizeof(szFrom));
lstrcpy(szFrom,sFromPath);
ZeroMemory(szTo,sizeof(szTo));
lstrcpy(szTo,sToPath);
ZeroMemory(&shf,sizeof(shf));
shf.hwnd = GetSafeHwnd();
shf.wFunc = FO_RENAME;
shf.pFrom = szFrom;
shf.pTo = szTo;
#ifdef _DEBUG
CString sMess;
sMess = szFrom;
sMess += _T("\n");
sMess += szTo;
AfxMessageBox(sMess);
#endif
int nRet = SHFileOperation(&shf);
TRACE1("SHFileOperation returned %u\n",nRet);
return false;
}
void CIEShellListCtrl::GoBack(int nRow)
{
// TODO: Add your specialized code here and/or call the base class
AfxMessageBox(_T("Needs to be implemented"));
}
void CIEShellListCtrl::ChangeStyle(UINT &dwStyle)
{
// TODO: Add your specialized code here and/or call the base class
CUIODListCtrl::ChangeStyle(dwStyle);
dwStyle |= (LVS_SHAREIMAGELISTS | LVS_EDITLABELS);
}
LRESULT CIEShellListCtrl::OnSetmessagestring(WPARAM wParam, LPARAM lParam)
{
if (GetParent())
return GetParent()->SendMessage(WM_SETMESSAGESTRING,wParam,lParam);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -