Source code of Windows XP (NT5)
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.

652 lines
13 KiB

  1. //*******************************************************************************************
  2. //
  3. // Filename : SFVMenu.cpp
  4. //
  5. // Implementation file for CSFView menu related methods
  6. //
  7. // Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
  8. //
  9. //*******************************************************************************************
  10. #include "Pch.H"
  11. #include "SFView.H"
  12. #include "SFVWnd.H"
  13. #include "Resource.H"
  14. enum
  15. {
  16. SUBMENU_EDIT,
  17. SUBMENU_VIEW,
  18. } ;
  19. enum
  20. {
  21. SUBMENUNF_EDIT,
  22. SUBMENUNF_VIEW,
  23. } ;
  24. static HMENU _GetMenuFromID(HMENU hmMain, UINT uID)
  25. {
  26. MENUITEMINFO miiSubMenu;
  27. miiSubMenu.cbSize = sizeof(MENUITEMINFO);
  28. miiSubMenu.fMask = MIIM_SUBMENU;
  29. miiSubMenu.cch = 0; // just in case
  30. if (!GetMenuItemInfo(hmMain, uID, FALSE, &miiSubMenu))
  31. {
  32. return NULL;
  33. }
  34. return(miiSubMenu.hSubMenu);
  35. }
  36. static int _GetOffsetFromID(HMENU hmMain, UINT uID)
  37. {
  38. int index;
  39. for (index = GetMenuItemCount(hmMain)-1; index>=0; index--)
  40. {
  41. MENUITEMINFO mii;
  42. mii.cbSize = sizeof(MENUITEMINFO);
  43. mii.fMask = MIIM_ID;
  44. mii.cch = 0; // just in case
  45. if (GetMenuItemInfo(hmMain, (UINT)index, TRUE, &mii)
  46. && (mii.wID == FCIDM_MENU_VIEW_SEP_OPTIONS))
  47. {
  48. // merge it right above the separator.
  49. break;
  50. }
  51. }
  52. return(index);
  53. }
  54. int CSFView::GetMenuIDFromViewMode()
  55. {
  56. switch (m_fs.ViewMode)
  57. {
  58. case FVM_SMALLICON:
  59. return(IDC_VIEW_SMALLICON);
  60. case FVM_LIST:
  61. return(IDC_VIEW_LIST);
  62. case FVM_DETAILS:
  63. return(IDC_VIEW_DETAILS);
  64. default:
  65. return(IDC_VIEW_ICON);
  66. }
  67. }
  68. BOOL CSFView::GetArrangeText(int iCol, UINT idFmt, LPSTR pszText, UINT cText)
  69. {
  70. char szFormat[200];
  71. LoadString(g_ThisDll.GetInstance(), idFmt, szFormat, sizeof(szFormat));
  72. LV_COLUMN col;
  73. char szText[80];
  74. col.mask = LVCF_TEXT;
  75. col.pszText = szText;
  76. col.cchTextMax = sizeof(szText);
  77. if (!m_cView.GetColumn(iCol, &col))
  78. {
  79. return(FALSE);
  80. }
  81. char szCommand[sizeof(szFormat)+sizeof(szText)];
  82. wsprintf(szCommand, szFormat, szText);
  83. lstrcpyn(pszText, szCommand, cText);
  84. return(TRUE);
  85. }
  86. void CSFView::MergeArrangeMenu(HMENU hmView)
  87. {
  88. // Now add the sorting menu items
  89. for (int i=0; i<MAX_COL; ++i)
  90. {
  91. MENUITEMINFO mii;
  92. mii.cbSize = sizeof(mii);
  93. char szCommand[100];
  94. if (!GetArrangeText(i, IDS_BYCOL_FMT, szCommand, sizeof(szCommand)))
  95. {
  96. mii.fMask = MIIM_TYPE;
  97. mii.fType = MFT_SEPARATOR;
  98. InsertMenuItem(hmView, IDC_ARRANGE_AUTO, FALSE, &mii);
  99. break;
  100. }
  101. mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
  102. mii.fType = MFT_STRING;
  103. mii.fState = MF_ENABLED;
  104. mii.wID = IDC_ARRANGE_BY + i;
  105. mii.dwTypeData = szCommand;
  106. InsertMenuItem(hmView, IDC_ARRANGE_AUTO, FALSE, &mii);
  107. }
  108. }
  109. void CSFView::MergeViewMenu(HMENU hmenu, HMENU hmMerge)
  110. {
  111. HMENU hmView = _GetMenuFromID(hmenu, FCIDM_MENU_VIEW);
  112. if (!hmView)
  113. {
  114. return;
  115. }
  116. int iOptions = _GetOffsetFromID(hmView, FCIDM_MENU_VIEW_SEP_OPTIONS);
  117. Cab_MergeMenus(hmView, hmMerge, (UINT)iOptions, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST,
  118. MM_SUBMENUSHAVEIDS | MM_ADDSEPARATOR);
  119. MergeArrangeMenu(hmView);
  120. }
  121. //*****************************************************************************
  122. //
  123. // CSFView::OnActivate
  124. //
  125. // Purpose:
  126. //
  127. // handles the UIActivate call by ShellBrowser
  128. //
  129. // Parameters:
  130. //
  131. // UINT uState - UIActivate flag
  132. //
  133. // Comments:
  134. //
  135. //*****************************************************************************
  136. BOOL CSFView::OnActivate(UINT uState)
  137. {
  138. if (m_uState == uState)
  139. {
  140. return(TRUE);
  141. }
  142. OnDeactivate();
  143. {
  144. // Scope cMenu
  145. CMenuTemp cMenu(CreateMenu());
  146. if (!((HMENU)cMenu))
  147. {
  148. return(TRUE);
  149. }
  150. OLEMENUGROUPWIDTHS mwidth = { { 0, 0, 0, 0, 0, 0 } };
  151. // insert menus into the shell browser
  152. // Explorer returns the wrong value so don't check
  153. m_psb->InsertMenusSB(cMenu, &mwidth);
  154. // store this current menu
  155. m_cmCur.Attach(cMenu.Detach());
  156. }
  157. // Get the edit menu in the browser
  158. HMENU hmEdit = _GetMenuFromID(m_cmCur, FCIDM_MENU_EDIT);
  159. if (uState == SVUIA_ACTIVATE_FOCUS)
  160. {
  161. // load the menu resource
  162. CMenuTemp cmMerge(LoadMenu(g_ThisDll.GetInstance(),
  163. MAKEINTRESOURCE(MENU_SFV_MAINMERGE)));
  164. if ((HMENU)cmMerge)
  165. {
  166. // merge it with Edit submenu
  167. Cab_MergeMenus(hmEdit, GetSubMenu(cmMerge, SUBMENU_EDIT), (UINT)-1,
  168. FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);
  169. // add the view menu
  170. MergeViewMenu(m_cmCur, GetSubMenu(cmMerge, SUBMENU_VIEW));
  171. }
  172. }
  173. else
  174. {
  175. CMenuTemp cmMerge(LoadMenu(g_ThisDll.GetInstance(),
  176. MAKEINTRESOURCE(MENU_SFV_MAINMERGENF)));
  177. if ((HMENU)cmMerge)
  178. {
  179. Cab_MergeMenus(hmEdit, GetSubMenu(cmMerge, SUBMENUNF_EDIT), (UINT)-1,
  180. FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);
  181. // view menu
  182. MergeViewMenu(m_cmCur, GetSubMenu(cmMerge, SUBMENUNF_VIEW));
  183. }
  184. }
  185. // install the composite menu into the shell browser
  186. m_psb->SetMenuSB(m_cmCur, NULL, m_cView);
  187. m_uState = uState;
  188. return TRUE;
  189. }
  190. BOOL CSFView::OnDeactivate()
  191. {
  192. if (m_uState != SVUIA_DEACTIVATE)
  193. {
  194. m_psb->SetMenuSB(NULL, NULL, NULL);
  195. m_psb->RemoveMenusSB(m_cmCur);
  196. DestroyMenu(m_cmCur.Detach());
  197. m_uState = SVUIA_DEACTIVATE;
  198. }
  199. return TRUE;
  200. }
  201. //*****************************************************************************
  202. //
  203. // CSFView::OnCommand
  204. //
  205. // Purpose:
  206. //
  207. // handle the WM_COMMAND sent by the explorer to the view
  208. //
  209. // Comments:
  210. //
  211. //*****************************************************************************
  212. void CSFView::OnCommand(IContextMenu *pcm, WPARAM wParam, LPARAM lParam)
  213. {
  214. if (!pcm)
  215. {
  216. pcm = m_pcmSel;
  217. }
  218. if (pcm)
  219. {
  220. pcm->AddRef();
  221. }
  222. CEnsureRelease erContext(pcm);
  223. int idCmd = GET_WM_COMMAND_ID(wParam, lParam);
  224. DWORD dwStyle;
  225. switch (idCmd)
  226. {
  227. // Set the FOLDERSETTINGS for this view
  228. case IDC_VIEW_ICON + FCIDM_SHVIEWFIRST:
  229. dwStyle = LVS_ICON;
  230. m_fs.ViewMode = FVM_ICON;
  231. goto SetStyle;
  232. case IDC_VIEW_SMALLICON + FCIDM_SHVIEWFIRST:
  233. dwStyle = LVS_SMALLICON;
  234. m_fs.ViewMode = FVM_SMALLICON;
  235. goto SetStyle;
  236. case IDC_VIEW_LIST + FCIDM_SHVIEWFIRST:
  237. dwStyle = LVS_LIST;
  238. m_fs.ViewMode = FVM_LIST;
  239. goto SetStyle;
  240. case IDC_VIEW_DETAILS + FCIDM_SHVIEWFIRST:
  241. dwStyle = LVS_REPORT;
  242. m_fs.ViewMode = FVM_DETAILS;
  243. goto SetStyle;
  244. // set the style of the Listview accordingly
  245. SetStyle:
  246. m_cView.SetStyle(dwStyle, LVS_TYPEMASK);
  247. CheckToolbar();
  248. break;
  249. // handle the Copy operation
  250. case IDC_EDIT_COPY + FCIDM_SHVIEWFIRST:
  251. {
  252. LPDATAOBJECT pdtobj;
  253. if (!m_cView.OleInited()
  254. || FAILED(m_cView.GetUIObjectFromItem(IID_IDataObject, (LPVOID*)&pdtobj,
  255. SVGIO_SELECTION)))
  256. {
  257. MessageBeep(0);
  258. break;
  259. }
  260. CEnsureRelease erData(pdtobj);
  261. OleSetClipboard(pdtobj);
  262. break;
  263. }
  264. // handle selection of items
  265. case IDC_EDIT_SELALL + FCIDM_SHVIEWFIRST:
  266. SetFocus(m_cView);
  267. m_cView.SelAll();
  268. break;
  269. case IDC_EDIT_INVSEL + FCIDM_SHVIEWFIRST:
  270. SetFocus(m_cView);
  271. m_cView.InvSel();
  272. break;
  273. default:
  274. if (idCmd>=IDC_ARRANGE_BY && idCmd<IDC_ARRANGE_BY+MAX_COL)
  275. {
  276. ColumnClick(idCmd - IDC_ARRANGE_BY);
  277. }
  278. else if (pcm && idCmd>=SFV_CONTEXT_FIRST && idCmd<=SFV_CONTEXT_LAST)
  279. {
  280. // invoke the context menu
  281. CMINVOKECOMMANDINFO ici;
  282. ici.cbSize = sizeof(ici);
  283. ici.fMask = 0;
  284. ici.hwnd = m_hwndMain;
  285. ici.lpVerb = MAKEINTRESOURCE(idCmd - SFV_CONTEXT_FIRST);
  286. ici.lpParameters = NULL;
  287. ici.lpDirectory = NULL;
  288. ici.nShow = SW_SHOWNORMAL;
  289. pcm->InvokeCommand(&ici);
  290. }
  291. break;
  292. }
  293. }
  294. IContextMenu * CSFView::GetSelContextMenu()
  295. {
  296. if (!m_pcmSel)
  297. {
  298. if (FAILED(m_cView.GetUIObjectFromItem(IID_IContextMenu, (LPVOID *)&m_pcmSel,
  299. SVGIO_SELECTION)))
  300. {
  301. m_pcmSel = NULL;
  302. return(m_pcmSel);
  303. }
  304. }
  305. m_pcmSel->AddRef();
  306. return(m_pcmSel);
  307. }
  308. void CSFView::ReleaseSelContextMenu()
  309. {
  310. if (m_pcmSel)
  311. {
  312. m_pcmSel->Release();
  313. m_pcmSel = NULL;
  314. }
  315. }
  316. void CSFView::InitFileMenu(HMENU hmInit)
  317. {
  318. //
  319. // Don't touch the file menu unless we have the focus.
  320. //
  321. if (m_uState != SVUIA_ACTIVATE_FOCUS)
  322. {
  323. return;
  324. }
  325. BOOL bDeleteItems = FALSE;
  326. int i;
  327. // Remove all the menu items we've added.
  328. for (i = GetMenuItemCount(hmInit) - 1; i >= 0; --i)
  329. {
  330. if (!bDeleteItems)
  331. {
  332. MENUITEMINFO mii;
  333. mii.cbSize = sizeof(mii);
  334. mii.fMask = MIIM_ID;
  335. mii.cch = 0; // just in case
  336. if (GetMenuItemInfo(hmInit, i, TRUE, &mii))
  337. {
  338. if (mii.wID>=SFV_CONTEXT_FIRST && mii.wID<=SFV_CONTEXT_LAST)
  339. {
  340. bDeleteItems = TRUE;
  341. }
  342. }
  343. }
  344. if (bDeleteItems)
  345. {
  346. DeleteMenu(hmInit, i, MF_BYPOSITION);
  347. }
  348. }
  349. // Let the object add the separator.
  350. if (CSFViewDlg::IsMenuSeparator(hmInit, 0))
  351. {
  352. DeleteMenu(hmInit, 0, MF_BYPOSITION);
  353. }
  354. //
  355. // Now add item specific commands to the menu
  356. // This is done by seeing if we already have a context menu
  357. // object for our selection. If not we generate it now.
  358. //
  359. IContextMenu *pcmSel = GetSelContextMenu();
  360. if (pcmSel)
  361. {
  362. pcmSel->QueryContextMenu(hmInit, 0, SFV_CONTEXT_FIRST,
  363. SFV_CONTEXT_LAST, CMF_DVFILE);
  364. pcmSel->Release();
  365. }
  366. // Note that the SelContextMenu stays around until the selection changes or we
  367. // close the window, but it doesn't really matter that much
  368. }
  369. void CSFView::InitEditMenu(HMENU hmInit)
  370. {
  371. ULONG dwAttr = SFGAO_CANCOPY;
  372. UINT uFlags = (m_cView.OleInited()
  373. && SUCCEEDED(m_cView.GetAttributesFromItem(&dwAttr, SVGIO_SELECTION))
  374. && (dwAttr & SFGAO_CANCOPY)) ? MF_ENABLED : MF_GRAYED;
  375. EnableMenuItem(hmInit, IDC_EDIT_COPY + FCIDM_SHVIEWFIRST, uFlags | MF_BYCOMMAND);
  376. }
  377. void CSFView::InitViewMenu(HMENU hmInit)
  378. {
  379. int iCurViewMenuItem = GetMenuIDFromViewMode() + FCIDM_SHVIEWFIRST;
  380. UINT uEnable;
  381. CheckMenuRadioItem(hmInit, IDC_VIEW_ICON, IDC_VIEW_DETAILS,
  382. iCurViewMenuItem, MF_BYCOMMAND | MF_CHECKED);
  383. uEnable = (iCurViewMenuItem==IDC_VIEW_LIST+FCIDM_SHVIEWFIRST
  384. || iCurViewMenuItem==IDC_VIEW_DETAILS+FCIDM_SHVIEWFIRST) ?
  385. (MF_GRAYED | MF_BYCOMMAND) : (MF_ENABLED | MF_BYCOMMAND);
  386. uEnable = MF_GRAYED | MF_BYCOMMAND;
  387. EnableMenuItem(hmInit, IDC_ARRANGE_GRID + FCIDM_SHVIEWFIRST, uEnable);
  388. EnableMenuItem(hmInit, IDC_ARRANGE_AUTO + FCIDM_SHVIEWFIRST, uEnable);
  389. CheckMenuItem(hmInit, IDC_ARRANGE_AUTO + FCIDM_SHVIEWFIRST,
  390. ((uEnable == (MF_ENABLED | MF_BYCOMMAND)) && (m_fs.fFlags & FWF_AUTOARRANGE))
  391. ? MF_CHECKED : MF_UNCHECKED);
  392. }
  393. //*****************************************************************************
  394. //
  395. // CSFView::OnInitMenuPopup
  396. //
  397. // Purpose:
  398. //
  399. // handle the WM_INITMENUPOPUP message received by CSFViewDlg
  400. //
  401. //
  402. //*****************************************************************************
  403. BOOL CSFView::OnInitMenuPopup(HMENU hmInit, int nIndex, BOOL fSystemMenu)
  404. {
  405. if (!(HMENU)m_cmCur)
  406. {
  407. return(TRUE);
  408. }
  409. MENUITEMINFO mii;
  410. mii.cbSize = sizeof(MENUITEMINFO);
  411. mii.fMask = MIIM_SUBMENU|MIIM_ID;
  412. mii.cch = 0; // just in case
  413. if (!GetMenuItemInfo(m_cmCur, nIndex, TRUE, &mii) || mii.hSubMenu!=hmInit)
  414. {
  415. return(TRUE);
  416. }
  417. switch (mii.wID)
  418. {
  419. case FCIDM_MENU_FILE:
  420. InitFileMenu(hmInit);
  421. break;
  422. case FCIDM_MENU_EDIT:
  423. InitEditMenu(hmInit);
  424. break;
  425. case FCIDM_MENU_VIEW:
  426. InitViewMenu(hmInit);
  427. break;
  428. default:
  429. return 1L;
  430. }
  431. return 0L;
  432. }
  433. int _FindIt(const UINT *puFirst, UINT uFind, UINT uStep, int cCount)
  434. {
  435. LPBYTE pbFirst = (LPBYTE)puFirst;
  436. for (--cCount, pbFirst+=cCount*uStep; cCount>=0; --cCount, pbFirst-=uStep)
  437. {
  438. if (*(UINT *)pbFirst == uFind)
  439. {
  440. break;
  441. }
  442. }
  443. return(cCount);
  444. }
  445. const struct
  446. {
  447. UINT idCmd;
  448. UINT idStr;
  449. UINT idTT;
  450. } c_idTbl[] =
  451. {
  452. IDC_VIEW_ICON, IDS_VIEW_ICON, IDS_TT_VIEW_ICON,
  453. IDC_VIEW_SMALLICON, IDS_VIEW_SMALLICON, IDS_TT_VIEW_SMALLICON,
  454. IDC_VIEW_LIST, IDS_VIEW_LIST, IDS_TT_VIEW_LIST,
  455. IDC_VIEW_DETAILS, IDS_VIEW_DETAILS, IDS_TT_VIEW_DETAILS,
  456. IDC_EDIT_COPY, IDS_EDIT_COPY, IDS_TT_EDIT_COPY,
  457. IDC_EDIT_SELALL, IDS_EDIT_SELALL, 0,
  458. IDC_EDIT_INVSEL, IDS_EDIT_INVSEL, 0,
  459. IDC_ARRANGE_GRID, IDS_ARRANGE_GRID, 0,
  460. IDC_ARRANGE_AUTO, IDS_ARRANGE_AUTO, 0,
  461. } ;
  462. void CSFView::GetCommandHelpText(UINT idCmd, LPSTR pszText, UINT cchText, BOOL bToolTip)
  463. {
  464. *pszText = 0;
  465. if (idCmd>=SFV_CONTEXT_FIRST && idCmd<=SFV_CONTEXT_LAST && m_pcmSel)
  466. {
  467. if (bToolTip)
  468. {
  469. return;
  470. }
  471. m_pcmSel->GetCommandString(idCmd - SFV_CONTEXT_FIRST, GCS_HELPTEXT, NULL,
  472. pszText, cchText);
  473. }
  474. else if (idCmd>=IDC_ARRANGE_BY && idCmd<IDC_ARRANGE_BY+MAX_COL)
  475. {
  476. if (bToolTip)
  477. {
  478. return;
  479. }
  480. GetArrangeText(idCmd-IDC_ARRANGE_BY, IDS_BYCOL_HELP_FMT, pszText, cchText);
  481. }
  482. else
  483. {
  484. int iid = _FindIt(&c_idTbl[0].idCmd, idCmd-FCIDM_SHVIEWFIRST, sizeof(c_idTbl[0]),
  485. ARRAYSIZE(c_idTbl));
  486. if (iid >= 0)
  487. {
  488. LoadString(g_ThisDll.GetInstance(),
  489. bToolTip ? c_idTbl[iid].idTT : c_idTbl[iid].idStr, pszText, cchText);
  490. }
  491. }
  492. }
  493. LRESULT CSFView::OnMenuSelect(UINT idCmd, UINT uFlags, HMENU hmenu)
  494. {
  495. // If we dismissed the menu restore our status bar...
  496. if (!hmenu && LOWORD(uFlags)==0xffff)
  497. {
  498. m_psb->SendControlMsg(FCW_STATUS, SB_SIMPLE, 0, 0L, NULL);
  499. return 0L;
  500. }
  501. if (uFlags & (MF_SYSMENU | MF_SEPARATOR))
  502. {
  503. return 0L;
  504. }
  505. char szHelpText[80 + 2*MAX_PATH];
  506. szHelpText[0] = 0; // in case of failures below
  507. if (uFlags & MF_POPUP)
  508. {
  509. MENUITEMINFO miiSubMenu;
  510. miiSubMenu.cbSize = sizeof(MENUITEMINFO);
  511. miiSubMenu.fMask = MIIM_ID;
  512. miiSubMenu.cch = 0; // just in case
  513. if (!GetMenuItemInfo(hmenu, idCmd, TRUE, &miiSubMenu))
  514. {
  515. return 0;
  516. }
  517. // Change the parameters to simulate a "normal" menu item
  518. idCmd = miiSubMenu.wID;
  519. uFlags &= ~MF_POPUP;
  520. }
  521. GetCommandHelpText(idCmd, szHelpText, sizeof(szHelpText), FALSE);
  522. m_psb->SendControlMsg(FCW_STATUS, SB_SETTEXT, SBT_NOBORDERS | 255,
  523. (LPARAM)szHelpText, NULL);
  524. m_psb->SendControlMsg(FCW_STATUS, SB_SIMPLE, 1, 0L, NULL);
  525. return 0;
  526. }