XTShellPidl.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:16k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTShellPidl.cpp : implementation file
  2. //
  3. // This file is a part of the XTREME CONTROLS MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/XTPVC80Helpers.h"  // Visual Studio 2005 helper functions
  22. #include "Common/XTPResourceManager.h"
  23. #include "XTShellPidl.h"
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. CXTShellPidl::CShellSpecialFolder::CShellSpecialFolder(int nFolder)
  30. {
  31. m_lpFolder = NULL;
  32. if (FAILED(::SHGetDesktopFolder(&m_lpFolder)))
  33. {
  34. m_lpFolder = NULL;
  35. return;
  36. }
  37. if (nFolder != CSIDL_DESKTOP)
  38. {
  39. CXTShellPidl::CShellMalloc lpMalloc;
  40. LPSHELLFOLDER lpFolder = NULL;
  41. if (lpMalloc)
  42. {
  43. LPITEMIDLIST pidlFolder = NULL;
  44. if (SUCCEEDED(::SHGetSpecialFolderLocation(NULL, nFolder, &pidlFolder)))
  45. {
  46. m_lpFolder->BindToObject(pidlFolder, 0, IID_IShellFolder, (LPVOID*)&lpFolder);
  47. lpMalloc.Free(pidlFolder);
  48. }
  49. }
  50. m_lpFolder->Release();
  51. m_lpFolder = lpFolder;
  52. }
  53. }
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CXTShellPidl
  56. CXTShellPidl::CXTShellPidl()
  57. {
  58. m_bShowShellLinkIcons = TRUE;
  59. }
  60. CXTShellPidl::~CXTShellPidl()
  61. {
  62. }
  63. /////////////////////////////////////////////////////////////////////////////
  64. // Functions that deal with PIDLs
  65. LPITEMIDLIST CXTShellPidl::IDLFromPath(LPCTSTR strPath)
  66. {
  67. IShellFolder *psfDeskTop = NULL;
  68. LPITEMIDLIST  pidlPath = NULL;
  69. if (FAILED(::SHGetDesktopFolder(&psfDeskTop)))
  70. {
  71. return NULL;
  72. }
  73. // Get the folders IDL
  74. psfDeskTop->ParseDisplayName(NULL, NULL,
  75. (LPOLESTR)XTP_CT2CW(strPath), NULL, &pidlPath, NULL);
  76. psfDeskTop->Release();
  77. return pidlPath;
  78. }
  79. LPITEMIDLIST CXTShellPidl::OneUpPIDL(LPITEMIDLIST pidlPath)
  80. {
  81. if (pidlPath)
  82. {
  83. // Get the last item
  84. LPITEMIDLIST pidlLast = GetLastITEM(pidlPath);
  85. // if not a NULL
  86. if (pidlLast)
  87. {
  88. // don't attempt to go any lower than 1 IDL
  89. if (pidlLast == pidlPath) return pidlPath;
  90. // set its cb to 0
  91. pidlLast->mkid.cb = 0;
  92. }
  93. }
  94. return pidlPath;
  95. }
  96. CString CXTShellPidl::OneUpPATH(const CString& path)
  97. {
  98. // Make a string buffer
  99. TCHAR newPath[MAX_PATH];
  100. ZeroMemory(newPath, sizeof(newPath));
  101. if (path.GetLength())
  102. {
  103. LPITEMIDLIST pidlPath = IDLFromPath(path);
  104. if (OneUpPIDL(pidlPath))
  105. {
  106. SHGetPathFromIDList(pidlPath, newPath);
  107. }
  108. }
  109. return CString(newPath);
  110. }
  111. LPITEMIDLIST CXTShellPidl::GetLastITEM(LPITEMIDLIST pidl)
  112. {
  113. LPSTR lpMem = NULL;
  114. LPITEMIDLIST pidlLast = NULL;
  115. if (pidl)
  116. {
  117. lpMem = (LPSTR)pidl;
  118. // walk the list until we find a null
  119. while (*lpMem != 0)
  120. {
  121. if (LPITEMIDLIST(lpMem)->mkid.cb == 0) break;// maybe ?
  122. pidlLast = (LPITEMIDLIST)lpMem;
  123. lpMem += LPITEMIDLIST(lpMem)->mkid.cb;
  124. }
  125. }
  126. return pidlLast;
  127. }
  128. LPITEMIDLIST CXTShellPidl::CopyPidlItem(LPITEMIDLIST pidl, UINT nItem)
  129. {
  130. if (!pidl)
  131. return NULL;
  132. while (nItem--)
  133. {
  134. if (pidl->mkid.cb == 0)
  135. return NULL;
  136. pidl = GetNextPidlItem(pidl);
  137. }
  138. int nSize = pidl->mkid.cb + sizeof(pidl->mkid.cb);
  139. LPITEMIDLIST pidlCopy = CreatePidl(CShellMalloc(), nSize);
  140. if (pidlCopy)
  141. {
  142. ZeroMemory(pidlCopy, nSize);
  143. MEMCPY_S(pidlCopy, pidl, pidl->mkid.cb);
  144. }
  145. return pidlCopy;
  146. }
  147. LPITEMIDLIST CXTShellPidl::CopyIDList(LPITEMIDLIST pidl)
  148. {
  149. LPITEMIDLIST pidlCopy = NULL;
  150. UINT bytes = 0;
  151. bytes = GetPidlItemCount(pidl);
  152. pidlCopy = CreatePidl(CShellMalloc(), bytes);
  153. if (pidlCopy)
  154. {
  155. ZeroMemory(pidlCopy, bytes);
  156. MEMCPY_S(pidlCopy, pidl, bytes);
  157. }
  158. return pidlCopy;
  159. }
  160. LPITEMIDLIST CXTShellPidl::GetNextPidlItem(LPCITEMIDLIST pidl)
  161. {
  162. LPSTR lpMem = (LPSTR)pidl;
  163. lpMem += pidl->mkid.cb;
  164. return (LPITEMIDLIST)lpMem;
  165. }
  166. UINT CXTShellPidl::GetPidlCount(LPCITEMIDLIST pidl)
  167. {
  168. UINT nCount = 0;
  169. if (pidl)
  170. {
  171. while (pidl->mkid.cb)
  172. {
  173. ++nCount;
  174. pidl = GetNextPidlItem(pidl);
  175. }
  176. }
  177. return nCount;
  178. }
  179. UINT CXTShellPidl::GetPidlItemCount(LPCITEMIDLIST pidl)
  180. {
  181. UINT cbTotal = 0;
  182. if (pidl)
  183. {
  184. cbTotal += sizeof(pidl->mkid.cb);       // Null terminator
  185. while (pidl->mkid.cb)
  186. {
  187. cbTotal += pidl->mkid.cb;
  188. pidl = GetNextPidlItem(pidl);
  189. }
  190. }
  191. return cbTotal;
  192. }
  193. LPITEMIDLIST CXTShellPidl::CreatePidl(LPMALLOC lpMalloc, UINT cbSize)
  194. {
  195. if (!lpMalloc)
  196. return NULL;
  197. // zero-init for external task allocate
  198. LPITEMIDLIST pidl = (LPITEMIDLIST)lpMalloc->Alloc(cbSize);
  199. if (pidl)
  200. {
  201. memset(pidl, 0, cbSize);
  202. }
  203. return pidl;
  204. }
  205. void CXTShellPidl::FreePidl(LPITEMIDLIST pidl)
  206. {
  207. if (!pidl)
  208. return;
  209. CShellMalloc lpMalloc;
  210. if (lpMalloc)
  211. {
  212. lpMalloc.Free(pidl);
  213. }
  214. }
  215. BOOL CXTShellPidl::ComparePidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2, LPSHELLFOLDER pShellFolder /*NULL*/)
  216. {
  217. if (pidl1 == NULL || pidl2 == NULL)
  218. return FALSE;
  219. BOOL bLPCreated = FALSE;
  220. if (pShellFolder == NULL)
  221. {
  222. if (FAILED(::SHGetDesktopFolder(&pShellFolder)))
  223. return FALSE;
  224. bLPCreated = TRUE;
  225. }
  226. HRESULT hr = pShellFolder->CompareIDs(0, pidl1, pidl2);
  227. if (bLPCreated)
  228. {
  229. pShellFolder->Release();
  230. }
  231. return ((short)hr) == 0;
  232. }
  233. LPITEMIDLIST CXTShellPidl::ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  234. {
  235. return ConcatPidls(CShellMalloc(), pidl1, pidl2);
  236. }
  237. LPITEMIDLIST CXTShellPidl::ConcatPidls(LPMALLOC lpMalloc, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  238. {
  239. LPITEMIDLIST pidlNew;
  240. UINT cb1;
  241. UINT cb2;
  242. // May be NULL
  243. if (pidl1)
  244. {
  245. cb1 = GetPidlItemCount(pidl1) - sizeof(pidl1->mkid.cb);
  246. }
  247. else
  248. {
  249. cb1 = 0;
  250. }
  251. cb2 = GetPidlItemCount(pidl2);
  252. pidlNew = CreatePidl(lpMalloc, cb1 + cb2);
  253. if (pidlNew)
  254. {
  255. if (pidl1)
  256. {
  257. MEMCPY_S(pidlNew, pidl1, cb1);
  258. }
  259. MEMCPY_S(((LPSTR)pidlNew) + cb1, pidl2, cb2);
  260. }
  261. return pidlNew;
  262. }
  263. LPITEMIDLIST CXTShellPidl::DuplicateItem(LPMALLOC lpMalloc, LPITEMIDLIST lpi)
  264. {
  265. LPITEMIDLIST lpiTemp = (LPITEMIDLIST)lpMalloc->Alloc(lpi->mkid.cb + sizeof(lpi->mkid.cb));
  266. MEMCPY_S((PVOID)lpiTemp, (CONST VOID *)lpi, lpi->mkid.cb + sizeof(lpi->mkid.cb));
  267. return lpiTemp;
  268. }
  269. BOOL CXTShellPidl::GetName(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, DWORD dwFlags, CString& strFriendlyName)
  270. {
  271. STRRET str;
  272. if (lpsf->GetDisplayNameOf(lpi, dwFlags, &str) == NOERROR)
  273. {
  274. switch (str.uType)
  275. {
  276. case STRRET_WSTR:
  277. {
  278. strFriendlyName = str.pOleStr;
  279. CShellMalloc pMalloc;
  280. if (pMalloc) pMalloc.Free(str.pOleStr);
  281. }
  282. break;
  283. case STRRET_OFFSET:
  284. {
  285. LPSTR lpszOffset = (LPSTR)lpi + str.uOffset;
  286. strFriendlyName = lpszOffset;
  287. }
  288. break;
  289. case STRRET_CSTR:
  290. strFriendlyName = (LPSTR)str.cStr;
  291. break;
  292. default:
  293. return FALSE;
  294. }
  295. }
  296. else
  297. {
  298. return FALSE;
  299. }
  300. return TRUE;
  301. }
  302. LPITEMIDLIST CXTShellPidl::GetFullyQualPidl(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi)
  303. {
  304. CString strBuff;
  305. LPSHELLFOLDER lpsfDeskTop;
  306. LPITEMIDLIST  lpifq;
  307. ULONG ulEaten, ulAttribs;
  308. if (!GetName(lpsf, lpi, SHGDN_FORPARSING, strBuff))
  309. {
  310. return NULL;
  311. }
  312. if (FAILED(::SHGetDesktopFolder(&lpsfDeskTop)))
  313. {
  314. return NULL;
  315. }
  316. if (FAILED(lpsfDeskTop->ParseDisplayName(NULL, NULL, (LPOLESTR)XTP_CT2CW(strBuff),
  317. &ulEaten, &lpifq, &ulAttribs)))
  318. {
  319. lpsfDeskTop->Release();
  320. return NULL;
  321. }
  322. lpsfDeskTop->Release();
  323. return lpifq;
  324. }
  325. // Static variables used for passing data to the subclassing wndProc
  326. WNDPROC        CXTShellPidl::m_pOldWndProc = NULL;  // regular window proc
  327. LPCONTEXTMENU2 CXTShellPidl::m_pIContext2 = NULL;  // active shell context menu
  328. BOOL CXTShellPidl::ShowContextMenu(HWND hwnd, LPSHELLFOLDER lpsfParent, LPITEMIDLIST lpi, LPPOINT lppt)
  329. {
  330. return ShowContextMenu(hwnd, lpsfParent, (LPCITEMIDLIST*)&lpi, 1, lppt);
  331. }
  332. void CXTShellPidl::OnShowContextMenu(int /*idCmd*/, CMINVOKECOMMANDINFO& /*cmi*/)
  333. {
  334. // handle in derived class.
  335. }
  336. BOOL CXTShellPidl::ShowContextMenu(HWND hwnd, LPSHELLFOLDER lpsfParent, LPCITEMIDLIST* lpi, int nCount, LPPOINT lppt)
  337. {
  338. LPCONTEXTMENU       lpcm;
  339. CMINVOKECOMMANDINFO cmi;
  340. BOOL                bSuccess = TRUE;
  341. int                 cmType; // "version" # of context menu
  342. // assume that psfFolder and pidl are valid
  343. HRESULT hr = GetSHContextMenu(lpsfParent, lpi, nCount, (void**)&lpcm, &cmType);
  344. if (SUCCEEDED(hr))
  345. {
  346. HMENU hMenu = ::CreatePopupMenu();
  347. if (hMenu != NULL)
  348. {
  349. hr = lpcm->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_EXPLORE);
  350. if (SUCCEEDED(hr))
  351. {
  352. // install the subclassing "hook", for versions 2 or 3
  353. if (cmType > 1)
  354. {
  355. m_pOldWndProc = (WNDPROC)
  356. SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)HookWndProc);
  357. m_pIContext2 = (LPCONTEXTMENU2)lpcm; // cast ok for ICMv3
  358. }
  359. else
  360. m_pOldWndProc = NULL;
  361. int idCmd = ::TrackPopupMenu(hMenu,
  362. TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON,
  363. lppt->x, lppt->y, 0, hwnd, NULL);
  364. if (m_pOldWndProc) // restore old wndProc
  365. SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)m_pOldWndProc);
  366. if (idCmd != 0)
  367. {
  368. cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
  369. cmi.fMask = 0;
  370. cmi.hwnd = hwnd;
  371. cmi.lpVerb = (LPCSTR)MAKEINTRESOURCE(idCmd-1);
  372. cmi.lpParameters = NULL;
  373. cmi.lpDirectory = NULL;
  374. cmi.nShow = SW_SHOWNORMAL;
  375. cmi.dwHotKey = 0;
  376. cmi.hIcon = NULL;
  377. if (SUCCEEDED(lpcm->InvokeCommand(&cmi)))
  378. {
  379. OnShowContextMenu(idCmd-1, cmi);
  380. }
  381. }
  382. m_pIContext2 = NULL; // prevents accidental use
  383. }
  384. else
  385. {
  386. bSuccess = FALSE;
  387. }
  388. ::DestroyMenu(hMenu);
  389. }
  390. else
  391. bSuccess = FALSE;
  392. lpcm->Release();
  393. }
  394. else
  395. {
  396. CString strMessage;
  397. strMessage.Format(_T("GetUIObjectOf failed! hr=%lx"), hr);
  398. AfxMessageBox(strMessage);
  399. bSuccess = FALSE;
  400. }
  401. return bSuccess;
  402. }
  403. int CXTShellPidl::GetItemIcon(LPITEMIDLIST lpi, UINT uFlags) const
  404. {
  405. SHFILEINFO sfi;
  406. ::SHGetFileInfo((TCHAR*)lpi, 0, &sfi, sizeof(SHFILEINFO), uFlags);
  407. return sfi.iIcon;
  408. }
  409. HIMAGELIST CXTShellPidl::GetSystemImageList(UINT uFlags) const
  410. {
  411. SHFILEINFO sfi;
  412. for (TCHAR cDrive = _T('C'); cDrive <= _T('Z'); cDrive++)
  413. {
  414. if (GetDriveType(CString(cDrive) + _T(":")) == DRIVE_FIXED)
  415. {
  416. return (HIMAGELIST)::SHGetFileInfo(CString(cDrive) + _T(":\"), 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | uFlags);
  417. }
  418. }
  419. return NULL;
  420. }
  421. HRESULT CXTShellPidl::GetSHContextMenu(LPSHELLFOLDER psfFolder, LPCITEMIDLIST* localPidl, int nCount, void** ppCM, int* pcmType)
  422. {
  423. *ppCM = NULL;
  424. LPCONTEXTMENU pICv1 = NULL; // plain version
  425. HRESULT hr;
  426. // try to obtain the lowest possible IContextMenu
  427. if (nCount == 0)
  428. {
  429. hr = psfFolder->CreateViewObject(NULL, IID_IContextMenu, (void**)&pICv1);
  430. }
  431. else
  432. {
  433. hr = psfFolder->GetUIObjectOf(NULL, nCount, localPidl, IID_IContextMenu, NULL, (void**)&pICv1);
  434. }
  435. // try to obtain a higher level pointer, first 3 then 2
  436. if (pICv1)
  437. {
  438. hr = pICv1->QueryInterface(IID_IContextMenu3, ppCM);
  439. if (NOERROR == hr)
  440. *pcmType = 3;
  441. else
  442. {
  443. hr = pICv1->QueryInterface(IID_IContextMenu2, ppCM);
  444. if (NOERROR == hr) *pcmType = 2;
  445. }
  446. // free initial "v1.0" interface
  447. if (*ppCM)
  448. pICv1->Release();
  449. // no higher version supported
  450. else
  451. {
  452. *pcmType = 1;
  453. *ppCM = pICv1;
  454. hr = NOERROR; // never mind the query failures, this'll do
  455. }
  456. }
  457. return hr;
  458. }
  459. LRESULT CALLBACK CXTShellPidl::HookWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
  460. {
  461. UINT  uItem;
  462. TCHAR szBuf[MAX_PATH];
  463. switch (msg)
  464. {
  465. case WM_DRAWITEM:
  466. case WM_MEASUREITEM:
  467. {
  468. if (wp)
  469. break; // not menu related
  470. }
  471. case WM_INITMENUPOPUP:
  472. {
  473. m_pIContext2->HandleMenuMsg(msg, wp, lp);
  474. return (msg == WM_INITMENUPOPUP ? 0 : TRUE); // handled
  475. }
  476. case WM_MENUSELECT:
  477. {
  478. // if this is a shell item, get it's descriptive text
  479. uItem = (UINT) LOWORD(wp);
  480. if (0 == (MF_POPUP & HIWORD(wp)) && uItem >= 1 && uItem <= 0x7fff)
  481. {
  482. CFrameWnd * pWnd = ((CFrameWnd*)(AfxGetApp()->m_pMainWnd));
  483. if (!pWnd)
  484. return 0;
  485. szBuf[0] = 0;
  486. // set the status bar text
  487. if (SUCCEEDED(m_pIContext2->GetCommandString(uItem-1, GCS_HELPTEXT,
  488. NULL, (LPSTR)szBuf, _countof(szBuf))))
  489. {
  490. pWnd->SetMessageText(szBuf);
  491. }
  492. else
  493. {
  494. pWnd->SetMessageText(_T(""));
  495. }
  496. return 0;
  497. }
  498. break;
  499. }
  500. default:
  501. break;
  502. }
  503. // for all untreated messages, call the original wndproc
  504. return ::CallWindowProc(m_pOldWndProc, hWnd, msg, wp, lp);
  505. }
  506. int CXTShellPidl::TreeViewCompareProc(LPARAM lparam1, LPARAM lparam2, LPARAM /*lparamSort*/)
  507. {
  508. XT_TVITEMDATA* lptvid1 = (XT_TVITEMDATA*)lparam1;
  509. XT_TVITEMDATA* lptvid2 = (XT_TVITEMDATA*)lparam2;
  510. HRESULT hr = lptvid1->lpsfParent->CompareIDs(0, lptvid1->lpi, lptvid2->lpi);
  511. if (FAILED(hr))
  512. {
  513. return 0;
  514. }
  515. return (short)SCODE_CODE(GetScode(hr));
  516. }
  517. int CXTShellPidl::ListViewCompareProc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort)
  518. {
  519. BOOL bAscending = (BOOL)lparamSort;
  520. XT_LVITEMDATA* lplvid1 = (XT_LVITEMDATA*)lparam1;
  521. XT_LVITEMDATA* lplvid2 = (XT_LVITEMDATA*)lparam2;
  522. HRESULT hr = lplvid1->lpsfParent->CompareIDs(0,
  523. bAscending ? lplvid1->lpi : lplvid2->lpi,
  524. bAscending ? lplvid2->lpi : lplvid1->lpi);
  525. if (FAILED(hr))
  526. {
  527. return 0;
  528. }
  529. return (short)SCODE_CODE(GetScode(hr));
  530. }
  531. void CXTShellPidl::MapShellFlagsToItemAttributes(CTreeCtrl* pTreeCtrl, HTREEITEM hItem, DWORD dwAttributes)
  532. {
  533. // Display with 'cut' feedback if the item is ghosted (about to be moved to a different location or a hidden one)
  534. if (dwAttributes & SFGAO_GHOSTED)
  535. {
  536. pTreeCtrl->SetItemState(hItem, TVIS_CUT, TVIS_CUT);
  537. }
  538. else
  539. {
  540. pTreeCtrl->SetItemState(hItem, 0, TVIS_CUT);
  541. }
  542. UINT nImage; // assign proper overlay image (link, share)
  543. if ((dwAttributes & SFGAO_LINK) && m_bShowShellLinkIcons)
  544. {
  545. nImage = INDEXTOOVERLAYMASK(2);
  546. }
  547. else
  548. if (dwAttributes & SFGAO_SHARE)
  549. {
  550. nImage = INDEXTOOVERLAYMASK(1);
  551. }
  552. else
  553. {
  554. nImage = 0; // no overlay
  555. }
  556. // NB: we use here TVIS_OVERLAYMASK (as for the tree control) though
  557. // the list view control also calls this function and LVIS_OVERLAYMASK
  558. // should be used in that case. Reason for that is both of them refer
  559. // to results of INDEXTOOVERLAYMASK macro and hence they have to be the same,
  560. // namely INDEXTOOVERLAYMASK(15)
  561. pTreeCtrl->SetItemState(hItem, nImage, TVIS_OVERLAYMASK);
  562. }
  563. void CXTShellPidl::MapShellFlagsToItemAttributes(CListCtrl* pListCtrl, int iItem, DWORD dwAttributes)
  564. {
  565. // Display with 'cut' feedback if the item is ghosted (about to be moved to a different location or a hidden one)
  566. if (dwAttributes & SFGAO_GHOSTED)
  567. {
  568. pListCtrl->SetItemState(iItem, LVIS_CUT, LVIS_CUT);
  569. }
  570. else
  571. {
  572. pListCtrl->SetItemState(iItem, 0, LVIS_CUT);
  573. }
  574. UINT nImage; // assign proper overlay image (link, share)
  575. if ((dwAttributes & SFGAO_LINK) && m_bShowShellLinkIcons)
  576. {
  577. nImage = INDEXTOOVERLAYMASK(2);
  578. }
  579. else
  580. if (dwAttributes & SFGAO_SHARE)
  581. {
  582. nImage = INDEXTOOVERLAYMASK(1);
  583. }
  584. else
  585. {
  586. nImage = 0; // no overlay
  587. }
  588. // NB: we use here TVIS_OVERLAYMASK (as for the tree control) though
  589. // the list view control also calls this function and LVIS_OVERLAYMASK
  590. // should be used in that case. Reason for that is both of them refer
  591. // to results of INDEXTOOVERLAYMASK macro and hence they have to be the same,
  592. // namely INDEXTOOVERLAYMASK(15)
  593. pListCtrl->SetItemState(iItem, nImage, TVIS_OVERLAYMASK);
  594. }