Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1142 lines
29 KiB

  1. /**************************************************************************
  2. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. PARTICULAR PURPOSE.
  6. Copyright 1998 Microsoft Corporation. All Rights Reserved.
  7. **************************************************************************/
  8. /**************************************************************************
  9. File: ContMenu.cpp
  10. Description: CContextMenu implementation.
  11. **************************************************************************/
  12. /**************************************************************************
  13. #include statements
  14. **************************************************************************/
  15. #include "ContMenu.h"
  16. #include "Commands.h"
  17. #include "ShlView.h"
  18. /**************************************************************************
  19. global variables
  20. **************************************************************************/
  21. #define MAX_VERB 64
  22. typedef struct {
  23. TCHAR szVerb[MAX_VERB];
  24. DWORD dwCommand;
  25. }VERBMAPPING, FAR *LPVERBMAPPING;
  26. VERBMAPPING g_VerbMap[] = { TEXT("explore"), IDM_EXPLORE,
  27. TEXT("open"), IDM_OPEN,
  28. TEXT("delete"), IDM_DELETE,
  29. TEXT("rename"), IDM_RENAME,
  30. TEXT("copy"), IDM_COPY,
  31. TEXT("cut"), IDM_CUT,
  32. TEXT("paste"), IDM_PASTE,
  33. TEXT("NewFolder"), IDM_NEW_FOLDER,
  34. TEXT("NewItem"), IDM_NEW_ITEM,
  35. TEXT("ModifyData"), IDM_MODIFY_DATA,
  36. TEXT(""), (DWORD)-1
  37. };
  38. /**************************************************************************
  39. CContextMenu::CContextMenu()
  40. **************************************************************************/
  41. CContextMenu::CContextMenu(CShellFolder *psfParent, LPCITEMIDLIST *aPidls, UINT uItemCount)
  42. {
  43. g_DllRefCount++;
  44. m_ObjRefCount = 1;
  45. m_aPidls = NULL;
  46. m_uItemCount = 0;
  47. m_fBackground = FALSE;
  48. m_psfParent = psfParent;
  49. if(m_psfParent)
  50. m_psfParent->AddRef();
  51. SHGetMalloc(&m_pMalloc);
  52. if(!m_pMalloc)
  53. {
  54. delete this;
  55. return;
  56. }
  57. m_pPidlMgr = new CPidlMgr();
  58. m_uItemCount = uItemCount;
  59. if(m_uItemCount)
  60. {
  61. m_aPidls = AllocPidlTable(uItemCount);
  62. if(m_aPidls)
  63. {
  64. FillPidlTable(aPidls, uItemCount);
  65. }
  66. }
  67. else
  68. {
  69. m_fBackground = TRUE;
  70. }
  71. m_cfPrivateData = RegisterClipboardFormat(CFSTR_SAMPVIEWDATA);
  72. }
  73. /**************************************************************************
  74. CContextMenu::~CContextMenu()
  75. **************************************************************************/
  76. CContextMenu::~CContextMenu()
  77. {
  78. if(m_psfParent)
  79. m_psfParent->Release();
  80. g_DllRefCount--;
  81. //make sure the pidls are freed
  82. if(m_aPidls && m_pMalloc)
  83. {
  84. FreePidlTable(m_aPidls);
  85. }
  86. if(m_pPidlMgr)
  87. delete m_pPidlMgr;
  88. if(m_pMalloc)
  89. m_pMalloc->Release();
  90. }
  91. ///////////////////////////////////////////////////////////////////////////
  92. //
  93. // IUnknown Implementation
  94. //
  95. /**************************************************************************
  96. CContextMenu::QueryInterface
  97. **************************************************************************/
  98. STDMETHODIMP CContextMenu::QueryInterface( REFIID riid,
  99. LPVOID FAR * ppReturn)
  100. {
  101. *ppReturn = NULL;
  102. if(IsEqualIID(riid, IID_IUnknown))
  103. {
  104. *ppReturn = (LPUNKNOWN)(LPCONTEXTMENU)this;
  105. }
  106. if(IsEqualIID(riid, IID_IContextMenu))
  107. {
  108. *ppReturn = (LPCONTEXTMENU)this;
  109. }
  110. if(IsEqualIID(riid, IID_IShellExtInit))
  111. {
  112. *ppReturn = (LPSHELLEXTINIT)this;
  113. }
  114. if(*ppReturn)
  115. {
  116. (*(LPUNKNOWN*)ppReturn)->AddRef();
  117. return S_OK;
  118. }
  119. return E_NOINTERFACE;
  120. }
  121. /**************************************************************************
  122. CContextMenu::AddRef
  123. **************************************************************************/
  124. STDMETHODIMP_(DWORD) CContextMenu::AddRef()
  125. {
  126. return ++m_ObjRefCount;
  127. }
  128. /**************************************************************************
  129. CContextMenu::Release
  130. **************************************************************************/
  131. STDMETHODIMP_(DWORD) CContextMenu::Release()
  132. {
  133. if(--m_ObjRefCount == 0)
  134. delete this;
  135. return m_ObjRefCount;
  136. }
  137. ///////////////////////////////////////////////////////////////////////////
  138. //
  139. // IContextMenu Implementation
  140. //
  141. /**************************************************************************
  142. CContextMenu::QueryContextMenu()
  143. **************************************************************************/
  144. STDMETHODIMP CContextMenu::QueryContextMenu( HMENU hMenu,
  145. UINT indexMenu,
  146. UINT idCmdFirst,
  147. UINT idCmdLast,
  148. UINT uFlags)
  149. {
  150. if(!(CMF_DEFAULTONLY & uFlags))
  151. {
  152. if(m_fBackground)
  153. {
  154. //add the menu items that apply to the background of the view
  155. InsertBackgroundItems(hMenu, indexMenu, idCmdFirst);
  156. }
  157. else
  158. {
  159. InsertItems(hMenu, indexMenu, idCmdFirst, uFlags);
  160. }
  161. return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_LAST + 1));
  162. }
  163. else
  164. {
  165. /*
  166. Just insert the default item.
  167. */
  168. MENUITEMINFO mii;
  169. TCHAR szText[MAX_PATH];
  170. ZeroMemory(&mii, sizeof(mii));
  171. mii.cbSize = sizeof(mii);
  172. if(CMF_EXPLORE & uFlags)
  173. {
  174. LoadString(g_hInst, IDS_EXPLORE, szText, sizeof(szText));
  175. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  176. mii.wID = idCmdFirst + IDM_EXPLORE;
  177. mii.fType = MFT_STRING;
  178. mii.dwTypeData = szText;
  179. mii.fState = MFS_ENABLED | MFS_DEFAULT;
  180. InsertMenuItem( hMenu,
  181. indexMenu++,
  182. TRUE,
  183. &mii);
  184. }
  185. else
  186. {
  187. LoadString(g_hInst, IDS_OPEN, szText, sizeof(szText));
  188. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  189. mii.wID = idCmdFirst + IDM_OPEN;
  190. mii.fType = MFT_STRING;
  191. mii.dwTypeData = szText;
  192. mii.fState = MFS_ENABLED | MFS_DEFAULT;
  193. InsertMenuItem( hMenu,
  194. indexMenu++,
  195. TRUE,
  196. &mii);
  197. }
  198. return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_LAST + 1));
  199. }
  200. return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
  201. }
  202. /**************************************************************************
  203. CContextMenu::InvokeCommand()
  204. **************************************************************************/
  205. STDMETHODIMP CContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
  206. {
  207. LPCMINVOKECOMMANDINFOEX piciex;
  208. if(pici->cbSize < sizeof(CMINVOKECOMMANDINFO))
  209. return E_INVALIDARG;
  210. if(pici->cbSize >= sizeof(CMINVOKECOMMANDINFOEX) - sizeof(POINT))
  211. piciex = (LPCMINVOKECOMMANDINFOEX)pici;
  212. else
  213. piciex = NULL;
  214. if(HIWORD(pici->lpVerb))
  215. {
  216. //the command is being sent via a verb
  217. LPCTSTR pVerb;
  218. #ifdef UNICODE
  219. BOOL fUnicode = FALSE;
  220. WCHAR szVerb[MAX_PATH];
  221. if(piciex && ((pici->fMask & CMIC_MASK_UNICODE) == CMIC_MASK_UNICODE))
  222. {
  223. fUnicode = TRUE;
  224. }
  225. if(!fUnicode || piciex->lpVerbW == NULL)
  226. {
  227. MultiByteToWideChar( CP_ACP,
  228. 0,
  229. pici->lpVerb,
  230. -1,
  231. szVerb,
  232. ARRAYSIZE(szVerb));
  233. pVerb = szVerb;
  234. }
  235. else
  236. {
  237. pVerb = piciex->lpVerbW;
  238. }
  239. #else
  240. pVerb = pici->lpVerb;
  241. #endif //UNICODE
  242. //run through our list of verbs and get the command ID of the verb, if any
  243. int i;
  244. for(i = 0; -1 != g_VerbMap[i].dwCommand; i++)
  245. {
  246. if(0 == lstrcmpi(pVerb, g_VerbMap[i].szVerb))
  247. {
  248. pici->lpVerb = (LPCSTR)MAKEINTRESOURCE(g_VerbMap[i].dwCommand);
  249. break;
  250. }
  251. }
  252. }
  253. //this will also catch if an unsupported verb was specified
  254. if((DWORD)pici->lpVerb > IDM_LAST)
  255. return E_INVALIDARG;
  256. switch(LOWORD(pici->lpVerb))
  257. {
  258. case IDM_EXPLORE:
  259. DoExplore(GetParent(pici->hwnd));
  260. break;
  261. case IDM_OPEN:
  262. DoOpen(GetParent(pici->hwnd));
  263. break;
  264. case IDM_NEW_FOLDER:
  265. DoNewFolder(pici->hwnd);
  266. break;
  267. case IDM_NEW_ITEM:
  268. DoNewItem(pici->hwnd);
  269. break;
  270. case IDM_MODIFY_DATA:
  271. DoModifyData(pici->hwnd);
  272. break;
  273. case IDM_RENAME:
  274. DoRename(pici->hwnd);
  275. break;
  276. case IDM_PASTE:
  277. DoPaste();
  278. break;
  279. case IDM_CUT:
  280. DoCopyOrCut(pici->hwnd, TRUE);
  281. break;
  282. case IDM_COPY:
  283. DoCopyOrCut(pici->hwnd, FALSE);
  284. break;
  285. case IDM_DELETE:
  286. DoDelete();
  287. break;
  288. }
  289. return NOERROR;
  290. }
  291. /**************************************************************************
  292. CContextMenu::GetCommandString()
  293. **************************************************************************/
  294. STDMETHODIMP CContextMenu::GetCommandString( UINT idCommand,
  295. UINT uFlags,
  296. LPUINT lpReserved,
  297. LPSTR lpszName,
  298. UINT uMaxNameLen)
  299. {
  300. HRESULT hr = E_INVALIDARG;
  301. switch(uFlags)
  302. {
  303. case GCS_HELPTEXT:
  304. switch(idCommand)
  305. {
  306. case 0:
  307. hr = NOERROR;
  308. break;
  309. }
  310. break;
  311. case GCS_VERBA:
  312. {
  313. int i;
  314. for(i = 0; -1 != g_VerbMap[i].dwCommand; i++)
  315. {
  316. if(g_VerbMap[i].dwCommand == idCommand)
  317. {
  318. LocalToAnsi(lpszName, g_VerbMap[i].szVerb, uMaxNameLen);
  319. hr = NOERROR;
  320. break;
  321. }
  322. }
  323. }
  324. break;
  325. /*
  326. NT 4.0 with IE 3.0x or no IE will always call this with GCS_VERBW. In this
  327. case, you need to do the lstrcpyW to the pointer passed.
  328. */
  329. case GCS_VERBW:
  330. {
  331. int i;
  332. for(i = 0; -1 != g_VerbMap[i].dwCommand; i++)
  333. {
  334. if(g_VerbMap[i].dwCommand == idCommand)
  335. {
  336. LocalToWideChar((LPWSTR)lpszName, g_VerbMap[i].szVerb, uMaxNameLen);
  337. hr = NOERROR;
  338. break;
  339. }
  340. }
  341. }
  342. break;
  343. case GCS_VALIDATE:
  344. hr = NOERROR;
  345. break;
  346. }
  347. return hr;
  348. }
  349. ///////////////////////////////////////////////////////////////////////////
  350. //
  351. // private and utility methods
  352. //
  353. /**************************************************************************
  354. CContextMenu::AllocPidlTable()
  355. **************************************************************************/
  356. LPITEMIDLIST* CContextMenu::AllocPidlTable(DWORD dwEntries)
  357. {
  358. LPITEMIDLIST *aPidls;
  359. dwEntries++;
  360. aPidls = (LPITEMIDLIST*)m_pMalloc->Alloc(dwEntries * sizeof(LPITEMIDLIST));
  361. if(aPidls)
  362. {
  363. //set all of the entries to NULL
  364. ZeroMemory(aPidls, dwEntries * sizeof(LPITEMIDLIST));
  365. }
  366. return aPidls;
  367. }
  368. /**************************************************************************
  369. CContextMenu::FreePidlTable()
  370. **************************************************************************/
  371. VOID CContextMenu::FreePidlTable(LPITEMIDLIST *aPidls)
  372. {
  373. if(aPidls && m_pPidlMgr)
  374. {
  375. UINT i;
  376. for(i = 0; aPidls[i]; i++)
  377. m_pPidlMgr->Delete(aPidls[i]);
  378. m_pMalloc->Free(aPidls);
  379. }
  380. }
  381. /**************************************************************************
  382. CContextMenu::FillPidlTable()
  383. **************************************************************************/
  384. BOOL CContextMenu::FillPidlTable(LPCITEMIDLIST *aPidls, UINT uItemCount)
  385. {
  386. if(m_aPidls)
  387. {
  388. if(m_pPidlMgr)
  389. {
  390. UINT i;
  391. for(i = 0; i < uItemCount; i++)
  392. {
  393. m_aPidls[i] = m_pPidlMgr->Copy(aPidls[i]);
  394. }
  395. return TRUE;
  396. }
  397. }
  398. return FALSE;
  399. }
  400. /**************************************************************************
  401. CContextMenu::DoCopyOrCut()
  402. **************************************************************************/
  403. BOOL CContextMenu::DoCopyOrCut(HWND hWnd, BOOL fCut)
  404. {
  405. /*
  406. Copy the data to the clipboard. If this is a cut operation, mark the
  407. item as cut in the list. We will do this in the same way that the shell
  408. does it for the file system where the source data actually gets deleted
  409. when the paste operation occurs.
  410. */
  411. BOOL fSuccess = FALSE;
  412. if(OpenClipboard(NULL))
  413. {
  414. if(EmptyClipboard())
  415. {
  416. HGLOBAL hMem;
  417. LPITEMIDLIST pidlParent;
  418. pidlParent = m_psfParent->CreateFQPidl(NULL);
  419. if(pidlParent)
  420. {
  421. hMem = CreatePrivateClipboardData(pidlParent, m_aPidls, m_uItemCount, fCut);
  422. if(SetClipboardData(m_cfPrivateData, hMem))
  423. {
  424. fSuccess = TRUE;
  425. if(fCut)
  426. {
  427. CShellView *pView = (CShellView*)GetViewInterface(hWnd);
  428. if(pView)
  429. {
  430. pView->MarkItemsAsCut((LPCITEMIDLIST*)m_aPidls, m_uItemCount);
  431. pView->Release();
  432. }
  433. }
  434. }
  435. m_pPidlMgr->Delete(pidlParent);
  436. }
  437. }
  438. CloseClipboard();
  439. }
  440. return fSuccess;
  441. }
  442. /**************************************************************************
  443. CContextMenu::DoPaste()
  444. **************************************************************************/
  445. BOOL CContextMenu::DoPaste(VOID)
  446. {
  447. BOOL fSuccess = FALSE;
  448. HGLOBAL hMem;
  449. OpenClipboard(NULL);
  450. hMem = GetClipboardData(m_cfPrivateData);
  451. if(hMem)
  452. {
  453. LPPRIVCLIPDATA pData = (LPPRIVCLIPDATA)GlobalLock(hMem);
  454. if(pData)
  455. {
  456. BOOL fCut = pData->fCut;
  457. CShellFolder *psfFrom = NULL;
  458. IShellFolder *psfDesktop;
  459. LPITEMIDLIST pidl;
  460. pidl = (LPITEMIDLIST)((LPBYTE)(pData) + pData->aoffset[0]);
  461. /*
  462. This is a fully qualified PIDL, so use the desktop folder to get the
  463. IShellFolder for this folder.
  464. */
  465. SHGetDesktopFolder(&psfDesktop);
  466. if(psfDesktop)
  467. {
  468. psfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (LPVOID*)&psfFrom);
  469. psfDesktop->Release();
  470. }
  471. if(psfFrom)
  472. {
  473. LPITEMIDLIST *aPidls;
  474. //allocate an array of PIDLS
  475. aPidls = AllocPidlTable(pData->cidl - 1);
  476. if(aPidls)
  477. {
  478. UINT i;
  479. //fill in the PIDL array
  480. for(i = 0; i < pData->cidl - 1; i++)
  481. {
  482. aPidls[i] = m_pPidlMgr->Copy((LPITEMIDLIST)((LPBYTE)(pData) + pData->aoffset[i + 1]));
  483. }
  484. if(SUCCEEDED(m_psfParent->CopyItems(psfFrom, aPidls, pData->cidl - 1)))
  485. {
  486. fSuccess = TRUE;
  487. if(fCut)
  488. {
  489. psfFrom->DeleteItems(aPidls, pData->cidl - 1);
  490. }
  491. }
  492. FreePidlTable(aPidls);
  493. }
  494. psfFrom->Release();
  495. }
  496. GlobalUnlock(hMem);
  497. if(fSuccess && fCut)
  498. {
  499. //a successful cut and paste operation will remove the data from the clipboard
  500. EmptyClipboard();
  501. }
  502. }
  503. }
  504. CloseClipboard();
  505. return fSuccess;
  506. }
  507. /**************************************************************************
  508. CContextMenu::DoExplore()
  509. **************************************************************************/
  510. BOOL CContextMenu::DoExplore(HWND hWnd)
  511. {
  512. LPITEMIDLIST pidlFQ;
  513. SHELLEXECUTEINFO sei;
  514. pidlFQ = m_psfParent->CreateFQPidl(m_aPidls[0]);
  515. ZeroMemory(&sei, sizeof(sei));
  516. sei.cbSize = sizeof(sei);
  517. sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
  518. sei.lpIDList = pidlFQ;
  519. sei.lpClass = TEXT("folder");
  520. sei.hwnd = hWnd;
  521. sei.nShow = SW_SHOWNORMAL;
  522. sei.lpVerb = TEXT("explore");
  523. BOOL fReturn = ShellExecuteEx(&sei);
  524. m_pPidlMgr->Delete(pidlFQ);
  525. return fReturn;
  526. }
  527. /**************************************************************************
  528. CContextMenu::DoOpen()
  529. **************************************************************************/
  530. BOOL CContextMenu::DoOpen(HWND hWnd)
  531. {
  532. LPITEMIDLIST pidlFQ;
  533. SHELLEXECUTEINFO sei;
  534. pidlFQ = m_psfParent->CreateFQPidl(m_aPidls[0]);
  535. ZeroMemory(&sei, sizeof(sei));
  536. sei.cbSize = sizeof(sei);
  537. sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
  538. sei.lpIDList = pidlFQ;
  539. sei.lpClass = TEXT("folder");
  540. sei.hwnd = hWnd;
  541. sei.nShow = SW_SHOWNORMAL;
  542. sei.lpVerb = TEXT("open");
  543. BOOL fReturn = ShellExecuteEx(&sei);
  544. m_pPidlMgr->Delete(pidlFQ);
  545. return fReturn;
  546. }
  547. /**************************************************************************
  548. CContextMenu::DoDelete()
  549. **************************************************************************/
  550. STDMETHODIMP CContextMenu::DoDelete(VOID)
  551. {
  552. return m_psfParent->DeleteItems(m_aPidls, m_uItemCount);
  553. }
  554. /**************************************************************************
  555. CContextMenu::DoNewFolder()
  556. Add the folder with the new folder name and then put the ListView into
  557. rename mode.
  558. **************************************************************************/
  559. STDMETHODIMP CContextMenu::DoNewFolder(HWND hWnd)
  560. {
  561. HRESULT hr = E_FAIL;
  562. TCHAR szName[MAX_PATH];
  563. LPITEMIDLIST pidl;
  564. m_psfParent->GetUniqueName(TRUE, szName, MAX_PATH);
  565. hr = m_psfParent->AddFolder(szName, &pidl);
  566. if(SUCCEEDED(hr))
  567. {
  568. /*
  569. CShellFolder::AddFolder should have added the new item. Tell the view to
  570. put the item into edit mode.
  571. */
  572. CShellView *pView = (CShellView*)GetViewInterface(hWnd);
  573. if(pView)
  574. {
  575. pView->EditItem(pidl);
  576. pView->Release();
  577. }
  578. m_pPidlMgr->Delete(pidl);
  579. }
  580. return hr;
  581. }
  582. /**************************************************************************
  583. CContextMenu::DoNewItem()
  584. Add the item with the new item name and then put the ListView into
  585. rename mode.
  586. **************************************************************************/
  587. STDMETHODIMP CContextMenu::DoNewItem(HWND hWnd)
  588. {
  589. HRESULT hr;
  590. TCHAR szName[MAX_PATH];
  591. LPITEMIDLIST pidl;
  592. m_psfParent->GetUniqueName(FALSE, szName, MAX_PATH);
  593. hr = m_psfParent->AddItem(szName, NULL, &pidl);
  594. if(SUCCEEDED(hr))
  595. {
  596. /*
  597. CShellFolder::AddItem should have added the new item. Tell the view to
  598. put the item into edit mode.
  599. */
  600. CShellView *pView = (CShellView*)GetViewInterface(hWnd);
  601. if(pView)
  602. {
  603. pView->EditItem(pidl);
  604. pView->Release();
  605. }
  606. m_pPidlMgr->Delete(pidl);
  607. }
  608. return hr;
  609. }
  610. /**************************************************************************
  611. CContextMenu::DoRename()
  612. **************************************************************************/
  613. VOID CContextMenu::DoRename(HWND hWnd)
  614. {
  615. CShellView *pView = (CShellView*)GetViewInterface(hWnd);
  616. if(pView)
  617. {
  618. pView->EditItem(m_aPidls[0]);
  619. pView->Release();
  620. }
  621. }
  622. /**************************************************************************
  623. CContextMenu::DoModifyData()
  624. **************************************************************************/
  625. int CContextMenu::DoModifyData(HWND hwndList)
  626. {
  627. TCHAR szData[MAX_DATA];
  628. int nRet;
  629. //get the item's current data
  630. m_pPidlMgr->GetData(m_aPidls[0], szData, MAX_DATA);
  631. nRet = DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_ITEMDATADLG), hwndList, ItemDataDlgProc, (LPARAM)szData);
  632. if(IDOK == nRet)
  633. {
  634. m_psfParent->SetItemData(m_aPidls[0], szData);
  635. }
  636. return nRet;
  637. }
  638. /**************************************************************************
  639. CContextMenu::InsertBackgroundItems()
  640. **************************************************************************/
  641. UINT CContextMenu::InsertBackgroundItems( HMENU hMenu,
  642. UINT indexMenu,
  643. UINT idCmdFirst)
  644. {
  645. HMENU hPopup;
  646. TCHAR szText[MAX_PATH];
  647. MENUITEMINFO mii;
  648. ZeroMemory(&mii, sizeof(mii));
  649. mii.cbSize = sizeof(mii);
  650. //add the View submenu
  651. hPopup = CreatePopupMenu();
  652. if(hPopup)
  653. {
  654. AddViewMenuItems(hPopup, idCmdFirst, -1, TRUE);
  655. LoadString(g_hInst, IDS_VIEW, szText, sizeof(szText));
  656. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU;
  657. mii.wID = idCmdFirst + IDM_VIEW;
  658. mii.fType = MFT_STRING;
  659. mii.dwTypeData = szText;
  660. mii.fState = MFS_ENABLED;
  661. mii.hSubMenu = hPopup;
  662. InsertMenuItem( hMenu,
  663. indexMenu++,
  664. TRUE,
  665. &mii);
  666. //only add a separator if needed
  667. mii.fMask = MIIM_TYPE;
  668. GetMenuItemInfo(hMenu, indexMenu, TRUE, &mii);
  669. if(!(mii.fType & MFT_SEPARATOR))
  670. {
  671. ZeroMemory(&mii, sizeof(mii));
  672. mii.cbSize = sizeof(mii);
  673. mii.fMask = MIIM_ID | MIIM_TYPE;
  674. mii.wID = 0;
  675. mii.fType = MFT_SEPARATOR;
  676. InsertMenuItem( hMenu,
  677. indexMenu++,
  678. TRUE,
  679. &mii);
  680. }
  681. }
  682. indexMenu += AddFileMenuItems(hMenu, idCmdFirst, indexMenu, TRUE);
  683. //only add a separator if needed
  684. mii.fMask = MIIM_TYPE;
  685. GetMenuItemInfo(hMenu, indexMenu, TRUE, &mii);
  686. if(!(mii.fType & MFT_SEPARATOR))
  687. {
  688. ZeroMemory(&mii, sizeof(mii));
  689. mii.cbSize = sizeof(mii);
  690. mii.fMask = MIIM_ID | MIIM_TYPE;
  691. mii.wID = 0;
  692. mii.fType = MFT_SEPARATOR;
  693. InsertMenuItem( hMenu,
  694. indexMenu++,
  695. TRUE,
  696. &mii);
  697. }
  698. OpenClipboard(NULL);
  699. HGLOBAL hClip = GetClipboardData(m_cfPrivateData);
  700. CloseClipboard();
  701. LoadString(g_hInst, IDS_PASTE, szText, sizeof(szText));
  702. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  703. mii.wID = idCmdFirst + IDM_PASTE;
  704. mii.fType = MFT_STRING;
  705. mii.dwTypeData = szText;
  706. mii.fState = (hClip ? MFS_ENABLED : MFS_DISABLED);
  707. InsertMenuItem( hMenu,
  708. indexMenu++,
  709. TRUE,
  710. &mii);
  711. return indexMenu;
  712. }
  713. /**************************************************************************
  714. CContextMenu::InsertItems()
  715. **************************************************************************/
  716. UINT CContextMenu::InsertItems( HMENU hMenu,
  717. UINT indexMenu,
  718. UINT idCmdFirst,
  719. UINT uFlags)
  720. {
  721. MENUITEMINFO mii;
  722. TCHAR szText[MAX_PATH];
  723. BOOL fExplore = uFlags & CMF_EXPLORE;
  724. DWORD dwAttr = SFGAO_CANRENAME |
  725. SFGAO_CANDELETE |
  726. SFGAO_CANCOPY |
  727. SFGAO_CANMOVE |
  728. SFGAO_FOLDER;
  729. ZeroMemory(&mii, sizeof(mii));
  730. mii.cbSize = sizeof(mii);
  731. m_psfParent->GetAttributesOf(m_uItemCount, (LPCITEMIDLIST*)m_aPidls, &dwAttr);
  732. //only add the Open and Explore items if all items are folders.
  733. if(dwAttr & SFGAO_FOLDER)
  734. {
  735. if(fExplore)
  736. {
  737. LoadString(g_hInst, IDS_EXPLORE, szText, sizeof(szText));
  738. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  739. mii.wID = idCmdFirst + IDM_EXPLORE;
  740. mii.fType = MFT_STRING;
  741. mii.dwTypeData = szText;
  742. mii.fState = MFS_ENABLED | MFS_DEFAULT;
  743. InsertMenuItem( hMenu,
  744. indexMenu++,
  745. TRUE,
  746. &mii);
  747. LoadString(g_hInst, IDS_OPEN, szText, sizeof(szText));
  748. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  749. mii.wID = idCmdFirst + IDM_OPEN;
  750. mii.fType = MFT_STRING;
  751. mii.dwTypeData = szText;
  752. mii.fState = MFS_ENABLED;
  753. InsertMenuItem( hMenu,
  754. indexMenu++,
  755. TRUE,
  756. &mii);
  757. }
  758. else
  759. {
  760. LoadString(g_hInst, IDS_OPEN, szText, sizeof(szText));
  761. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  762. mii.wID = idCmdFirst + IDM_OPEN;
  763. mii.fType = MFT_STRING;
  764. mii.dwTypeData = szText;
  765. mii.fState = MFS_ENABLED | MFS_DEFAULT;
  766. InsertMenuItem( hMenu,
  767. indexMenu++,
  768. TRUE,
  769. &mii);
  770. LoadString(g_hInst, IDS_EXPLORE, szText, sizeof(szText));
  771. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  772. mii.wID = idCmdFirst + IDM_EXPLORE;
  773. mii.fType = MFT_STRING;
  774. mii.dwTypeData = szText;
  775. mii.fState = MFS_ENABLED;
  776. InsertMenuItem( hMenu,
  777. indexMenu++,
  778. TRUE,
  779. &mii);
  780. }
  781. }
  782. if(dwAttr & SFGAO_CANRENAME)
  783. {
  784. //only add a separator if needed
  785. if(GetMenuItemCount(hMenu))
  786. {
  787. mii.fMask = MIIM_TYPE;
  788. GetMenuItemInfo(hMenu, indexMenu, TRUE, &mii);
  789. if(!(mii.fType & MFT_SEPARATOR))
  790. {
  791. ZeroMemory(&mii, sizeof(mii));
  792. mii.cbSize = sizeof(mii);
  793. mii.fMask = MIIM_ID | MIIM_TYPE;
  794. mii.wID = 0;
  795. mii.fType = MFT_SEPARATOR;
  796. InsertMenuItem( hMenu,
  797. indexMenu++,
  798. TRUE,
  799. &mii);
  800. }
  801. }
  802. LoadString(g_hInst, IDS_RENAME, szText, sizeof(szText));
  803. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  804. mii.wID = idCmdFirst + IDM_RENAME;
  805. mii.fType = MFT_STRING;
  806. mii.dwTypeData = szText;
  807. mii.fState = ((uFlags & MYCMF_MULTISELECT) ? MFS_DISABLED : MFS_ENABLED);
  808. InsertMenuItem( hMenu,
  809. indexMenu++,
  810. TRUE,
  811. &mii);
  812. }
  813. //only add a separator if needed
  814. if(GetMenuItemCount(hMenu))
  815. {
  816. mii.fMask = MIIM_TYPE;
  817. GetMenuItemInfo(hMenu, indexMenu, TRUE, &mii);
  818. if(!(mii.fType & MFT_SEPARATOR))
  819. {
  820. mii.fMask = MIIM_ID | MIIM_TYPE;
  821. mii.wID = 0;
  822. mii.fType = MFT_SEPARATOR;
  823. InsertMenuItem( hMenu,
  824. indexMenu++,
  825. TRUE,
  826. &mii);
  827. }
  828. }
  829. LoadString(g_hInst, IDS_CUT, szText, sizeof(szText));
  830. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  831. mii.wID = idCmdFirst + IDM_CUT;
  832. mii.fType = MFT_STRING;
  833. mii.dwTypeData = szText;
  834. mii.fState = ((dwAttr & SFGAO_CANMOVE) ? MFS_ENABLED : MFS_DISABLED);
  835. InsertMenuItem( hMenu,
  836. indexMenu++,
  837. TRUE,
  838. &mii);
  839. LoadString(g_hInst, IDS_COPY, szText, sizeof(szText));
  840. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  841. mii.wID = idCmdFirst + IDM_COPY;
  842. mii.fType = MFT_STRING;
  843. mii.dwTypeData = szText;
  844. mii.fState = ((dwAttr & SFGAO_CANCOPY) ? MFS_ENABLED : MFS_DISABLED);
  845. InsertMenuItem( hMenu,
  846. indexMenu++,
  847. TRUE,
  848. &mii);
  849. if(dwAttr & SFGAO_CANDELETE)
  850. {
  851. //only add a separator if needed
  852. if(GetMenuItemCount(hMenu))
  853. {
  854. mii.fMask = MIIM_TYPE;
  855. GetMenuItemInfo(hMenu, indexMenu, TRUE, &mii);
  856. if(!(mii.fType & MFT_SEPARATOR))
  857. {
  858. ZeroMemory(&mii, sizeof(mii));
  859. mii.cbSize = sizeof(mii);
  860. mii.fMask = MIIM_ID | MIIM_TYPE;
  861. mii.wID = 0;
  862. mii.fType = MFT_SEPARATOR;
  863. InsertMenuItem( hMenu,
  864. indexMenu++,
  865. TRUE,
  866. &mii);
  867. }
  868. }
  869. LoadString(g_hInst, IDS_DELETE, szText, sizeof(szText));
  870. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  871. mii.wID = idCmdFirst + IDM_DELETE;
  872. mii.fType = MFT_STRING;
  873. mii.dwTypeData = szText;
  874. mii.fState = MFS_ENABLED;
  875. InsertMenuItem( hMenu,
  876. indexMenu++,
  877. TRUE,
  878. &mii);
  879. }
  880. if(!(dwAttr & SFGAO_FOLDER) && !(m_fBackground))
  881. {
  882. //only add a separator if needed
  883. if(GetMenuItemCount(hMenu))
  884. {
  885. mii.fMask = MIIM_TYPE;
  886. GetMenuItemInfo(hMenu, indexMenu, TRUE, &mii);
  887. if(!(mii.fType & MFT_SEPARATOR))
  888. {
  889. ZeroMemory(&mii, sizeof(mii));
  890. mii.cbSize = sizeof(mii);
  891. mii.fMask = MIIM_ID | MIIM_TYPE;
  892. mii.wID = 0;
  893. mii.fType = MFT_SEPARATOR;
  894. InsertMenuItem( hMenu,
  895. indexMenu++,
  896. TRUE,
  897. &mii);
  898. }
  899. }
  900. LoadString(g_hInst, IDS_MODIFY_DATA, szText, sizeof(szText));
  901. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
  902. mii.wID = idCmdFirst + IDM_MODIFY_DATA;
  903. mii.fType = MFT_STRING;
  904. mii.dwTypeData = szText;
  905. mii.fState = ((uFlags & MYCMF_MULTISELECT) ? MFS_DISABLED : MFS_ENABLED);
  906. InsertMenuItem( hMenu,
  907. indexMenu++,
  908. TRUE,
  909. &mii);
  910. }
  911. return indexMenu;
  912. }