IEShellListCtrl.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:41k
源码类别:

图形图象

开发平台:

Visual C++

  1. //*******************************************************************************
  2. // COPYRIGHT NOTES
  3. // ---------------
  4. // You may use this source code, compile or redistribute it as part of your application 
  5. // for free. You cannot redistribute it as a part of a software development 
  6. // library without the agreement of the author. If the sources are 
  7. // distributed along with the application, you should leave the original 
  8. // copyright notes in the source code without any changes.
  9. // This code can be used WITHOUT ANY WARRANTIES at your own risk.
  10. // 
  11. // For the latest updates to this code, check this site:
  12. // http://www.masmex.com 
  13. // after Sept 2000
  14. // 
  15. // Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
  16. //*******************************************************************************
  17. // IEShellListCtrl.cpp : implementation file
  18. #include "stdafx.h"
  19. #include "IEShellListCtrl.h"
  20. #include "UIMessages.h"
  21. #include "dirwalk.h"
  22. #include "cbformats.h"
  23. #include "..IRWEngineIRWEngine.h"
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. #ifdef _DEBUG
  30. #pragma comment(lib,"..\IRWEngine\Debug\IRWEngine.lib")
  31. #else
  32. #pragma comment(lib,"..\IRWEngine\Release\IRWEngine.lib")
  33. #endif
  34. COLORREF bkColor[15] = 
  35. RGB(255,255,255),
  36. RGB(255,255,255),
  37. RGB(255,255,255),
  38. RGB(255,255,255),
  39. RGB(255,255,255),
  40. RGB(255,255,255),
  41. RGB(255,255,255),
  42. RGB(255,255,255),
  43. RGB(255,255,255),
  44. RGB(255,255,255),
  45. RGB(255,255,255),
  46. RGB(255,255,255),
  47. RGB(255,255,255),
  48. RGB(255,255,255),
  49. RGB(255,255,255),
  50. };
  51. #define UMAKEINT64(low,high) ((unsigned __int64)(((DWORD)(low)) | ((unsigned __int64)((DWORD)(high))) << 32))
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CIEShellListCtrl
  54. CIEShellListCtrl::CIEShellListCtrl()
  55. {
  56. SetEditSubItems(false);
  57. SetDropFiles(false);
  58. ZeroMemory(&m_tvid,sizeof(m_tvid));
  59. m_psfSubFolder = NULL;
  60. m_pMalloc = NULL;
  61. m_bCallBack = false;
  62. m_bNoExt = false;
  63. m_nThreadCount = 0;
  64. m_bRefreshAllowed = true;
  65. m_bPopulateInit = false;
  66. m_bInitiliazed = false;
  67. m_bNotifyParent = false;
  68. m_pidlInternet = NULL;
  69. SHGetMalloc(&m_pMalloc);
  70. SHGetSpecialFolderLocation(NULL,CSIDL_INTERNET,&m_pidlInternet);
  71. m_sColumns = _T("名称|大小|类型|修改时间");
  72. }
  73. CIEShellListCtrl::~CIEShellListCtrl()
  74. {
  75. FreeTVID();
  76. AllItemsDeleted();
  77. if (m_pidlInternet)
  78. m_pMalloc->Release();
  79. if (m_pMalloc)
  80. m_pMalloc->Release();
  81. }
  82. void CIEShellListCtrl::PopupTheMenu(int nRow,CPoint point)
  83. {
  84. if (!GetSelectedCount())
  85. return;
  86. int nSel=-1;
  87. LPLVITEMDATA lplvid=NULL;
  88. LPITEMIDLIST *pidls=(LPITEMIDLIST*)GetShellPidl().GetMalloc()->Alloc(GetSelectedCount()*sizeof(LPITEMIDLIST));
  89. int i=0;
  90. while ((nSel = GetNextSel(nSel)) != -1)
  91. {
  92. lplvid=(LPLVITEMDATA)GetItemData(nSel);
  93. pidls[i] = lplvid->lpi;
  94. i++;
  95. }
  96. // at least one
  97. if (pidls && i)
  98. {
  99. GetShellPidl().PopupTheMenu(m_hWnd, lplvid->lpsfParent, pidls, i, &point);
  100. }
  101. GetShellPidl().Free(pidls);
  102. }
  103. void CIEShellListCtrl::ShellExecute(int nRow,LPCTSTR pszVerb)
  104. {
  105. SHELLEXECUTEINFO si;
  106. ZeroMemory(&si,sizeof(si));
  107. si.cbSize = sizeof(si);
  108. si.hwnd = GetSafeHwnd();
  109. si.nShow = SW_SHOW;
  110. si.lpIDList = (LPVOID)GetPathPidl(nRow);
  111. si.fMask  = SEE_MASK_INVOKEIDLIST;
  112. if (pszVerb)
  113. si.lpVerb = pszVerb;
  114. ShellExecuteEx(&si);
  115. }
  116. void CIEShellListCtrl::SetNotificationObject(bool bNotify)
  117. {
  118. if (bNotify)
  119. CreateFileChangeThread(GetSafeHwnd());
  120. else
  121. DestroyThreads();
  122. }
  123. void CIEShellListCtrl::FreeInterface(IUnknown *pInterface)
  124. {
  125. if (pInterface)
  126. pInterface->Release();
  127. }
  128. void CIEShellListCtrl::DestroyThreads()
  129. {
  130.     if (m_nThreadCount == 0) 
  131. return;
  132.     for (UINT i=0; i<m_nThreadCount; i++)
  133.     m_event[i].SetEvent();
  134.     ::WaitForMultipleObjects (m_nThreadCount, m_hThreads, TRUE, INFINITE);
  135.     for (i=0; i<m_nThreadCount; i++)
  136.         delete m_pThreads[i];
  137.     m_nThreadCount = 0;
  138. }
  139. void CIEShellListCtrl::FreeTVID()
  140. {
  141. if (m_tvid.lpsfParent)
  142. m_tvid.lpsfParent->Release();
  143. if (m_tvid.lpi)
  144. m_pMalloc->Free(m_tvid.lpi);
  145. if (m_tvid.lpifq)
  146. m_pMalloc->Free(m_tvid.lpifq);
  147. ZeroMemory(&m_tvid,sizeof(m_tvid));
  148. if (m_psfSubFolder)
  149. m_psfSubFolder->Release();
  150. m_psfSubFolder = NULL;
  151. }
  152. CString CIEShellListCtrl::GetCurrPathName()
  153. {
  154. return GetPathName(GetCurSel());
  155. }
  156. CString CIEShellListCtrl::GetPathName(int nRow)
  157. {
  158. if (nRow == -1)
  159. nRow = GetCurSel();
  160. CString sPath;
  161. if (nRow == -1)
  162. return sPath;
  163. LPLVITEMDATA plvit = (LPLVITEMDATA)GetItemData(nRow);
  164. ASSERT(plvit);
  165. if (plvit == NULL)
  166. return sPath;
  167. SHGetPathFromIDList(plvit->lpifq,sPath.GetBuffer(MAX_PATH));
  168. sPath.ReleaseBuffer();
  169. return sPath;
  170. }
  171. LPCITEMIDLIST CIEShellListCtrl::GetPathPidl(int nRow)
  172. {
  173. if (nRow == -1)
  174. return NULL;
  175. LPLVITEMDATA plvit = (LPLVITEMDATA)GetItemData(nRow);
  176. ASSERT(plvit);
  177. if (plvit == NULL)
  178. return NULL;
  179. return plvit->lpifq;
  180. }
  181. void CIEShellListCtrl::FillExcludedFileTypes(CComboBox &cb)
  182. {
  183. cb.ResetContent();
  184. for(POSITION pos=m_ExcludedLookup.GetHeadPosition();pos != NULL;m_ExcludedLookup.GetNext(pos))
  185. {
  186. cb.AddString(m_ExcludedLookup.GetAt(pos));
  187. }
  188. }
  189. void CIEShellListCtrl::SetExcludedFileTypes(CComboBox &cb)
  190. {
  191. m_ExcludedLookup.RemoveAll();
  192. CString sText;
  193. for(int i=0;i < cb.GetCount();i++)
  194. {
  195. cb.GetLBText(i,sText);
  196. m_ExcludedLookup.AddHead(sText);
  197. }
  198. }
  199. void CIEShellListCtrl::LoadFilterFiles(const CString &sFileFilter)
  200. {
  201. m_FilterLookup.RemoveAll();
  202. CFileFind ff;
  203. CString sPath;
  204. if (FAILED(GetShellPidl().SHPidlToPathEx(m_tvid.lpifq,sPath)))
  205. return;
  206. if (sPath.Right(1) != _T('\'))
  207. sPath += _T('\');
  208. CString sFindPath;
  209. CString sMask;
  210. LPCTSTR pszFilter=sFileFilter;
  211. pszFilter = GetFilterMask(pszFilter,sMask);
  212. while (pszFilter != NULL)
  213. {
  214. sFindPath = sPath;
  215. sFindPath += sMask;
  216. BOOL bFind = ff.FindFile(sFindPath);  
  217. while (bFind)
  218. {
  219. bFind = ff.FindNextFile();
  220. m_FilterLookup.AddHead(ff.GetFilePath());
  221. }
  222. pszFilter = GetFilterMask(pszFilter,sMask);
  223. }
  224. }
  225. LPCTSTR CIEShellListCtrl::GetFilterMask(LPCTSTR pszFilter,CString &sMask)
  226. {
  227. if (*pszFilter == '')
  228. return NULL;
  229. TCHAR szMask[MAX_PATH];
  230. szMask[0] = 0;
  231. for(int i=0;*pszFilter != '';i++)
  232. {
  233. if (*pszFilter == _T(';') || *pszFilter == _T(','))
  234. {
  235. pszFilter = _tcsinc(pszFilter);
  236. break;
  237. }
  238. szMask[i] = *pszFilter;
  239. pszFilter = _tcsinc(pszFilter);
  240. }
  241. szMask[i] = 0;
  242. sMask = szMask;
  243. return pszFilter;
  244. }
  245. void CIEShellListCtrl::AllItemsDeleted()
  246. {
  247. LPLVITEMDATA pItemData=NULL;
  248. for(vecListItemData::iterator it=m_vecItemData.begin();it != m_vecItemData.end();it++)
  249. {
  250. pItemData = *it;
  251. if (pItemData)
  252. {
  253. if (pItemData->lpsfParent)
  254. pItemData->lpsfParent->Release();
  255. if (pItemData->lpi)
  256. m_pMalloc->Free(pItemData->lpi);  
  257. if (pItemData->lpifq)
  258. m_pMalloc->Free(pItemData->lpifq);  
  259. if (pItemData->lParam)
  260. {
  261. PSLC_COLUMN_DATA pColData = (PSLC_COLUMN_DATA)pItemData->lParam;
  262. if (pColData->pidl)
  263. GetShellPidl().FreePidl(pColData->pidl);
  264. delete pColData;
  265. }
  266. //清除文件项的回执单
  267. if ( pItemData->pRReceipt )
  268. {
  269. //回执单的析构函数将自动清除各种资源
  270. //pItemData->pRReceipt->ClearImageBitData();
  271. delete pItemData->pRReceipt;
  272. }
  273. m_pMalloc->Free(pItemData);
  274. }
  275. }
  276. m_vecItemData.erase(m_vecItemData.begin(),m_vecItemData.end());
  277. }
  278. void CIEShellListCtrl::StartPopulate()
  279. {
  280. m_bPopulateInit = true;
  281. m_iProcessed = 0;
  282. DeleteAllItems();
  283. for(UINT i=0;i < m_nThreadCount;i++)
  284. m_MonitorEvent[i].SetEvent();
  285. if (m_sFileFilter.IsEmpty() || m_sFileFilter == _T("*.*") || m_sFileFilter == _T("*"))
  286. return;
  287. LoadFilterFiles(m_sFileFilter);
  288. }
  289. void CIEShellListCtrl::EndPopulate()
  290. {
  291. m_bPopulateInit = false;
  292. Sort();
  293. SetColumnWidths();
  294. }
  295. BOOL CIEShellListCtrl::Populate(LPTVITEMDATA lptvid)
  296. {
  297. IShellFolder *pFolder=NULL;
  298. BOOL bRet=FALSE;
  299. HRESULT hr=E_FAIL;
  300. if (lptvid->lpsfParent)
  301. {
  302. hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,0,IID_IShellFolder,(LPVOID*)&pFolder);
  303. }
  304. else
  305. {
  306. LPSHELLFOLDER psfDesktop;
  307. LPITEMIDLIST pidlDesktop=NULL;
  308. hr=SHGetDesktopFolder(&psfDesktop);
  309. SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOP,&pidlDesktop);
  310. if (GetShellPidl().ComparePidls(NULL,lptvid->lpifq,pidlDesktop))
  311. {
  312. pFolder = psfDesktop;
  313. }
  314. else
  315. {
  316. hr=psfDesktop->BindToObject(lptvid->lpifq,0,IID_IShellFolder,(LPVOID*)&pFolder);
  317. psfDesktop->Release();
  318. }
  319. if (pidlDesktop)
  320. GetShellPidl().FreePidl(pidlDesktop);
  321. }
  322. if (SUCCEEDED(hr))
  323. {
  324. bRet = Populate(lptvid,pFolder,true);
  325. pFolder->Release();
  326. }
  327. return bRet;
  328. }
  329. BOOL CIEShellListCtrl::Populate(LPCTSTR pszPath, bool bCallBack)
  330. {
  331. LPITEMIDLIST pidlfq=NULL;
  332. LPITEMIDLIST pidl=NULL;
  333. LPSHELLFOLDER pDesktop = NULL;
  334.     SHGetDesktopFolder(&pDesktop);
  335. if (FAILED(GetShellPidl().SHPathToPidlEx(pszPath,&pidlfq,pDesktop)))
  336. return FALSE;
  337. LPSHELLFOLDER pSubFolder = NULL;
  338. pidl = pidlfq; //add this by 阳光灿烂
  339. //i think the author forget this statment;
  340. if (FAILED(pDesktop->BindToObject(pidl, 0, IID_IShellFolder,(LPVOID*)&pSubFolder)))
  341. return FALSE;
  342. pidl = GetShellPidl().CopyLastItemID(pidlfq);
  343. TVITEMDATA tvid;
  344. tvid.lpifq = pidlfq;
  345. tvid.lpi = pidl;
  346. tvid.lpsfParent = NULL;
  347. BOOL bRet = Populate(&tvid,pSubFolder,bCallBack);
  348. if (pDesktop)
  349. pDesktop->Release();
  350. if (pSubFolder)
  351. pSubFolder->Release();
  352. if (pidl)
  353. m_pMalloc->Free(pidl);
  354. if (pidlfq)
  355. m_pMalloc->Free(pidlfq);
  356. return bRet;
  357. }
  358. BOOL CIEShellListCtrl::Populate(LPTVITEMDATA lptvid,LPSHELLFOLDER psfFolder,bool bCallBack)
  359. {
  360. m_bCallBack = bCallBack;
  361. FreeTVID();
  362. m_tvid.lpi = GetShellPidl().CopyItemIDList(lptvid->lpi);
  363. m_tvid.lpifq = GetShellPidl().CopyItemIDList(lptvid->lpifq);
  364. #ifdef _DEBUG
  365. CString sPath;
  366. GetShellPidl().SHPidlToPathEx(m_tvid.lpifq,sPath,NULL);
  367. TRACE1("Populating path %s in CIEShellListCtrln",sPath);
  368. #endif
  369. if (lptvid->lpsfParent)
  370. {
  371. m_tvid.lpsfParent = lptvid->lpsfParent;
  372. m_tvid.lpsfParent->AddRef();
  373. }
  374. m_psfSubFolder = psfFolder;
  375. m_psfSubFolder->AddRef();
  376. Load();
  377.     return TRUE;
  378. }
  379. CString CIEShellListCtrl::GetColumns()
  380. {
  381. SHELLDETAILS sd;
  382. LPTSTR pszHeader=NULL;
  383. CString sColumns;
  384. for(int i=0;SUCCEEDED(m_ShellDetails.GetDetailsOf(NULL,i,&sd));i++)
  385. {
  386. GetShellPidl().StrRetToStr(sd.str,&pszHeader,NULL);
  387. if (pszHeader)
  388. {
  389. TRACE1("Column found %sn",pszHeader);
  390. if (!sColumns.IsEmpty())
  391. sColumns += _T("|");
  392. sColumns += pszHeader;
  393. GetShellPidl().Free(pszHeader);
  394. pszHeader= NULL;
  395. }
  396. }
  397. return sColumns;
  398. }
  399. void CIEShellListCtrl::InitColumns()
  400. {
  401. CString sColumns = GetColumns();
  402. if (sColumns.IsEmpty())
  403. sColumns = m_sColumns;
  404. InitListCtrl(sColumns);
  405. }
  406. void CIEShellListCtrl::SetColumnWidths()
  407. {
  408. if (!m_bCallBack)
  409. {
  410. for(int i=0;i < GetColumnCount();i++)
  411. SetColumnWidth(i,LVSCW_AUTOSIZE);
  412. }
  413. }
  414. void CIEShellListCtrl::Refresh()
  415. {
  416. if (m_psfSubFolder==NULL)
  417. return;
  418. SetRefreshAllowed(false);
  419. SetRedraw(FALSE);
  420. int nCurSel = GetCurSel();
  421. TRACE(_T("Refreshing shell list controln"));
  422. Load();
  423. SetCurSel(nCurSel);
  424. LONG Result;
  425. OnSelChanged(nCurSel,&Result);
  426. SetRedraw(TRUE);
  427. SetRefreshAllowed(true);
  428. }
  429. void CIEShellListCtrl::Load()
  430. {
  431. CWaitCursor w;
  432.     if (!InitItems(&m_tvid,m_bCallBack))
  433.         return;
  434. }
  435. void CIEShellListCtrl::Init()
  436. {
  437. if (m_bInitiliazed)
  438. return;
  439. CUIODListCtrl::Init();
  440. InitShellSettings();
  441. InitImageLists();
  442. m_bInitiliazed = true;
  443. }
  444. BOOL CIEShellListCtrl::InitItems(LPTVITEMDATA lptvid, bool bCallBack)
  445. {
  446. CWaitCursor w;
  447. Init();
  448. ASSERT(m_psfSubFolder);
  449. if (m_psfSubFolder == NULL)
  450. return FALSE;
  451. // Try to initialize columns from shell
  452. m_ShellDetails.SetShellDetails(NULL);
  453. IShellFolder2 *pShellFolder2=NULL;
  454. HRESULT hr=m_psfSubFolder->QueryInterface(IID_IShellFolder2,(LPVOID*)&pShellFolder2);
  455. if (SUCCEEDED(hr))
  456. {
  457. LPUNKNOWN pUnk=NULL;
  458. if (SUCCEEDED(pShellFolder2->QueryInterface(IID_IUnknown,(LPVOID*)&pUnk)))
  459. {
  460. m_ShellDetails.SetShellDetails(pUnk);
  461. pUnk->Release();
  462. }
  463. m_ShellDetails.SetShellDetails((LPUNKNOWN)pShellFolder2);
  464. pShellFolder2->Release();
  465. }
  466. else
  467. {
  468. IShellDetails *pShellDetails=NULL;
  469. HRESULT hr = m_psfSubFolder->CreateViewObject(GetSafeHwnd(), IID_IShellDetails, (LPVOID*)&pShellDetails);
  470. if (SUCCEEDED(hr))
  471. {
  472. LPUNKNOWN pUnk=NULL;
  473. if (SUCCEEDED(pShellDetails->QueryInterface(IID_IUnknown,(LPVOID*)&pUnk)))
  474. {
  475. m_ShellDetails.SetShellDetails(pUnk);
  476. pUnk->Release();
  477. }
  478. pShellDetails->Release();
  479. }
  480. }
  481. InitColumns();
  482. DWORD dwExStyle = GetExStyle(); 
  483. if(!m_ShellSettings.DoubleClickInWebView()) 
  484. {
  485. dwExStyle |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT | LVS_EX_UNDERLINEHOT; 
  486. }
  487. else
  488. {
  489. dwExStyle &= ~LVS_EX_ONECLICKACTIVATE;
  490. dwExStyle &= ~LVS_EX_TRACKSELECT;
  491. dwExStyle &= ~LVS_EX_UNDERLINEHOT; 
  492. }
  493. SetExStyle(dwExStyle);
  494.     LPITEMIDLIST lpi=NULL;
  495.     LPENUMIDLIST lpe=NULL;
  496.     LPLVITEMDATA lplvid=NULL;
  497. LPSHELLFOLDER lpsf=m_psfSubFolder;
  498.     ULONG        ulFetched, ulAttrs;
  499.     HWND         hwnd=::GetParent(m_hWnd);
  500. DWORD dwFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;//add SHCONTF_FOLDERS flags by 阳光灿烂
  501.                                                      //use this can see folder.
  502. if (GetShellSettings().ShowAllObjects() && !GetShellSettings().ShowSysFiles())
  503. dwFlags |= SHCONTF_INCLUDEHIDDEN;
  504.     hr=lpsf->EnumObjects(hwnd,dwFlags, &lpe);
  505.     if (FAILED(hr))
  506. return FALSE;
  507. bool bEndPopulate=false;
  508. if (m_bPopulateInit == false)
  509. {
  510. StartPopulate();
  511. bEndPopulate = true;
  512. }
  513.     while (NO_ERROR==lpe->Next(1, &lpi, &ulFetched))
  514.     {
  515. ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_DISPLAYATTRMASK | SFGAO_CONTENTSMASK | SFGAO_REMOVABLE; 
  516.         lpsf->GetAttributesOf(1, (LPCITEMIDLIST*)&lpi, &ulAttrs);
  517. if (!FilterItem(lpsf,lpi,ulAttrs))
  518. {
  519.         m_pMalloc->Free(lpi);  // free PIDL the shell gave you
  520.     lpi=NULL;
  521. continue;
  522. }
  523.         lplvid = (LPLVITEMDATA)m_pMalloc->Alloc(sizeof(LVITEMDATA));
  524.         if (!lplvid)
  525.            break;
  526. ZeroMemory(lplvid,sizeof(LVITEMDATA));
  527. m_vecItemData.push_back(lplvid);
  528.         lplvid->ulAttribs=ulAttrs;
  529.         lplvid->lpifq=m_ShellPidl.ConcatPidl(lptvid->lpifq, lpi);
  530.         lplvid->lpsfParent=lpsf;
  531.         lplvid->lpsfParent->AddRef();
  532.         // Now make a copy of the ITEMIDLIST.
  533.         lplvid->lpi=m_ShellPidl.CopyItemID(lpi);
  534. // // Now set the color of this file.
  535. //   lplvid->rgbColor = 
  536. // Add the item to the list view control.   
  537. int nRow=-1;
  538. if (bCallBack)
  539. {
  540. nRow = AddCallBackItem((DWORD)lplvid,I_IMAGECALLBACK);
  541. if ((ulAttrs & SFGAO_COMPRESSED) && m_ShellSettings.ShowCompColor())
  542. SetTextColor(nRow,0,RGB(0,0,255));
  543. else
  544. SetDefaultTextColor(nRow,-1);
  545. }
  546. else
  547. {
  548. nRow = AddTextItem();
  549. if (nRow != -1)
  550. {
  551. TCHAR szText[MAX_PATH+1];
  552. SetItemData(nRow,(DWORD)lplvid);
  553. LV_DISPINFO dsp;
  554. ZeroMemory(&dsp,sizeof(LV_DISPINFO));
  555. dsp.item.mask |= (LVIF_TEXT | LVIF_IMAGE);
  556. for(int i=0; i < GetColumnCount();i++)
  557. {
  558. szText[0] = 0;
  559. dsp.item.iItem = nRow;
  560. dsp.item.iSubItem = i;
  561. dsp.item.cchTextMax = MAX_PATH;
  562. dsp.item.pszText = szText;
  563. if (i > 0)
  564. dsp.item.mask &= ~LVIF_IMAGE;
  565. m_bCallBack = true;
  566. GetDispInfo(&dsp);
  567. m_bCallBack = false;
  568. SetIcon(nRow,dsp.item.iImage);
  569. AddString(nRow,i,szText);
  570. }
  571. }
  572. }
  573.         m_pMalloc->Free(lpi);  // free PIDL the shell gave you
  574.         lpi=NULL;
  575.     }
  576.     if (lpe)  
  577.         lpe->Release();
  578.     // The following two if statements will be TRUE only if you got here
  579.     // on an error condition from the goto statement.  Otherwise, free 
  580.     // this memory at the end of the while loop above.
  581.     if (lpi)           
  582.         m_pMalloc->Free(lpi);
  583.  
  584. if (bEndPopulate)
  585. EndPopulate();
  586.     return TRUE;
  587. }
  588. bool CIEShellListCtrl::FilterItem(LPSHELLFOLDER pFolder,LPCITEMIDLIST pidl,UINT ulAttrs)
  589. {
  590. if ((m_sFileFilter.IsEmpty() || m_sFileFilter == _T("*.*") || m_sFileFilter == _T("*"))
  591. && m_ExcludedLookup.IsEmpty())
  592. return true;
  593. bool bRet=false;
  594. if (m_sFileFilter == _T("*.*") || m_sFileFilter == _T("*"))
  595. {
  596. bRet=true;
  597. }
  598. else if (!m_sFileFilter.IsEmpty())
  599. {
  600. CString sPath;
  601. GetShellPidl().SHPidlToPathEx(pidl,sPath,pFolder);
  602. if (m_FilterLookup.Find(sPath))
  603. bRet = true;
  604. }
  605. if (bRet == false)
  606. return bRet;
  607. if (!m_ExcludedLookup.IsEmpty())
  608. {
  609. SHFILEINFO fileInfo;
  610. ZeroMemory(&fileInfo,sizeof(fileInfo));
  611. SHGetFileInfo((LPCTSTR)pidl, NULL, &fileInfo, sizeof(fileInfo), SHGFI_PIDL|SHGFI_TYPENAME);
  612. if (m_ExcludedLookup.Find(fileInfo.szTypeName))
  613. {
  614. bRet = false;
  615. }
  616. }
  617. return bRet;
  618. }
  619. void CIEShellListCtrl::InitShellSettings()
  620. {
  621. m_ShellSettings.GetSettings();
  622. }  
  623. BOOL CIEShellListCtrl::InitImageLists()
  624. {
  625.     HIMAGELIST himlSmall;
  626.     HIMAGELIST himlLarge;
  627.     SHFILEINFO sfi;
  628.     BOOL       bSuccess=TRUE;
  629.     himlSmall = (HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C:\"), 
  630.                                            0,
  631.                                            &sfi, 
  632.                                            sizeof(SHFILEINFO), 
  633.                                            SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  634.     himlLarge = (HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C:\"), 
  635.                                            0,
  636.                                            &sfi, 
  637.                                            sizeof(SHFILEINFO), 
  638.                                            SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
  639.     if (himlSmall && himlLarge)
  640.     {
  641.         ::SendMessage(GetSafeHwnd(), LVM_SETIMAGELIST, (WPARAM)LVSIL_SMALL,
  642.             (LPARAM)himlSmall);
  643.         ::SendMessage(GetSafeHwnd(), LVM_SETIMAGELIST, (WPARAM)LVSIL_NORMAL,
  644.             (LPARAM)himlLarge);
  645.     }
  646.     else
  647.        bSuccess = FALSE;
  648.     return bSuccess;
  649. }
  650. BEGIN_MESSAGE_MAP(CIEShellListCtrl, CUIODListCtrl)
  651. //{{AFX_MSG_MAP(CIEShellListCtrl)
  652. ON_MESSAGE(WM_SETMESSAGESTRING,OnSetmessagestring)
  653. ON_MESSAGE(WM_SETTINGCHANGE,OnSettingChange)
  654. // NOTE - the ClassWizard will add and remove mapping macros here.
  655. ON_WM_DESTROY()
  656. ON_WM_MENUSELECT()
  657. //}}AFX_MSG_MAP
  658. ON_MESSAGE(WM_APP_ON_DELETE_KEY,OnAppDeleteKey)
  659. ON_MESSAGE(WM_APP_ON_PROPERTIES_KEY,OnAppPropertiesKey)
  660. ON_MESSAGE(WM_APP_UPDATE_ALL_VIEWS,OnAppUpdateAllViews)
  661. ON_MESSAGE(WM_APP_FILE_CHANGE_NEW_PATH,OnAppFileChangeNewPath)
  662. ON_MESSAGE(WM_APP_FILE_CHANGE_EVENT,OnAppFileChangeEvent)
  663. END_MESSAGE_MAP()
  664. /////////////////////////////////////////////////////////////////////////////
  665. // CIEShellListCtrl message handlers
  666. void CIEShellListCtrl::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
  667. {
  668. CUIODListCtrl::OnMenuSelect(nItemID,nFlags,hSysMenu);
  669. }
  670. void CIEShellListCtrl::ShowPopupMenu(int nRow,int nCol,CPoint point)
  671. {
  672. if ((nCol > 0 || nRow == -1) || (m_PopupID || m_MultiPopupID))
  673. {
  674. CUIODListCtrl::ShowPopupMenu(nRow,nCol,point);
  675. return;
  676. }
  677. PopupTheMenu(nRow,point);
  678. }
  679. void CIEShellListCtrl::OnDestroy()
  680. {
  681. SetImageList(NULL,LVSIL_SMALL);
  682. SetImageList(NULL,LVSIL_NORMAL);
  683. DestroyThreads();
  684. CUIODListCtrl::OnDestroy();
  685. }
  686. bool CIEShellListCtrl::UseShellColumns()
  687. {
  688. return m_ShellDetails.IsValidDetails();
  689. }
  690. BOOL CIEShellListCtrl::GetDispInfo(LV_DISPINFO *pDispInfo)
  691. {
  692. // TODO: Add your specialized code here and/or call the base class
  693. if (m_psfSubFolder == NULL || m_bCallBack == false)
  694. return CUIODListCtrl::GetDispInfo(pDispInfo);
  695. LPLVITEMDATA lplvid = (LPLVITEMDATA)GetItemData(pDispInfo->item.iItem);
  696. ASSERT(lplvid);
  697. if (lplvid == NULL)
  698. return FALSE;
  699. PSLC_COLUMN_DATA pColData=(PSLC_COLUMN_DATA)lplvid->lParam;
  700. if (pColData == NULL)
  701. {
  702. pColData = new SLC_COLUMN_DATA;
  703. pColData->sItems.SetSize(GetColumnCount());
  704. lplvid->lParam = (LPARAM)pColData;
  705. }
  706. if (pColData->pidl == NULL)
  707. pColData->pidl = m_ShellPidl.ConcatPidl(m_tvid.lpifq, lplvid->lpi);
  708. if (pDispInfo->item.mask & LVIF_IMAGE)
  709. {
  710. if (pColData->iImage == -1)
  711. {
  712. pColData->iImage = m_ShellPidl.GetIcon(pColData->pidl,SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  713. }
  714. pDispInfo->item.iImage = pColData->iImage;
  715. if (lplvid->ulAttribs & SFGAO_GHOSTED)
  716. {
  717. pDispInfo->item.mask |= LVIF_STATE;
  718. pDispInfo->item.stateMask = LVIS_CUT;
  719. pDispInfo->item.state = LVIS_CUT;
  720. }
  721. if (lplvid->ulAttribs & SFGAO_LINK)
  722. {
  723. pDispInfo->item.mask |= LVIF_STATE;
  724. pDispInfo->item.stateMask = LVIS_OVERLAYMASK;
  725. pDispInfo->item.state = INDEXTOOVERLAYMASK(2);
  726. }
  727. if (lplvid->ulAttribs & SFGAO_SHARE)
  728. {
  729. pDispInfo->item.mask |= LVIF_STATE;
  730. pDispInfo->item.stateMask = LVIS_OVERLAYMASK;
  731. pDispInfo->item.state = INDEXTOOVERLAYMASK(1);
  732. }
  733. }
  734. if (pDispInfo->item.mask & LVIF_TEXT)
  735. {
  736. if (UseShellColumns())
  737. {
  738. if (pDispInfo->item.iSubItem == COL_NAME)
  739. {
  740. if (pColData->sItems[pDispInfo->item.iSubItem].IsEmpty())
  741. m_ShellPidl.GetName(lplvid->lpsfParent, lplvid->lpi, SHGDN_NORMAL, pColData->sItems[pDispInfo->item.iSubItem]);
  742. _tcscpy(pDispInfo->item.pszText,pColData->sItems[pDispInfo->item.iSubItem]);
  743. if (m_bNoExt)
  744. RemoveExt(pDispInfo->item.pszText);
  745. }
  746. else
  747. {
  748. if (pColData->sItems[pDispInfo->item.iSubItem].IsEmpty())
  749. {
  750. SHELLDETAILS sd;
  751. ZeroMemory(&sd,sizeof(sd));
  752. HRESULT hr = m_ShellDetails.GetDetailsOf(lplvid->lpi,pDispInfo->item.iSubItem,&sd);
  753. LPTSTR pszText=NULL;
  754. GetShellPidl().StrRetToStr(sd.str,&pszText,lplvid->lpi);
  755. if (pszText)
  756. {
  757. _tcscpy(pDispInfo->item.pszText,pszText);
  758. GetShellPidl().Free(pszText);
  759. }
  760. }
  761. else
  762. {
  763. _tcscpy(pDispInfo->item.pszText,pColData->sItems[pDispInfo->item.iSubItem]);
  764. }
  765. }
  766. }
  767. else
  768. {
  769. GetText(pColData,pDispInfo,lplvid);
  770. }
  771. }
  772. return TRUE;
  773. }
  774. bool CIEShellListCtrl::GetColText(int nCol,LPCITEMIDLIST pidlAbs,LPLVITEMDATA lplvid,CString &sText)
  775. {
  776. return false;
  777. }
  778. void CIEShellListCtrl::GetText(PSLC_COLUMN_DATA pColData,LV_DISPINFO *pDispInfo,LPLVITEMDATA lplvid)
  779. {
  780. if (!pColData->sItems[pDispInfo->item.iSubItem].IsEmpty())
  781. {
  782. _tcscpy(pDispInfo->item.pszText,pColData->sItems[pDispInfo->item.iSubItem]);
  783. return;
  784. }
  785. LPITEMIDLIST pidlAbs = pColData->pidl;
  786. CString sText;
  787. if (GetColText(pDispInfo->item.iSubItem,pidlAbs,lplvid,sText))
  788. {
  789. pColData->sItems[pDispInfo->item.iSubItem] = sText;
  790. _tcscpy(pDispInfo->item.pszText,pColData->sItems[pDispInfo->item.iSubItem]);
  791. return;
  792. }
  793. if (pDispInfo->item.iSubItem == COL_NAME)
  794. {
  795. if (pColData->sItems[pDispInfo->item.iSubItem].IsEmpty())
  796. m_ShellPidl.GetName(lplvid->lpsfParent, lplvid->lpi, SHGDN_NORMAL,pColData->sItems[pDispInfo->item.iSubItem]);
  797. _tcscpy(pDispInfo->item.pszText,pColData->sItems[pDispInfo->item.iSubItem]);
  798. if (m_bNoExt)
  799. RemoveExt(pDispInfo->item.pszText);
  800. }
  801. else if (pDispInfo->item.iSubItem == COL_TYPE)
  802. {
  803. if (pColData->sItems[pDispInfo->item.iSubItem].IsEmpty())
  804. {
  805. SHFILEINFO fileInfo;
  806. if (SHGetFileInfo((LPCTSTR)lplvid->lpi, NULL, &fileInfo, sizeof(fileInfo), SHGFI_PIDL|SHGFI_TYPENAME))
  807. {
  808. pColData->sItems[pDispInfo->item.iSubItem] = fileInfo.szTypeName;
  809. }
  810. }
  811. _tcscpy(pDispInfo->item.pszText,pColData->sItems[pDispInfo->item.iSubItem]);
  812. }
  813. else if (pDispInfo->item.iSubItem == COL_SIZE || pDispInfo->item.iSubItem == COL_MODIFIED)
  814. {
  815. if (pColData->sItems[COL_SIZE].IsEmpty() || (pColData->sItems[COL_MODIFIED].IsEmpty()))
  816. {
  817. CString sSize;
  818. CString sDateTime;
  819. GetFileDetails(pidlAbs,sSize,sDateTime);
  820. if (pDispInfo->item.iSubItem == COL_SIZE)
  821. pColData->sItems[pDispInfo->item.iSubItem] = sSize;
  822. else if (pDispInfo->item.iSubItem == COL_MODIFIED)
  823. pColData->sItems[pDispInfo->item.iSubItem] = sDateTime;
  824. }
  825. if (pDispInfo->item.iSubItem == COL_SIZE)
  826. _tcscpy(pDispInfo->item.pszText,pColData->sItems[pDispInfo->item.iSubItem]);
  827. else if (pDispInfo->item.iSubItem == COL_MODIFIED)
  828. _tcscpy(pDispInfo->item.pszText,pColData->sItems[pDispInfo->item.iSubItem]);
  829. }
  830. }
  831. void CIEShellListCtrl::GetFileDetails(LPCITEMIDLIST pidl, CString &sSize, CString &sDateTime)
  832. {
  833. CString sPath;
  834. GetShellPidl().SHPidlToPathEx((LPITEMIDLIST)pidl,sPath,NULL);
  835. if (sPath.GetLength() <= 3)
  836. return;
  837. WIN32_FIND_DATA FindFileData;
  838.     HANDLE hFind = FindFirstFile(sPath,&FindFileData);
  839.     if (hFind != INVALID_HANDLE_VALUE)
  840. {
  841. if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  842. {
  843. unsigned __int64 fs = UMAKEINT64(FindFileData.nFileSizeLow, FindFileData.nFileSizeHigh);
  844. unsigned __int64 kb=1;
  845. TCHAR szText[1024];
  846. if (fs > 1024)
  847. {
  848. kb = fs / 1024;
  849. if (fs % 1024)
  850. kb++;
  851. }
  852. _ui64tot(kb,szText,10);
  853. sSize = szText;
  854. AddThousandSeps(sSize);
  855. sSize += _T(" KB");
  856. }
  857. if ((FindFileData.ftLastWriteTime.dwLowDateTime != 0) || (FindFileData.ftLastWriteTime.dwHighDateTime != 0))
  858. {
  859. sDateTime = CLocaleInfo::Instance()->FormatDateTime(FindFileData.ftLastWriteTime);
  860. }
  861. else
  862. {
  863. sDateTime = CLocaleInfo::Instance()->FormatDateTime(FindFileData.ftCreationTime);
  864. }
  865.     FindClose(hFind);
  866. }
  867. }
  868. void CIEShellListCtrl::RemoveExt(LPTSTR pszFileName)
  869. {
  870. if (pszFileName == NULL)
  871. return;
  872. LPTSTR pExtPos=NULL;
  873. LPTSTR pEndPos = pszFileName+lstrlen(pszFileName);
  874. LPTSTR pStartPos = pszFileName;
  875. while (pEndPos > pStartPos)
  876. {
  877. if (*pEndPos == '.')
  878. {
  879. pExtPos = pEndPos;
  880. break;
  881. }
  882. pEndPos = _tcsdec(pStartPos,pEndPos);
  883. }
  884. if (pExtPos)
  885. *pExtPos = '';
  886. }
  887. int CALLBACK ShellCompareFunc(LPARAM lparam1, 
  888.                                  LPARAM lparam2,
  889.                                  LPARAM lparamSort);
  890. PFNLVCOMPARE CIEShellListCtrl::GetCompareFunc()
  891. {
  892. if (m_bCallBack)
  893. return ShellCompareFunc;
  894. return CUIODListCtrl::GetCompareFunc();
  895. }
  896. int CALLBACK ShellCompareFunc(LPARAM lParam1, 
  897.                          LPARAM lParam2,
  898.                          LPARAM lParamSort)
  899. {
  900. CUIListCtrlData *pData1 = (CUIListCtrlData*)lParam1;
  901. CUIListCtrlData *pData2 = (CUIListCtrlData*)lParam2;
  902.     LPLVITEMDATA lplvid1=(LPLVITEMDATA)pData1->GetExtData();
  903.     LPLVITEMDATA lplvid2=(LPLVITEMDATA)pData2->GetExtData();
  904. CUIODListCtrlSortInfo *pSortInfo = (CUIODListCtrlSortInfo*)lParamSort;
  905. int nRet=0;
  906. HRESULT hr = lplvid1->lpsfParent->CompareIDs(pSortInfo->GetColumn(),lplvid1->lpi,lplvid2->lpi);
  907.     if (SUCCEEDED(hr))
  908. nRet = (short)hr;
  909. if (!pSortInfo->Ascending())
  910. nRet = -nRet;
  911. return nRet;
  912. }
  913. /////////////////////////////////////////////////////////////////////////
  914. // Thread function for detecting file system changes
  915. UINT CIEShellListCtrl::ThreadFunc (LPVOID pParam)
  916. {
  917. ///////////////////////
  918.     PFC_THREADINFO pThreadInfo = (PFC_THREADINFO)pParam;
  919.     HANDLE hEvent = pThreadInfo->hEvent;
  920.     HANDLE hMonitorEvent = pThreadInfo->hMonitorEvent;
  921. CIEShellListCtrl *pListCtrl = pThreadInfo->pListCtrl;
  922.     HWND hWnd = pListCtrl->GetSafeHwnd();
  923.     delete pThreadInfo;
  924. ////////////////////////
  925. TCHAR szPath[MAX_PATH];
  926.     int nHandles=2;
  927. int nRet=0;
  928. HANDLE hFileChange=NULL;
  929.     HANDLE aHandles[3];
  930. aHandles[0] = hMonitorEvent;
  931.     aHandles[1] = hEvent;
  932. aHandles[2] = NULL;
  933.     BOOL bContinue = TRUE;
  934.     // Sleep until a file change notification wakes this thread or
  935.     // m_event becomes set indicating it's time for the thread to end.
  936.     while (bContinue)
  937. {
  938. TRACE(_T("ListControl waiting for %u multiple objectsn"),nHandles);
  939.         DWORD dw = ::WaitForMultipleObjects (nHandles, aHandles, FALSE, INFINITE);
  940. if (dw >= WAIT_ABANDONED && dw <= (WAIT_ABANDONED+(nHandles-1)))
  941. {
  942. TRACE(_T("ListControl waiting abandonedn"),nHandles);
  943. break;
  944. }
  945. // Reset Event
  946.         if(dw - WAIT_OBJECT_0 == 0) 
  947. {
  948. if (hFileChange && hFileChange != INVALID_HANDLE_VALUE)
  949. ::FindCloseChangeNotification(hFileChange);
  950. if (::SendMessage(hWnd, WM_APP_FILE_CHANGE_NEW_PATH, (WPARAM)szPath, 0))
  951. {
  952. if (szPath[0] == 0)
  953. {
  954. TRACE(_T("File notify path was returned emptyn"));
  955. hFileChange = NULL;
  956. aHandles[2] = hFileChange;
  957. continue;
  958. }
  959. TRACE(_T("File notify path returned %sn"),szPath);
  960.     hFileChange = ::FindFirstChangeNotification (szPath, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE);
  961.     if (hFileChange == INVALID_HANDLE_VALUE)
  962. {
  963. TRACE(_T("File notify thread was unable to create notification objectn"));
  964. hFileChange = NULL;
  965. aHandles[2] = hFileChange;
  966. continue;
  967. }
  968. else
  969. {
  970. if (nHandles == 2)
  971. {
  972. TRACE(_T("File notify thread has created the notification object for the first timen"));
  973. nHandles++;
  974. }
  975. TRACE(_T("File notify thread has created the notification objectn"));
  976. aHandles[2] = hFileChange;
  977. }
  978. }
  979. }
  980. // End Event
  981.         else if(dw - WAIT_OBJECT_0 == 1) 
  982. {
  983.             bContinue = FALSE;
  984. TRACE(_T("File Notify Thread was signalled to stopn"));
  985. }
  986. // File Change Event
  987.         else if (dw - WAIT_OBJECT_0 == 2) 
  988. { // Respond to a change notification.
  989.             ::FindNextChangeNotification (hFileChange);
  990. TRACE(_T("-- File notify event was fired in CIEShellListCtrl --n"));
  991. if (pListCtrl->RefreshAllowed())
  992. {
  993. ::PostMessage (hWnd, WM_APP_FILE_CHANGE_EVENT,0,0);
  994. }
  995. else
  996. {
  997. TRACE(_T("but not sending as refreshingn"));
  998. pListCtrl->SetRefreshAllowed(true);
  999. TRACE(_T("Refresh is now allowedn"));
  1000. }
  1001.         }
  1002.     }
  1003. if (hFileChange && hFileChange != INVALID_HANDLE_VALUE)
  1004. ::FindCloseChangeNotification (hFileChange);
  1005. TRACE(_T("File Notify Thread is endingn"));
  1006.     return nRet;
  1007. }
  1008. LRESULT CIEShellListCtrl::OnAppFileChangeNewPath(WPARAM wParam, LPARAM lParam)
  1009. {
  1010. ASSERT(wParam);
  1011. SHGetPathFromIDList(m_tvid.lpifq,(LPTSTR)wParam);
  1012. return 1;
  1013. }
  1014. LRESULT CIEShellListCtrl::OnAppFileChangeEvent(WPARAM wParam, LPARAM lParam)
  1015. {
  1016. if (!RefreshAllowed())
  1017. return 1L;
  1018. Refresh();
  1019. if (m_bNotifyParent)
  1020. GetParent()->SendMessage(WM_APP_UPDATE_ALL_VIEWS,(WPARAM)HINT_SHELL_FILE_CHANGED,(LPARAM)(LPCTSTR)m_sMonitorPath);
  1021. return 1L;
  1022. }
  1023. void CIEShellListCtrl::PreSubclassWindow()
  1024. {
  1025. CUIODListCtrl::PreSubclassWindow();
  1026. CreateFileChangeThread(GetSafeHwnd());
  1027. }
  1028. void CIEShellListCtrl::CreateFileChangeThread(HWND hwnd)
  1029. {
  1030. if (m_nThreadCount >= MAX_THREADS)
  1031. return;
  1032.     PFC_THREADINFO pThreadInfo = new FC_THREADINFO; // Thread will delete
  1033.     pThreadInfo->hMonitorEvent = m_MonitorEvent[m_nThreadCount].m_hObject;
  1034.     pThreadInfo->hEvent = m_event[m_nThreadCount].m_hObject;
  1035.     pThreadInfo->pListCtrl = this;
  1036.     CWinThread* pThread = AfxBeginThread (ThreadFunc, pThreadInfo,
  1037.         THREAD_PRIORITY_IDLE);
  1038.     pThread->m_bAutoDelete = FALSE;
  1039.     m_hThreads[m_nThreadCount] = pThread->m_hThread;
  1040.     m_pThreads[m_nThreadCount++] = pThread;
  1041. }
  1042. bool CIEShellListCtrl::DragDrop(CDD_OleDropTargetInfo *pInfo)
  1043. {
  1044. // TODO: Add your specialized code here and/or call the base class
  1045. return m_ShellDragDrop.DragDrop(pInfo,m_tvid.lpsfParent,m_tvid.lpi);
  1046. }
  1047. bool CIEShellListCtrl::DragEnter(CDD_OleDropTargetInfo *pInfo)
  1048. {
  1049. // TODO: Add your specialized code here and/or call the base class
  1050. return m_ShellDragDrop.DragEnter(pInfo,m_tvid.lpsfParent,m_tvid.lpi);
  1051. }
  1052. bool CIEShellListCtrl::DragLeave(CDD_OleDropTargetInfo *pInfo)
  1053. {
  1054. // TODO: Add your specialized code here and/or call the base class
  1055. return m_ShellDragDrop.DragLeave(pInfo);
  1056. }
  1057. bool CIEShellListCtrl::DragOver(CDD_OleDropTargetInfo *pInfo)
  1058. {
  1059. // TODO: Add your specialized code here and/or call the base class
  1060. return m_ShellDragDrop.DragOver(pInfo,m_tvid.lpsfParent,m_tvid.lpi);
  1061. }
  1062. // When the use starts a drag drop source
  1063. DROPEFFECT CIEShellListCtrl::DoDragDrop(int *pnRows,COleDataSource *pOleDataSource)
  1064. {
  1065. CShellPidl pidl;
  1066. CCF_ShellIDList sl;
  1067. CCF_HDROP cf_hdrop;
  1068. CCF_String cf_text;
  1069. cf_hdrop.AddDropPoint(CPoint(),FALSE);
  1070. CString sPath;
  1071. CString sText;
  1072. LPLVITEMDATA plvid=NULL;
  1073. if (GetShellPidl().IsDesktopFolder(m_psfSubFolder))
  1074. sl.AddPidl(GetShellPidl().GetEmptyPidl());
  1075. else
  1076. sl.AddPidl(m_tvid.lpifq);
  1077. for(int i=0;*pnRows != -1;i++)
  1078. {
  1079. plvid = (LPLVITEMDATA)GetItemData(*pnRows);
  1080. ASSERT(plvid);
  1081. sl.AddPidl(plvid->lpi);
  1082. pidl.SHPidlToPathEx(plvid->lpi,sPath,plvid->lpsfParent);
  1083. cf_hdrop.AddFileName(sPath);
  1084. sText += sPath;
  1085. sText += _T("n");
  1086. pnRows++;
  1087. }
  1088. cf_text.SetString(sText);
  1089. if (i > 0)
  1090. {
  1091. CWDClipboardData::Instance()->SetData(pOleDataSource,&cf_text,CWDClipboardData::e_cfString);
  1092. CWDClipboardData::Instance()->SetData(pOleDataSource,&sl,CWDClipboardData::e_cfShellIDList);
  1093. CWDClipboardData::Instance()->SetData(pOleDataSource,&cf_hdrop,CWDClipboardData::e_cfHDROP);
  1094. }
  1095. return GetShellPidl().GetDragDropAttributes(plvid);
  1096. }
  1097. LRESULT CIEShellListCtrl::OnAppUpdateAllViews(WPARAM wParam, LPARAM lParam)
  1098. {
  1099. if (wParam == HINT_TREE_SEL_CHANGED)
  1100. {
  1101. ASSERT(lParam);
  1102. const CRefreshShellFolder *pRefresh = reinterpret_cast<CRefreshShellFolder*>(lParam);
  1103. if (pRefresh)
  1104. {
  1105. LPTVITEMDATA lptvid = reinterpret_cast<LPTVITEMDATA>(pRefresh->GetItemData());
  1106. ASSERT(lptvid);
  1107. if (lptvid == NULL)
  1108. return 1L;
  1109. bool bInternet=GetShellPidl().ComparePidls(NULL,lptvid->lpifq,m_pidlInternet);
  1110. if (GetParent())
  1111. GetParent()->SendMessage(WM_APP_UPDATE_ALL_VIEWS,HINT_TREE_INTERNET_FOLDER_SELECTED,(LPARAM)(bInternet ? 1 : 0));
  1112. if (bInternet == false)
  1113. Populate(lptvid);
  1114. }
  1115. }
  1116. return 1L;
  1117. }
  1118. LRESULT CIEShellListCtrl::OnSettingChange(WPARAM wParam,LPARAM lParam)
  1119. InitShellSettings();
  1120. Refresh();
  1121. LPCTSTR lpszSection=(LPCTSTR)lParam;
  1122. TRACE1("OnSettingsChange in CIEShellListCtrl with %sn",lpszSection ? lpszSection : _T("null"));
  1123. return 1L; 
  1124. }  
  1125. BOOL CIEShellListCtrl::DoubleClick(NM_LISTVIEW* pNMListView)
  1126. {
  1127. //修改此函数以便双击目录时可以直接在listctrl中打开,并实现与TreeCtrl的互动。  阳光灿烂
  1128. /* if (m_ShellSettings.DoubleClickInWebView())
  1129. {
  1130. ShellExecute(pNMListView->iItem);
  1131. return TRUE;
  1132. }
  1133. */
  1134. //是否无效点击
  1135. if ( pNMListView->iItem < 0 || pNMListView->iItem > GetItemCount() )
  1136. return TRUE;
  1137. //取对应的路径
  1138. CString szPath = GetPathName( pNMListView->iItem );
  1139. //取对应的pidl
  1140. LPITEMIDLIST pidlSel = (LPITEMIDLIST) GetPathPidl( pNMListView->iItem );
  1141. //判断是否为目录
  1142. DWORD dwResult;
  1143. dwResult = GetFileAttributes( szPath );
  1144. dwResult &= FILE_ATTRIBUTE_DIRECTORY;
  1145. if ( dwResult ) //is dir
  1146. {
  1147. Populate( szPath , true );
  1148. //打开对应的TreeCtrl
  1149. UINT mess = WM_APP_CB_IE_HIT_ENTER;
  1150. if (m_hTreeWnd)
  1151. ::SendMessage(m_hTreeWnd,mess,(WPARAM)pidlSel,(LPARAM)(LPCTSTR)szPath);
  1152. }
  1153. else
  1154. ShellExecute( pNMListView->iItem );
  1155. return TRUE;
  1156. }
  1157. BOOL CIEShellListCtrl::OnEnter(NM_LISTVIEW* pNMListView)
  1158. {
  1159. // TODO: Add your specialized code here and/or call the base class
  1160. ShellExecute(pNMListView->iItem);
  1161. return TRUE;
  1162. }
  1163. LRESULT CIEShellListCtrl::OnAppDeleteKey(WPARAM wParam, LPARAM lParam)
  1164. {
  1165. // TODO: Add your specialized code here and/or call the base class
  1166. UINT nSize = GetSelectedCount()*MAX_PATH;
  1167. if (nSize == 0)
  1168. return 0L;
  1169. SetRefreshAllowed(false);
  1170. SHFILEOPSTRUCT shf;
  1171. ZeroMemory(&shf,sizeof(shf));
  1172. LPTSTR pszFrom=new TCHAR[nSize];
  1173. LPTSTR pszStartFrom=pszFrom;
  1174. ZeroMemory(pszFrom,nSize*sizeof(TCHAR));
  1175. CString sPath;
  1176. int item=-1;
  1177. while ((item = GetNextSel(item)) != -1)
  1178. {
  1179. sPath = GetPathName(item);
  1180. lstrcpy(pszFrom,(LPCTSTR)sPath);
  1181. pszFrom += sPath.GetLength()+1;
  1182. }
  1183. shf.hwnd = GetSafeHwnd();
  1184. shf.wFunc = FO_DELETE;
  1185. shf.pFrom = (LPCTSTR)pszStartFrom;
  1186. shf.fFlags = GetKeyState(VK_SHIFT) < 0 ? 0 : FOF_ALLOWUNDO;
  1187. if (SHFileOperation(&shf) != 0)
  1188. SetRefreshAllowed(true);
  1189. delete []pszStartFrom;
  1190. return 1L;
  1191. }
  1192. LRESULT CIEShellListCtrl::OnAppPropertiesKey(WPARAM wParam, LPARAM lParam)
  1193. {
  1194. // TODO: Add your specialized code here and/or call the base class
  1195. if (GetSelectedCount() == 0)
  1196. return 0L;
  1197. SHELLEXECUTEINFO si;
  1198. ZeroMemory(&si,sizeof(si));
  1199. si.cbSize = sizeof(si);
  1200. si.hwnd = GetSafeHwnd();
  1201. si.nShow = SW_SHOW;
  1202. si.fMask  = SEE_MASK_INVOKEIDLIST;
  1203. si.lpVerb = _T("properties");
  1204. int item=GetCurSel();
  1205. while ((item = GetNextSel(item)) != -1)
  1206. {
  1207. CString sPath(GetPathName(item));
  1208. si.lpFile = (LPCTSTR)sPath;
  1209. ShellExecuteEx(&si);
  1210. }
  1211. return 1L;
  1212. }
  1213. bool CIEShellListCtrl::EndLabelEdit(int nRow,int nCol,LPCTSTR pszText)
  1214. {
  1215. // TODO: Add your specialized code here and/or call the base class
  1216. if (nCol != 0)
  1217. return CUIODListCtrl::EndLabelEdit(nRow,nCol,pszText);
  1218. CString sFromPath(GetPathName(nRow));
  1219. CString sToPath;
  1220. CSplitPath path(sFromPath);
  1221. if (GetShellSettings().ShowExtensions())
  1222. {
  1223. CSplitPath file(pszText);
  1224. path.SetFileName(file.GetFileName());
  1225. path.SetExt(file.GetExt());
  1226. }
  1227. else
  1228. {
  1229. path.SetFileName(pszText);
  1230. }
  1231. path.Make();
  1232. sToPath = path.GetPath();
  1233. SHFILEOPSTRUCT shf;
  1234. TCHAR szFrom[MAX_PATH+1];
  1235. TCHAR szTo[MAX_PATH+1];
  1236. ZeroMemory(szFrom,sizeof(szFrom));
  1237. lstrcpy(szFrom,sFromPath);
  1238. ZeroMemory(szTo,sizeof(szTo));
  1239. lstrcpy(szTo,sToPath);
  1240. ZeroMemory(&shf,sizeof(shf));
  1241. shf.hwnd = GetSafeHwnd();
  1242. shf.wFunc = FO_RENAME;
  1243. shf.pFrom = szFrom;
  1244. shf.pTo = szTo;
  1245. #ifdef _DEBUG
  1246. CString sMess;
  1247. sMess = szFrom;
  1248. sMess += _T("n");
  1249. sMess += szTo;
  1250. AfxMessageBox(sMess);
  1251. #endif
  1252. int nRet = SHFileOperation(&shf);
  1253. TRACE1("SHFileOperation returned %un",nRet);
  1254. return false;
  1255. }
  1256. void CIEShellListCtrl::GoBack(int nRow)
  1257. {
  1258. // TODO: Add your specialized code here and/or call the base class
  1259. AfxMessageBox(_T("Needs to be implemented"));
  1260. }
  1261. void CIEShellListCtrl::ChangeStyle(UINT &dwStyle)
  1262. {
  1263. // TODO: Add your specialized code here and/or call the base class
  1264. CUIODListCtrl::ChangeStyle(dwStyle);
  1265. dwStyle |= (LVS_SHAREIMAGELISTS | LVS_EDITLABELS);  
  1266. }
  1267. LRESULT CIEShellListCtrl::OnSetmessagestring(WPARAM wParam, LPARAM lParam)
  1268. {
  1269. if (GetParent())
  1270. return GetParent()->SendMessage(WM_SETMESSAGESTRING,wParam,lParam);
  1271. return 0;
  1272. }
  1273. void CIEShellListCtrl::SetTreeCtrlWnd(HWND hWnd)
  1274. {
  1275. m_hTreeWnd = hWnd;
  1276. }
  1277. void CIEShellListCtrl::SelChanged(int nItem, LRESULT *pResult)
  1278. {
  1279. CIRWEngine *pIRWEngine = ISeeGetIRWEngine();
  1280. CReturnReceipt *pRReceipt = NULL;
  1281. CString szPath = GetPathName( nItem );
  1282. LPLVITEMDATA pItemData = (LPLVITEMDATA)GetItemData( nItem );
  1283. if ( pItemData->iFlag == 2 )
  1284. return; //此文件项不能被处理
  1285. pRReceipt = pItemData->pRReceipt;
  1286. if ( pRReceipt == NULL )
  1287. {
  1288. if ( szPath.IsEmpty() )
  1289. {
  1290. pItemData->iFlag = 2;
  1291. return ;  //
  1292. }
  1293. DWORD dwResult;
  1294. dwResult = GetFileAttributes( szPath );
  1295. dwResult &= FILE_ATTRIBUTE_DIRECTORY;
  1296. if ( dwResult ) //is dir
  1297. {
  1298. pItemData->iFlag = 2;
  1299. return ;
  1300. }
  1301. pRReceipt = pIRWEngine->IsValidImageFile( szPath , FALSE);
  1302. if (pRReceipt == NULL)
  1303. return ; // 内存不足
  1304. if (pRReceipt->GetImagePluginID() >= 0) // 该文件能被插件处理
  1305. {
  1306. pIRWEngine->GetImageFileInfo(pRReceipt);
  1307. while(pRReceipt->GetResult() == IRWERRT_ING); // 等待命令处理完毕
  1308. if (pRReceipt->GetResult() == IRWERRT_FAIL)
  1309. return; //处理失败
  1310. }
  1311. else
  1312. {
  1313. pItemData->iFlag = 2;
  1314. delete pRReceipt;
  1315. return;//不能处理
  1316. }
  1317. }
  1318. pIRWEngine->LoadImageFromFile( pRReceipt , TRUE );
  1319. pItemData->iFlag = 1;
  1320. pItemData->pRReceipt = pRReceipt;
  1321. pItemData->rgbColor = bkColor[ pRReceipt->GetImagePluginID() ];
  1322.   //因为引擎是异步执行的,所以LoadImageFromFile()不会立即成功,
  1323.   //是否读完可由工作场模块判断
  1324.   //if ( pRReceipt->GetResult() == IRWERRT_SUCCESS )
  1325.   /*if ( true )
  1326. {
  1327. pItemData->iFlag = 1;
  1328. pItemData->pRReceipt = pRReceipt;
  1329. pItemData->rgbColor = bkColor[ pRReceipt->GetImagePluginID() ];
  1330. }
  1331. else
  1332. {
  1333. delete pRReceipt;
  1334. return; //失败
  1335. }*/
  1336. UINT message = WM_APP_LIST_SELECTCHANGED;
  1337. GetParent()->SendMessage( message , (WPARAM)nItem , 0 );
  1338. *pResult = 0;
  1339. }
  1340. //此函数用来在系统空闲时进行图像的预读。
  1341. //m_iProcessed用来决定预读哪一幅图像, 当m_iProcessed的值大于当前目录中的图像个数时
  1342. //预读结束。
  1343. BOOL CIEShellListCtrl::OnIdle(LONG lCount)
  1344. {
  1345. CIRWEngine *pIRWEngine = ISeeGetIRWEngine();
  1346. CReturnReceipt *pRReceipt = NULL;
  1347. LPLVITEMDATA  pListData;
  1348. if (m_iProcessed < GetItemCount())
  1349. {
  1350. pListData = (LPLVITEMDATA)GetItemData( m_iProcessed );
  1351. CString szPath = GetPathName( m_iProcessed );
  1352. if ( pListData->iFlag > 0 )
  1353. {
  1354. m_iProcessed ++;
  1355. return true;
  1356. }
  1357. if ( szPath.IsEmpty() )  
  1358. {
  1359. pListData->iFlag = 2;
  1360. m_iProcessed++;
  1361. return true;
  1362. }
  1363. DWORD dwResult;
  1364. dwResult = GetFileAttributes( szPath );
  1365. dwResult &= FILE_ATTRIBUTE_DIRECTORY;
  1366. if ( dwResult ) //不处理目录
  1367. {
  1368. pListData->iFlag = 2;
  1369. m_iProcessed++;
  1370. return true;
  1371. }
  1372. pRReceipt = pIRWEngine->IsValidImageFile( szPath , FALSE);
  1373. if (pRReceipt == NULL)
  1374. return false ; // 内存不足
  1375. if (pRReceipt->GetImagePluginID() >= 0) // 该文件能被插件处理
  1376. {
  1377. pIRWEngine->GetImageFileInfo(pRReceipt);
  1378. while(pRReceipt->GetResult() == IRWERRT_ING); // 等待命令处理完毕
  1379. if (pRReceipt->GetResult() == IRWERRT_SUCCESS)
  1380. {
  1381. // 在选择被修改时读取图像的位数据,否则内存耗量太大
  1382. // pIRWEngine->LoadImageFromFile( pRReceipt );
  1383. // if ( pRReceipt->GetResult() == IRWERRT_SUCCESS )
  1384. // if ( true )
  1385. // {
  1386. pListData->iFlag = 1;
  1387. pListData->pRReceipt = pRReceipt;
  1388. pListData->rgbColor = bkColor[ pRReceipt->GetImagePluginID() ];
  1389. // }
  1390. // else
  1391. // delete pRReceipt; //读取数据不成功,删除回执单
  1392.           //当前可处理图像已读取完。
  1393. }
  1394. }
  1395. else 
  1396. {
  1397. pListData->iFlag = 2;
  1398. delete pRReceipt;
  1399. }
  1400. m_iProcessed ++;
  1401. }
  1402. else 
  1403. return false; //通知系统不必调用此函数了。
  1404. return true;
  1405. }
  1406. void * CIEShellListCtrl::GetIdleFuncAddr()
  1407. {
  1408. // BOOL (* pFuncAddr)(LONG);
  1409. // pFuncAddr = OnIdle;
  1410. // return ( (void *)pFuncAddr );
  1411. return NULL;
  1412. }