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.

1881 lines
56 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1992 - 1999
  6. //
  7. // File: toolbar.cpp
  8. //
  9. // Contents: ToolBars implementation
  10. //
  11. // History: 09-30-99 AnandhaG Created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "stdafx.h"
  15. #include "ChildFrm.h"
  16. #include "mainfrm.h"
  17. #include "controls.h"
  18. #include "toolbar.h"
  19. #include "bitmap.h"
  20. #include "amcview.h"
  21. #include "util.h"
  22. int CAMCViewToolbars::s_idCommand = MMC_TOOLBUTTON_ID_FIRST;
  23. CAMCViewToolbars::~CAMCViewToolbars()
  24. {
  25. // Ask the toolbars (on nodemgr side) that reference this object to
  26. // remove their references.
  27. TBarToBitmapIndex::iterator itToolbars = m_mapTBarToBitmapIndex.begin();
  28. for (;itToolbars != m_mapTBarToBitmapIndex.end(); ++itToolbars)
  29. {
  30. CToolbarNotify* pNotifyCallbk = itToolbars->first;
  31. SC sc = ScCheckPointers(pNotifyCallbk, E_UNEXPECTED);
  32. if (sc)
  33. {
  34. sc.TraceAndClear();
  35. continue;
  36. }
  37. sc = pNotifyCallbk->ScAMCViewToolbarsBeingDestroyed();
  38. if (sc)
  39. {
  40. sc.TraceAndClear();
  41. continue;
  42. }
  43. }
  44. }
  45. //+-------------------------------------------------------------------
  46. //
  47. // Member: CAMCViewToolbars::ScInit
  48. //
  49. // Synopsis: Initialize the object by createing imagelist.
  50. //
  51. // Arguments:
  52. //
  53. // Returns: SC
  54. //
  55. //--------------------------------------------------------------------
  56. SC CAMCViewToolbars::ScInit ()
  57. {
  58. AFX_MANAGE_STATE (AfxGetAppModuleState());
  59. DECLARE_SC(sc, _T("CAMCViewToolbars::ScInit"));
  60. if (m_ImageList.m_hImageList)
  61. return (sc = E_UNEXPECTED);
  62. // Create an imagelist.
  63. BOOL b = m_ImageList.Create(BUTTON_BITMAP_SIZE, BUTTON_BITMAP_SIZE,
  64. ILC_COLORDDB|ILC_MASK,
  65. 20 /*Initial imagelist size*/, 10 /* grow */);
  66. if (!b)
  67. return (sc = E_FAIL);
  68. m_ImageList.SetBkColor(CLR_NONE);
  69. return (sc);
  70. }
  71. //+-------------------------------------------------------------------
  72. //
  73. // Member: CAMCViewToolbars::ScCreateToolBar
  74. //
  75. // Synopsis: Create a Toolbar (Just return CMMCToolbarIntf).
  76. //
  77. // Arguments:
  78. // [ppToolbarIntf] - corresponds to IToolbar imp.
  79. // call this interface to manipulate toolbar UI.
  80. //
  81. // Returns: SC
  82. //
  83. //--------------------------------------------------------------------
  84. SC CAMCViewToolbars::ScCreateToolBar (CMMCToolbarIntf** ppToolbarIntf)
  85. {
  86. DECLARE_SC(sc, _T("CAMCViewToolbars::ScCreateToolBar"));
  87. sc = ScCheckPointers(ppToolbarIntf);
  88. if (sc)
  89. return sc;
  90. *ppToolbarIntf = this;
  91. return (sc);
  92. }
  93. //+-------------------------------------------------------------------
  94. //
  95. // Member: CAMCViewToolbars::ScDisableToolbars
  96. //
  97. // Synopsis: Disable all the toolbar buttons (reqd during LV multiselect).
  98. //
  99. // Arguments:
  100. //
  101. // Returns: SC
  102. //
  103. //--------------------------------------------------------------------
  104. SC CAMCViewToolbars::ScDisableToolbars ()
  105. {
  106. DECLARE_SC(sc, _T("CAMCViewToolbars::ScDisableToolbars"));
  107. if (! m_fViewActive)
  108. return (sc = E_UNEXPECTED);
  109. // Now iterate thro all toolbuttons & disable them.
  110. ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
  111. for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
  112. {
  113. CMMCToolbarButton *pToolButton = itBtn;
  114. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  115. if (sc)
  116. return sc;
  117. // Set the UI button state.
  118. sc = ScSetButtonStateInToolbar(pToolButton, TBSTATE_ENABLED, FALSE);
  119. if (sc)
  120. return sc;
  121. // Save the new state.
  122. BYTE byOldState = pToolButton->GetState();
  123. pToolButton->SetState(byOldState & ~TBSTATE_ENABLED);
  124. }
  125. return (sc);
  126. }
  127. //+-------------------------------------------------------------------
  128. //
  129. // Member: CAMCViewToolbars::ScAddBitmap
  130. //
  131. // Synopsis: Add the given bitmap into the view toolbars imagelist.
  132. // Also store the start index & number of images in an object
  133. // mapped by the CToolbarNotify (which identifies snapin toolbar
  134. // or std bar).
  135. //
  136. // Arguments: [pNotifyCallbk] - The toolbar identifier (Button click callback interface).
  137. // [nImages] - Number of bitmaps.
  138. // [hbmp] - Handle to the bitmap.
  139. // [crMask] - Color used to generate a mask to overlay
  140. // the images on the toolbar button.
  141. //
  142. // Returns: SC
  143. //
  144. //--------------------------------------------------------------------
  145. SC CAMCViewToolbars::ScAddBitmap (CToolbarNotify* pNotifyCallbk, INT nImages,
  146. HBITMAP hbmp, COLORREF crMask)
  147. {
  148. AFX_MANAGE_STATE (AfxGetAppModuleState());
  149. DECLARE_SC(sc, _T("CAMCViewToolbars::ScAddBitmap"));
  150. sc = ScCheckPointers(pNotifyCallbk, hbmp);
  151. if (sc)
  152. return sc;
  153. /*
  154. * make a copy of the input bitmap because ImageList_AddMasked will
  155. * modify the input bitmap
  156. */
  157. CBitmap bmpCopy;
  158. bmpCopy.Attach (CopyBitmap (hbmp));
  159. if (bmpCopy.GetSafeHandle() == NULL)
  160. return (sc.FromLastError());
  161. sc = ScCheckPointers(m_ImageList.m_hImageList, E_UNEXPECTED);
  162. if (sc)
  163. return sc;
  164. MMCToolbarImages imagesNew;
  165. int cImagesOld = m_ImageList.GetImageCount();
  166. // First add the bitmap into the imagelist.
  167. imagesNew.iStart = m_ImageList.Add (bmpCopy, crMask);
  168. imagesNew.cCount = m_ImageList.GetImageCount() - cImagesOld;
  169. if (imagesNew.iStart == -1)
  170. return (sc = E_FAIL);
  171. /*
  172. * Assume a snapin adds 3 bitmaps initialy & then 4 for a toolbar.
  173. * Then while adding buttons it will specify bitmap index as 5.
  174. *
  175. * So this toolbar will have two MMCToolbarImages objects in the multimap.
  176. *
  177. * The first MMCToolbarImages has cCount = 3, iStartWRTSnapin = 0, thus
  178. * images from 0 (iStartWRTSnapin) to 3 (iStartWRTSnapin + cCount) with respect
  179. * to snapin.
  180. * The second MMCToolbarImages has cCount = 4, iStartWRTSnapin = 3, thus
  181. * images from 3(iStartWRTSnapin) to 7(iStartWRTSnapin + cCount) wrt snapin.
  182. *
  183. * The iStartWRTSnapin member is nothing but the largest of iStartWRTSnapin + cCount
  184. * in all of this toolbars MMCToolbarImages.
  185. *
  186. */
  187. std::pair<TBarToBitmapIndex::iterator, TBarToBitmapIndex::iterator>
  188. range = m_mapTBarToBitmapIndex.equal_range(pNotifyCallbk);
  189. imagesNew.iStartWRTSnapin = 0;
  190. while (range.first != range.second)
  191. {
  192. // Go thro each item and get the correct start index.
  193. MMCToolbarImages imagesOld = (range.first)->second;
  194. int nLastImageIndex = imagesOld.iStartWRTSnapin + imagesOld.cCount;
  195. if ( imagesNew.iStartWRTSnapin < nLastImageIndex )
  196. imagesNew.iStartWRTSnapin = nLastImageIndex;
  197. (range.first)++;
  198. }
  199. // Now store the start index, number of bitmaps identified
  200. // by CToolbarNotify in a multi-map.
  201. m_mapTBarToBitmapIndex.insert(
  202. TBarToBitmapIndex::value_type(pNotifyCallbk, imagesNew) );
  203. // To be compatible with SysInfo snapin dont return error.
  204. if ((cImagesOld + nImages) > m_ImageList.GetImageCount())
  205. {
  206. sc = E_INVALIDARG;
  207. TraceSnapinError(_T("IToolbar::AddBitmap, Number of bitmaps is less than number mentioned"), sc);
  208. sc.Clear();
  209. }
  210. return (sc);
  211. }
  212. //+-------------------------------------------------------------------
  213. //
  214. // Member: ScValidateButton
  215. //
  216. // Synopsis: Validate the MMCBUTTON data.
  217. //
  218. // Arguments:
  219. // [nButtons] - Number of elements in MMCBUTTON array.
  220. // [lpButtons] - MMCBUTTON array.
  221. //
  222. // Returns: SC
  223. //
  224. //--------------------------------------------------------------------
  225. SC CAMCViewToolbars::ScValidateButton(int nButtons, LPMMCBUTTON lpButtons)
  226. {
  227. AFX_MANAGE_STATE (AfxGetAppModuleState());
  228. DECLARE_SC (sc, _T("CAMCViewToolbars::ScValidateButton"));
  229. if ( (lpButtons == NULL) || (nButtons < 1) )
  230. return (sc = E_INVALIDARG);
  231. for (int i=0; i < nButtons; i++)
  232. {
  233. if (lpButtons[i].nBitmap > GetImageCount())
  234. {
  235. sc = E_INVALIDARG;
  236. return sc;
  237. }
  238. // There should be button text if it is not a separator.
  239. if (((lpButtons[i].fsType & TBSTYLE_SEP) == 0) &&
  240. ((lpButtons[i].lpButtonText == NULL) ||
  241. (lpButtons[i].lpTooltipText == NULL)))
  242. {
  243. sc = E_INVALIDARG;
  244. return sc;
  245. }
  246. // There should be no bitmap set if it is a separator.
  247. if ( ((lpButtons[i].fsType & TBSTYLE_SEP) != 0) &&
  248. (lpButtons[i].nBitmap > 0) )
  249. {
  250. sc = E_INVALIDARG;
  251. return sc;
  252. }
  253. // Reset any TBSTATE_WRAP state.
  254. lpButtons[i].fsState &= (~TBSTATE_WRAP);
  255. }
  256. return sc;
  257. }
  258. //+-------------------------------------------------------------------
  259. //
  260. // Member: CAMCViewToolbars::ScInsertButtonToToolbar
  261. //
  262. // Synopsis: Inserts the toolbar button into the main toolbar UI.
  263. //
  264. // Arguments: [pToolButton] - The CMMCToolbarButton object.
  265. //
  266. // Returns: SC
  267. //
  268. //--------------------------------------------------------------------
  269. SC CAMCViewToolbars::ScInsertButtonToToolbar (CMMCToolbarButton* pToolButton)
  270. {
  271. DECLARE_SC(sc, _T("CAMCViewToolbars::ScInsertButtonToToolbar"));
  272. sc = ScCheckPointers(pToolButton);
  273. if (sc)
  274. return sc;
  275. // Button can be added only if view is active, button is not already added
  276. // to the toolbar & toolbar is attached.
  277. if (! m_fViewActive)
  278. return (sc);
  279. if (pToolButton->IsButtonIsAddedToUI())
  280. return sc;
  281. if (! IsToolbarAttached(pToolButton->GetToolbarNotify()))
  282. return sc;
  283. // Now get the main toolbar & add the button.
  284. CMMCToolBar* pToolBarUI = GetMainToolbar();
  285. sc = ScCheckPointers(pToolBarUI, E_UNEXPECTED);
  286. if (sc)
  287. return sc;
  288. TBBUTTON tbButton;
  289. ZeroMemory(&tbButton, sizeof(tbButton));
  290. tbButton.idCommand = pToolButton->GetUniqueCommandID();
  291. tbButton.fsStyle = pToolButton->GetStyle();
  292. tbButton.iBitmap = pToolButton->GetBitmap();
  293. tbButton.fsState = pToolButton->GetState();
  294. // The toolbar is hidden by customize view dialog.
  295. // If so insert the button as hidden. (Do not record
  296. // the hidden status into the CMMCToolbarButton).
  297. if (IsToolbarHidden(pToolButton->GetToolbarNotify()))
  298. tbButton.fsState |= TBSTATE_HIDDEN;
  299. // Insert the button.
  300. BOOL bRet = pToolBarUI->InsertButton(-1, &tbButton);
  301. sc = (bRet ? S_OK : E_FAIL);
  302. if (sc)
  303. return sc;
  304. pToolButton->SetButtonIsAddedToUI(true);
  305. // Bug 225711: If the button is supposed to be hidden, hide it now.
  306. if (tbButton.fsState & TBSTATE_HIDDEN)
  307. sc = pToolBarUI->ScHideButton(tbButton.idCommand, true);
  308. if (sc)
  309. return sc;
  310. return sc;
  311. }
  312. //+-------------------------------------------------------------------
  313. //
  314. // Member: CAMCViewToolbars::ScInsertButtonToDataStr
  315. //
  316. // Synopsis:
  317. //
  318. // Arguments: [pNotifyCallbk] - The callbk interface for IToolbar imp.
  319. // [nIndex] - Index of the button.
  320. // [lpButton] - MMCBUTTON ptr.
  321. // [pToolButton] - Return value, the button added (or found
  322. // in case of dup buttons).
  323. //
  324. // Returns: SC
  325. //
  326. //--------------------------------------------------------------------
  327. SC CAMCViewToolbars::ScInsertButtonToDataStr (CToolbarNotify* pNotifyCallbk,
  328. int nIndex,
  329. LPMMCBUTTON lpButton,
  330. CMMCToolbarButton** ppToolButton)
  331. {
  332. DECLARE_SC(sc, _T("CAMCViewToolbars::ScInsertButtonToDataStr"));
  333. sc = ScCheckPointers(pNotifyCallbk, ppToolButton);
  334. if (sc)
  335. return sc;
  336. sc = ScValidateButton(1, lpButton);
  337. if (sc)
  338. return sc;
  339. // Make sure snapin does not add duplicate buttons
  340. // For compatibility (services snapin) this is not a bug.
  341. *ppToolButton = GetToolbarButton(pNotifyCallbk, lpButton->idCommand);
  342. if (*ppToolButton)
  343. {
  344. // if snapin added the button we already have,
  345. // we still need to ensure its state (BUG: 439229)
  346. if ((*ppToolButton)->GetState() != lpButton->fsState)
  347. {
  348. // update the object
  349. (*ppToolButton)->SetState(lpButton->fsState);
  350. // do we need to update the UI as well?
  351. if (m_fViewActive && (*ppToolButton)->IsButtonIsAddedToUI())
  352. {
  353. INT iCommandID = (*ppToolButton)->GetUniqueCommandID();
  354. if (!m_pMainToolbar->SetState(iCommandID, lpButton->fsState))
  355. return (sc = E_FAIL);
  356. }
  357. }
  358. return sc;
  359. }
  360. // If this button belongs to different toolbar from last button
  361. // then insert a separator in between.
  362. if (! m_vToolbarButtons.empty())
  363. {
  364. CMMCToolbarButton& lastBtn = m_vToolbarButtons.back();
  365. if (lastBtn.GetToolbarNotify() != pNotifyCallbk)
  366. {
  367. CMMCToolbarButton separatorBtn(-1, GetUniqueCommandID(), -1, -1, 0, TBSTYLE_SEP, pNotifyCallbk);
  368. m_vToolbarButtons.push_back(separatorBtn);
  369. }
  370. }
  371. /*
  372. * Assume a snapin adds 3 bitmaps initialy & then 4 for a toolbar.
  373. * Then while adding buttons it will specify bitmap index as 5.
  374. *
  375. * So this toolbar will have two MMCToolbarImages objects in the multimap.
  376. *
  377. * The first MMCToolbarImages has cCount = 3, iStartWRTSnapin = 0, thus
  378. * images from 0 (iStartWRTSnapin) to 3 (iStartWRTSnapin + cCount) with respect
  379. * to snapin.
  380. * The second MMCToolbarImages has cCount = 4, iStartWRTSnapin = 3, thus
  381. * images from 3(iStartWRTSnapin) to 7(iStartWRTSnapin + cCount) wrt snapin.
  382. *
  383. * The iStartWRTSnapin member is nothing but the largest of iStartWRTSnapin + cCount
  384. * in all of this toolbars MMCToolbarImages.
  385. *
  386. * Below we run thro different MMCToolbarImages for this toolbar and see in which
  387. * one the given index falls under and calculate the real index by adding that
  388. * object's iStart.
  389. *
  390. */
  391. // Now we need to compute the bitmap index. Find this toolbar in the multimap.
  392. int iBitmap = -1;
  393. std::pair<TBarToBitmapIndex::iterator, TBarToBitmapIndex::iterator>
  394. range = m_mapTBarToBitmapIndex.equal_range(pNotifyCallbk);
  395. while (range.first != range.second)
  396. {
  397. MMCToolbarImages images = (range.first)->second;
  398. // We need to find the bitmap whose start index is greater than or
  399. // equal to given index and upper index is less than given index.
  400. int nLastImageIndex = images.iStartWRTSnapin + images.cCount -1;
  401. if ( (lpButton->nBitmap >= images.iStartWRTSnapin ) &&
  402. ( lpButton->nBitmap <= nLastImageIndex ) )
  403. {
  404. iBitmap = images.iStart + lpButton->nBitmap;
  405. break;
  406. }
  407. (range.first)++;
  408. }
  409. // No bitmaps for separators.
  410. if ( (-1 == iBitmap) && (!(TBSTYLE_SEP & lpButton->fsType)) )
  411. return (sc = E_UNEXPECTED);
  412. // Create CMMCToolbarButton for each button, init it with unique command-id, toolbar id.
  413. // There is only one imagelist per view that contains bitmaps from different toolbars.
  414. // We use a multimap to identify a particular toolbar's bitmap start indices.
  415. CMMCToolbarButton newButton(lpButton->idCommand,
  416. GetUniqueCommandID(),
  417. nIndex,
  418. (lpButton->fsType & TBSTYLE_SEP) ? 0 : iBitmap,
  419. lpButton->fsState,
  420. lpButton->fsType,
  421. pNotifyCallbk);
  422. USES_CONVERSION;
  423. // First save the button data in CMMCToolButton.
  424. if (lpButton->lpTooltipText)
  425. newButton.SetTooltip(OLE2CT(lpButton->lpTooltipText));
  426. if (lpButton->lpButtonText)
  427. newButton.SetButtonText(OLE2CT(lpButton->lpButtonText));
  428. // Add this button to the end of our array.
  429. ToolbarButtons::iterator itBtn = m_vToolbarButtons.insert(m_vToolbarButtons.end(), newButton);
  430. if (m_vToolbarButtons.end() == itBtn)
  431. return (sc = E_FAIL);
  432. *ppToolButton = itBtn;
  433. sc = ScCheckPointers(*ppToolButton, E_OUTOFMEMORY);
  434. if (sc)
  435. return sc;
  436. return (sc);
  437. }
  438. //+-------------------------------------------------------------------
  439. //
  440. // Member: CAMCViewToolbars::ScInsertButton
  441. //
  442. // Synopsis: Insert a button in our array & if the our view is active
  443. // add the button to the UI.
  444. //
  445. // Arguments: [pNotifyCallbk] - The callbk interface for IToolbar imp.
  446. // [nIndex] - Index of the button.
  447. // [lpButton] - MMCBUTTON ptr.
  448. //
  449. // Returns: SC
  450. //
  451. //--------------------------------------------------------------------
  452. SC CAMCViewToolbars::ScInsertButton (CToolbarNotify* pNotifyCallbk, int nIndex, LPMMCBUTTON lpButton)
  453. {
  454. AFX_MANAGE_STATE (AfxGetAppModuleState());
  455. DECLARE_SC(sc, _T("CAMCViewToolbars::ScInsertButton"));
  456. CMMCToolbarButton *pToolbarButton = NULL;
  457. sc = ScInsertButtonToDataStr(pNotifyCallbk, nIndex, lpButton, &pToolbarButton);
  458. if (sc)
  459. return sc;
  460. sc = ScInsertButtonToToolbar(pToolbarButton);
  461. if (sc)
  462. return sc;
  463. return (sc);
  464. }
  465. //+-------------------------------------------------------------------
  466. //
  467. // Member: CAMCViewToolbars::ScAddButtons
  468. //
  469. // Synopsis: Save the buttons in our array and add them to UI if view is active.
  470. //
  471. // Arguments: [pNotifyCallbk] - Button click callback interface.
  472. // [nButtons] - Number of buttons in lpButtons array.
  473. // [lpButtons] - MMCBUTTONs (array) bo be added.
  474. //
  475. // Returns: SC
  476. //
  477. //--------------------------------------------------------------------
  478. SC CAMCViewToolbars::ScAddButtons (CToolbarNotify* pNotifyCallbk, int nButtons, LPMMCBUTTON lpButtons)
  479. {
  480. DECLARE_SC(sc, _T("CAMCViewToolbars::ScAddButtons"));
  481. for (int i = 0; i < nButtons; i++)
  482. {
  483. sc = ScInsertButton(pNotifyCallbk, -1, &(lpButtons[i]));
  484. if (sc)
  485. return sc;
  486. }
  487. return (sc);
  488. }
  489. //+-------------------------------------------------------------------
  490. //
  491. // Member: CAMCViewToolbars::ScDeleteButtonFromToolbar
  492. //
  493. // Synopsis: Deletes a button from the toolbar UI if it exists.
  494. //
  495. // Arguments: [pToolButton] - The CMMCToolbarButton object.
  496. //
  497. // Returns: SC
  498. //
  499. //--------------------------------------------------------------------
  500. SC CAMCViewToolbars::ScDeleteButtonFromToolbar (CMMCToolbarButton* pToolButton)
  501. {
  502. DECLARE_SC(sc, _T("CAMCViewToolbars::ScDeleteButtonFromToolbar"));
  503. sc = ScCheckPointers(pToolButton);
  504. if (sc)
  505. return sc;
  506. if (! m_fViewActive)
  507. return (sc);
  508. if (! pToolButton->IsButtonIsAddedToUI())
  509. return sc;
  510. CMMCToolBar* pToolBarUI = GetMainToolbar();
  511. sc = ScCheckPointers(pToolBarUI, E_UNEXPECTED);
  512. if (sc)
  513. return sc;
  514. int nIndexOfBtn = pToolBarUI->CommandToIndex(pToolButton->GetUniqueCommandID());
  515. // Update the separators before deleting the button.
  516. pToolBarUI->UpdateSeparators(pToolButton->GetUniqueCommandID(), true);
  517. // Delete the button.
  518. BOOL bRet = pToolBarUI->DeleteButton(nIndexOfBtn);
  519. sc = (bRet ? S_OK : E_FAIL);
  520. if (sc)
  521. return sc;
  522. pToolButton->SetButtonIsAddedToUI(false);
  523. return (sc);
  524. }
  525. //+-------------------------------------------------------------------
  526. //
  527. // Member: CAMCViewToolbars::ScDeleteButton
  528. //
  529. // Synopsis: Delete button at given index (index is wrt snapin).
  530. //
  531. // Arguments: [pNotifyCallbk]
  532. // [nIndex[
  533. //
  534. // Returns: SC
  535. //
  536. //--------------------------------------------------------------------
  537. SC CAMCViewToolbars::ScDeleteButton (CToolbarNotify* pNotifyCallbk, int nIndex)
  538. {
  539. AFX_MANAGE_STATE (AfxGetAppModuleState());
  540. DECLARE_SC(sc, _T("CAMCViewToolbars::ScDeleteButton"));
  541. sc = ScCheckPointers(pNotifyCallbk);
  542. if (sc)
  543. return sc;
  544. // Now iterate thro all toolbuttons & find the one with
  545. // given toolbar-id & index and if it is added to the
  546. // toolbar UI then delete it.
  547. ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
  548. for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
  549. {
  550. CMMCToolbarButton *pToolButton = itBtn;
  551. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  552. if (sc)
  553. return sc;
  554. if ( (pToolButton->GetToolbarNotify() == pNotifyCallbk) &&
  555. (pToolButton->GetIndexFromSnapin() == nIndex) )
  556. {
  557. sc = ScDeleteButtonFromToolbar(pToolButton);
  558. if (sc)
  559. return sc;
  560. return sc;
  561. }
  562. }
  563. // To be compatible with services snapin on Windows2000 return S_OK.
  564. sc = S_OK;
  565. TraceSnapinError(_T("IToolbar::DeleteButton, Snapin called IToolbar::DeleteButton, but the toolbar button is not found. Most likely the button index is wrong (snapin should have called InsertButton with that index)"), sc);
  566. return (sc);
  567. }
  568. //+-------------------------------------------------------------------
  569. //
  570. // Member: CAMCViewToolbars::ScAttach
  571. //
  572. // Synopsis: Make the toolbars visible (Add the toolbar buttons
  573. // to the toolbar UI). First get the CMMCToolbarData
  574. // and set attached flag. Then add the buttons to toolbar.
  575. //
  576. // Arguments: [pNotifyCallbk] - The toolbar identifier (corresponds
  577. // to the IToolbar imp).
  578. //
  579. // Returns: SC
  580. //
  581. //--------------------------------------------------------------------
  582. SC CAMCViewToolbars::ScAttach (CToolbarNotify* pNotifyCallbk)
  583. {
  584. DECLARE_SC(sc, _T("CAMCViewToolbars::ScAttach"));
  585. sc = ScCheckPointers(pNotifyCallbk);
  586. if (sc)
  587. return sc;
  588. SetToolbarAttached(pNotifyCallbk, true);
  589. // Go thro all ToolButtons of this toolbar and add those
  590. // buttons that are not yet added to the toolbar UI.
  591. ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
  592. for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
  593. {
  594. CMMCToolbarButton *pToolButton = itBtn;
  595. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  596. if (sc)
  597. return sc;
  598. if (pToolButton->GetToolbarNotify() == pNotifyCallbk)
  599. {
  600. // Add this button to toolbar UI.
  601. sc = ScInsertButtonToToolbar(pToolButton);
  602. if (sc)
  603. return sc;
  604. }
  605. }
  606. return (sc);
  607. }
  608. //+-------------------------------------------------------------------
  609. //
  610. // Member: CAMCViewToolbars::ScDetach
  611. //
  612. // Synopsis: Remove the toolbar buttons from the toolbar UI for
  613. // given toolbar.
  614. //
  615. // Arguments: [pNotifyCallbk] - The given (IToolbar) toolbar.
  616. //
  617. // Returns: SC
  618. //
  619. //--------------------------------------------------------------------
  620. SC CAMCViewToolbars::ScDetach (CToolbarNotify* pNotifyCallbk)
  621. {
  622. DECLARE_SC(sc, _T("CAMCViewToolbars::ScDetach"));
  623. sc = ScCheckPointers(pNotifyCallbk);
  624. if (sc)
  625. return sc;
  626. SetToolbarAttached(pNotifyCallbk, false);
  627. // Go thro all ToolButtons of this toolbar and delete those
  628. // buttons that are added to the toolbar UI.
  629. ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
  630. for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
  631. {
  632. CMMCToolbarButton *pToolButton = itBtn;
  633. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  634. if (sc)
  635. return sc;
  636. if (pToolButton->GetToolbarNotify() == pNotifyCallbk)
  637. {
  638. // Delete this button from the toolbar UI.
  639. sc = ScDeleteButtonFromToolbar(pToolButton);
  640. if (sc)
  641. return sc;
  642. }
  643. }
  644. return (sc);
  645. }
  646. //+-------------------------------------------------------------------
  647. //
  648. // Member: CAMCViewToolbars::ScGetButtonStateInToolbar
  649. //
  650. // Synopsis: Get the state of given button from toolbar UI.
  651. //
  652. // Arguments: [pToolButton] - The CMMCToolbarButton object.
  653. // [byState] - The TBSTATE needed.
  654. // [pbState] - The button state.
  655. //
  656. // Returns: SC
  657. //
  658. //--------------------------------------------------------------------
  659. SC CAMCViewToolbars::ScGetButtonStateInToolbar(CMMCToolbarButton *pToolButton,
  660. BYTE byState,
  661. BOOL* pbState)
  662. {
  663. DECLARE_SC(sc, _T("CAMCViewToolbars::ScGetButtonStateInToolbar"));
  664. sc = ScCheckPointers(pToolButton);
  665. if (sc)
  666. return sc;
  667. ASSERT(NULL != m_pMainToolbar);
  668. int idCommand = pToolButton->GetUniqueCommandID();
  669. // Make sure button with this command-id exists.
  670. if (m_pMainToolbar->GetState(idCommand) == -1)
  671. return (sc = E_INVALIDARG);
  672. switch (byState)
  673. {
  674. case TBSTATE_ENABLED:
  675. *pbState = m_pMainToolbar->IsButtonEnabled(idCommand);
  676. break;
  677. case TBSTATE_CHECKED:
  678. *pbState = m_pMainToolbar->IsButtonChecked(idCommand);
  679. break;
  680. case TBSTATE_HIDDEN:
  681. *pbState = m_pMainToolbar->IsButtonHidden(idCommand);
  682. break;
  683. case TBSTATE_INDETERMINATE:
  684. *pbState = m_pMainToolbar->IsButtonIndeterminate(idCommand);
  685. break;
  686. case TBSTATE_PRESSED:
  687. *pbState = m_pMainToolbar->IsButtonPressed(idCommand);
  688. break;
  689. default:
  690. sc = E_NOTIMPL;
  691. ASSERT(FALSE); // Invalid option
  692. }
  693. return sc;
  694. }
  695. //+-------------------------------------------------------------------
  696. //
  697. // Member: CAMCViewToolbars::ScGetButtonState
  698. //
  699. // Synopsis: Get the state of the given button.
  700. //
  701. // Arguments: [pNotifyCallbk] - The toolbar (IToolbar).
  702. // [idCommand] - Snapin given command-id of button.
  703. // [byState] - The state needed.
  704. // [pbState] - bool ret val.
  705. //
  706. // Returns: SC
  707. //
  708. //--------------------------------------------------------------------
  709. SC CAMCViewToolbars::ScGetButtonState (CToolbarNotify* pNotifyCallbk,
  710. int idCommandFromSnapin, BYTE byState,
  711. BOOL* pbState)
  712. {
  713. AFX_MANAGE_STATE (AfxGetAppModuleState());
  714. DECLARE_SC(sc, _T("CAMCViewToolbars::ScGetButtonState"));
  715. sc = ScCheckPointers(pNotifyCallbk, pbState);
  716. if (sc)
  717. return sc;
  718. // Get the toolbutton of given toolbar id & command-id.
  719. CMMCToolbarButton *pToolButton = GetToolbarButton(pNotifyCallbk, idCommandFromSnapin);
  720. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  721. if (sc)
  722. return sc;
  723. // The toolbutton is not available if view is not active or toolbar is hidden by
  724. // customize view dialog, then return the state from our data-structure.
  725. if (m_fViewActive && pToolButton->IsButtonIsAddedToUI() && (!IsToolbarHidden(pNotifyCallbk)) )
  726. sc = ScGetButtonStateInToolbar(pToolButton, byState, pbState);
  727. else
  728. // We cant access the toolbar UI. Return the state we saved.
  729. *pbState = (pToolButton->GetState() & byState);
  730. if (sc)
  731. return sc;
  732. return (sc);
  733. }
  734. //+-------------------------------------------------------------------
  735. //
  736. // Member: CAMCViewToolbars::ScSetButtonStateInToolbar
  737. //
  738. // Synopsis: Set the state of a button in main toolbar UI.
  739. //
  740. // Arguments: [pToolButton] - The CMMCToolbarButton object.
  741. // [byState] - The button state to be set.
  742. // [bState] - Set or Reset the state.
  743. //
  744. // Returns: SC
  745. //
  746. //--------------------------------------------------------------------
  747. SC CAMCViewToolbars::ScSetButtonStateInToolbar (CMMCToolbarButton* pToolButton,
  748. BYTE byState,
  749. BOOL bState)
  750. {
  751. DECLARE_SC(sc, _T("CAMCViewToolbars::ScSetButtonStateInToolbar"));
  752. sc = ScCheckPointers(pToolButton);
  753. if (sc)
  754. return sc;
  755. if(! m_fViewActive)
  756. return sc;
  757. if (! pToolButton->IsButtonIsAddedToUI())
  758. return sc;
  759. ASSERT(NULL != m_pMainToolbar);
  760. int idCommand = pToolButton->GetUniqueCommandID();
  761. BOOL bRet = FALSE;
  762. switch (byState)
  763. {
  764. case TBSTATE_ENABLED:
  765. bRet = m_pMainToolbar->EnableButton(idCommand, bState);
  766. break;
  767. case TBSTATE_CHECKED:
  768. bRet = m_pMainToolbar->CheckButton(idCommand, bState);
  769. break;
  770. case TBSTATE_HIDDEN:
  771. {
  772. int nButtonIndex = m_pMainToolbar->CommandToIndex(idCommand);
  773. // ignore unknown buttons
  774. if (nButtonIndex == -1)
  775. break;
  776. // ignore ineffectual changes (negate both sides to insure pure bool)
  777. if (!m_pMainToolbar->IsButtonHidden(idCommand) == !bState)
  778. {
  779. bRet = TRUE;
  780. break;
  781. }
  782. sc = m_pMainToolbar->ScHideButton(idCommand, bState);
  783. return sc;
  784. break;
  785. }
  786. case TBSTATE_INDETERMINATE:
  787. bRet = m_pMainToolbar->Indeterminate(idCommand, bState);
  788. break;
  789. case TBSTATE_PRESSED:
  790. bRet = m_pMainToolbar->PressButton(idCommand, bState);
  791. break;
  792. default:
  793. sc = E_NOTIMPL;
  794. ASSERT(FALSE); // Invalid option
  795. return sc;
  796. }
  797. sc = (bRet ? S_OK : E_FAIL);
  798. return (sc);
  799. }
  800. //+-------------------------------------------------------------------
  801. //
  802. // Member: CAMCViewToolbars::ScSetButtonState
  803. //
  804. // Synopsis: Set the state of a button.
  805. //
  806. // Arguments: [pNotifyCallbk] - The toolbar (IToolbar).
  807. // [byState] - The button state to be set.
  808. // [bState] - Set or Reset the state.
  809. //
  810. // Returns: SC
  811. //
  812. //--------------------------------------------------------------------
  813. SC CAMCViewToolbars::ScSetButtonState (CToolbarNotify* pNotifyCallbk,
  814. int idCommandFromSnapin,
  815. BYTE byState, BOOL bSetState)
  816. {
  817. AFX_MANAGE_STATE (AfxGetAppModuleState());
  818. DECLARE_SC(sc, _T("CAMCViewToolbars::ScSetButtonState"));
  819. sc = ScCheckPointers(pNotifyCallbk);
  820. if (sc)
  821. return sc;
  822. // Reset any TBSTATE_WRAP state.
  823. byState &= (~TBSTATE_WRAP);
  824. // Get the toolbutton of given toolbar id & command-id.
  825. CMMCToolbarButton *pToolButton = GetToolbarButton(pNotifyCallbk, idCommandFromSnapin);
  826. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  827. if (sc)
  828. return (sc = S_OK); // Not an error.
  829. BYTE byNewState = (bSetState) ? (pToolButton->GetState() | byState) :
  830. (pToolButton->GetState() & (~byState) );
  831. pToolButton->SetState(byNewState);
  832. // The toolbar can be hidden by customize view dialog.
  833. // If the snapin tries to unhide a button in hidden toolbar just return.
  834. if ( (byState & TBSTATE_HIDDEN) && (!bSetState) && IsToolbarHidden(pNotifyCallbk) )
  835. return (sc = S_OK);
  836. sc = ScSetButtonStateInToolbar(pToolButton, byState, bSetState);
  837. if (sc)
  838. return sc;
  839. return (sc);
  840. }
  841. //+-------------------------------------------------------------------
  842. //
  843. // Member: CAMCViewToolbars::ScOnActivateView
  844. //
  845. // Synopsis: The view of this object is active, add its toolbuttons.
  846. //
  847. // Arguments: [pAMCView] - The AMCView ptr.
  848. // [bFirstActiveView] - Is this first active view.
  849. //
  850. // Returns: SC
  851. //
  852. //--------------------------------------------------------------------
  853. SC CAMCViewToolbars::ScOnActivateView (CAMCView *pAMCView, // We dont care about this arg.
  854. bool bFirstActiveView)
  855. {
  856. DECLARE_SC(sc, _T("CAMCViewToolbars::ScOnActivateView"));
  857. // If this is the first active view then insert the toolbar band.
  858. CMMCToolBar* pMainToolbar = GetMainToolbar();
  859. sc = ScCheckPointers(pMainToolbar, E_UNEXPECTED);
  860. if (sc)
  861. return sc;
  862. sc = ScFireEvent(CAMCViewToolbarsObserver::ScOnActivateAMCViewToolbars, this);
  863. if (sc)
  864. sc.TraceAndClear();
  865. m_fViewActive = true;
  866. pMainToolbar->SetImageList(GetImageList());
  867. // Go thro all ToolButtons of this toolbar and add them to the UI.
  868. ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
  869. for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
  870. {
  871. CMMCToolbarButton *pToolButton = itBtn;
  872. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  873. if (sc)
  874. return sc;
  875. // Add this button to toolbar UI.
  876. sc = ScInsertButtonToToolbar(pToolButton);
  877. if (sc)
  878. return sc;
  879. }
  880. bool bToolbarBandVisible = pMainToolbar->IsBandVisible();
  881. bool bThereAreVisibleButtons = IsThereAVisibleButton();
  882. // If there are visible buttons show the band.
  883. if (bThereAreVisibleButtons)
  884. pMainToolbar->Show(true, true);
  885. else if (bToolbarBandVisible) // Otherwise hide it if it is currently visible.
  886. pMainToolbar->Show(false);
  887. return (sc);
  888. }
  889. //+-------------------------------------------------------------------
  890. //
  891. // Member: CAMCViewToolbars::ScOnDeactivateView
  892. //
  893. // Synopsis: The view of this object is de-activated. Disable the
  894. // imagelists & this object should not manipulate the
  895. // toolbar UI till OnActivateView is fired.
  896. //
  897. // Arguments: [pAMCView] - The view to be de-activated.
  898. // [bLastActiveView] - Is this the last view.
  899. //
  900. // Returns: SC
  901. //
  902. //--------------------------------------------------------------------
  903. SC CAMCViewToolbars::ScOnDeactivateView (CAMCView *pAMCView, bool bLastActiveView)
  904. {
  905. DECLARE_SC(sc, _T("CAMCViewToolbars::ScOnDeactivateView"));
  906. CMMCToolBar* pMainToolbar = GetMainToolbar();
  907. sc = ScCheckPointers(pMainToolbar, E_UNEXPECTED);
  908. if (sc)
  909. return sc;
  910. ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
  911. for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
  912. {
  913. CMMCToolbarButton *pToolButton = itBtn;
  914. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  915. if (sc)
  916. return sc;
  917. sc = ScDeleteButtonFromToolbar(pToolButton);
  918. if (sc)
  919. return sc;
  920. }
  921. sc = ScFireEvent(CAMCViewToolbarsObserver::ScOnDeactivateAMCViewToolbars);
  922. if (sc)
  923. sc.TraceAndClear();
  924. // If this is last view then delete the band if it is visible.
  925. if (bLastActiveView && pMainToolbar->IsBandVisible())
  926. pMainToolbar->Show(FALSE);
  927. m_bLastActiveView = bLastActiveView;
  928. m_fViewActive = false;
  929. return (sc);
  930. }
  931. //+-------------------------------------------------------------------
  932. //
  933. // Member: CAMCViewToolbars::ScButtonClickedNotify
  934. //
  935. // Synopsis: A button of this object is clicked. Get the context
  936. // and inform the CToolbarNotify object.
  937. //
  938. // Arguments: [nID] - command id of the button clicked.
  939. //
  940. // Returns: SC
  941. //
  942. //--------------------------------------------------------------------
  943. SC CAMCViewToolbars::ScButtonClickedNotify (UINT nID)
  944. {
  945. DECLARE_SC(sc, _T("CAMCViewToolbars::ScButtonClickedNotify"));
  946. CMMCToolbarButton* pButton = GetToolbarButton(nID);
  947. sc = ScCheckPointers(pButton, m_pAMCViewOwner, E_UNEXPECTED);
  948. if (sc)
  949. return sc;
  950. // Get the context, (the currently selected HNODE,
  951. // lParam (if result item)) etc...
  952. HNODE hNode;
  953. bool bScope;
  954. LPARAM lParam;
  955. sc = m_pAMCViewOwner->ScGetFocusedItem (hNode, lParam, bScope);
  956. if (sc)
  957. return sc;
  958. CToolbarNotify* pNotifyCallbk = pButton->GetToolbarNotify();
  959. sc = ScCheckPointers(pNotifyCallbk, E_UNEXPECTED);
  960. if (sc)
  961. return sc;
  962. // Deactivate if theming (fusion or V6 common-control) context before calling snapins.
  963. ULONG_PTR ulpCookie;
  964. if (! MmcDownlevelActivateActCtx(NULL, &ulpCookie))
  965. return E_FAIL;
  966. try
  967. {
  968. sc = pNotifyCallbk->ScNotifyToolBarClick(hNode, bScope, lParam, pButton->GetCommandIDFromSnapin());
  969. }
  970. catch(...)
  971. {
  972. sc = E_FAIL;
  973. }
  974. MmcDownlevelDeactivateActCtx(0, ulpCookie);
  975. if (sc)
  976. return sc;
  977. // fire event informing about execution
  978. sc = ScFireEvent(CAMCViewToolbarsObserver::ScOnToolbarButtonClicked);
  979. if (sc)
  980. return sc;
  981. return (sc);
  982. }
  983. //+-------------------------------------------------------------------
  984. //
  985. // Member: CAMCViewToolbars::ScGetToolTip
  986. //
  987. // Synopsis: Tooltip is requested for a button of this object.
  988. //
  989. // Arguments: [nCommandID] - Command id of the button.
  990. // [strTipText] - CString to hold the tooltip.
  991. //
  992. // Returns: SC
  993. //
  994. //--------------------------------------------------------------------
  995. SC CAMCViewToolbars::ScGetToolTip (int nCommandID, CString& strTipText)
  996. {
  997. AFX_MANAGE_STATE (AfxGetAppModuleState());
  998. DECLARE_SC(sc, _T("CAMCViewToolbars::ScGetToolTip"));
  999. // Get the toolbutton.
  1000. CMMCToolbarButton* pButton = GetToolbarButton(nCommandID);
  1001. sc = ScCheckPointers(pButton, E_UNEXPECTED);
  1002. if (sc)
  1003. return sc;
  1004. strTipText = pButton->GetTooltip();
  1005. return (sc);
  1006. }
  1007. //+-------------------------------------------------------------------
  1008. //
  1009. // Member: CAMCViewToolbars::ScDelete
  1010. //
  1011. // Synopsis: A toolbar needs to be deleted. First remove the buttons
  1012. // from UI & remove buttons from our data structure,
  1013. // remove the toolbar reference from our data structures.
  1014. //
  1015. // Arguments: [pNotifyCallbk] - The toolbar (IToolbar).
  1016. //
  1017. // Returns: SC
  1018. //
  1019. // Note: This method should remove its reference of CToolbarNotify
  1020. // object when it returns (even if it encounters intermediate errors).
  1021. //
  1022. //--------------------------------------------------------------------
  1023. SC CAMCViewToolbars::ScDelete (CToolbarNotify* pNotifyCallbk)
  1024. {
  1025. AFX_MANAGE_STATE (AfxGetAppModuleState());
  1026. DECLARE_SC(sc, _T("CAMCViewToolbars::ScDelete"));
  1027. sc = ScCheckPointers(pNotifyCallbk);
  1028. if (sc)
  1029. return sc;
  1030. ToolbarButtons::iterator itBtn;
  1031. // Detach the toolbar first.
  1032. sc = ScDetach(pNotifyCallbk);
  1033. if (sc)
  1034. goto Cleanup;
  1035. // Delete the buttons from m_vToolbarButtons.
  1036. itBtn = m_vToolbarButtons.begin();
  1037. while (itBtn != m_vToolbarButtons.end())
  1038. {
  1039. CMMCToolbarButton* pToolButton = itBtn;
  1040. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  1041. if (sc)
  1042. goto Cleanup;
  1043. if (pToolButton->GetToolbarNotify() == pNotifyCallbk)
  1044. {
  1045. sc = ScDeleteButtonFromToolbar(pToolButton);
  1046. if (sc)
  1047. goto Cleanup;
  1048. itBtn = m_vToolbarButtons.erase(itBtn);
  1049. }
  1050. else
  1051. ++itBtn;
  1052. }
  1053. Cleanup:
  1054. // The toolbar client has asked us to remove our reference
  1055. // to it. So even if there is any error encountered we
  1056. // should remove the reference.
  1057. m_mapTBarToBitmapIndex.erase(pNotifyCallbk);
  1058. return (sc);
  1059. }
  1060. //+-------------------------------------------------------------------
  1061. //
  1062. // Member: CAMCViewToolbars::ScShow
  1063. //
  1064. // Synopsis: Show/Hide buttons of a toolbar.
  1065. //
  1066. // Arguments: [pNotifyCallbk] - Identifies the toolbar
  1067. // [bShow] - Show/Hide.
  1068. //
  1069. // Returns: SC
  1070. //
  1071. //--------------------------------------------------------------------
  1072. SC CAMCViewToolbars::ScShow (CToolbarNotify* pNotifyCallbk, BOOL bShow)
  1073. {
  1074. DECLARE_SC(sc, _T("CAMCViewToolbars::ScShow"));
  1075. if (m_bLastActiveView)
  1076. return sc;
  1077. sc = ScCheckPointers(pNotifyCallbk);
  1078. if (sc)
  1079. return sc;
  1080. sc = ScCheckPointers(m_pMainToolbar, E_UNEXPECTED);
  1081. if (sc)
  1082. return sc;
  1083. // Go thro all ToolButtons of this toolbar and hide or show them.
  1084. ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
  1085. for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
  1086. {
  1087. CMMCToolbarButton *pToolButton = itBtn;
  1088. sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
  1089. if (sc)
  1090. return sc;
  1091. if ( (pToolButton->GetToolbarNotify() == pNotifyCallbk) &&
  1092. (pToolButton->IsButtonIsAddedToUI()) )
  1093. {
  1094. // Do not show the buttons which should be hidden (TBSTATE_HIDDEN).
  1095. BOOL bHide = (bShow == FALSE) || (pToolButton->GetState() & TBSTATE_HIDDEN);
  1096. sc = m_pMainToolbar->ScHideButton(pToolButton->GetUniqueCommandID(), bHide);
  1097. if (sc)
  1098. return sc;
  1099. }
  1100. }
  1101. // The toolbar is hidden/shown by customize view dialog.
  1102. SetToolbarStatusHidden(pNotifyCallbk, (FALSE == bShow) );
  1103. if (bShow)
  1104. m_pMainToolbar->Show(TRUE, true /* insert band in new line*/ );
  1105. else if ( (false == IsThereAVisibleButton()) && // If there is no visible
  1106. (m_pMainToolbar->IsBandVisible()) ) // buttons hide the band.
  1107. m_pMainToolbar->Show(FALSE);
  1108. return (sc);
  1109. }
  1110. //+-------------------------------------------------------------------
  1111. //
  1112. // Member: CAMCViewToolbars::IsThereAVisibleButton
  1113. //
  1114. // Synopsis: Returns true if there is any visible button. If not
  1115. // the band should be hidden (or removed).
  1116. //
  1117. // Returns: bool
  1118. //
  1119. //--------------------------------------------------------------------
  1120. bool CAMCViewToolbars::IsThereAVisibleButton()
  1121. {
  1122. if (! m_pMainToolbar)
  1123. return false;
  1124. int cButtons = m_pMainToolbar->GetButtonCount();
  1125. for (int i = 0; i < cButtons; ++i)
  1126. {
  1127. TBBUTTON tbButton;
  1128. if (m_pMainToolbar->GetButton(i, &tbButton))
  1129. {
  1130. // If the button is not hidden return true to
  1131. // IsThereAVisibleButton question.
  1132. if ( !(tbButton.fsState & TBSTATE_HIDDEN) )
  1133. return true;
  1134. }
  1135. }
  1136. return false;
  1137. }
  1138. //+-------------------------------------------------------------------
  1139. //
  1140. // Member: CAMCViewToolbars::GetToolbarButton
  1141. //
  1142. // Synopsis: Given the command ID return the button object.
  1143. //
  1144. // Arguments: [nCommandID] -
  1145. //
  1146. // Returns: CMMCToolbarButton obj.
  1147. //
  1148. //--------------------------------------------------------------------
  1149. CMMCToolbarButton* CAMCViewToolbars::GetToolbarButton(int nUniqueCommandID)
  1150. {
  1151. ToolbarButtons::iterator itBtns = m_vToolbarButtons.begin();
  1152. for (; itBtns != m_vToolbarButtons.end(); ++itBtns)
  1153. {
  1154. if ((itBtns)->GetUniqueCommandID() == nUniqueCommandID)
  1155. return (itBtns);
  1156. }
  1157. return NULL;
  1158. }
  1159. //+-------------------------------------------------------------------
  1160. //
  1161. // Member: CAMCViewToolbars::GetToolbarButton
  1162. //
  1163. // Synopsis: Search for the button with given toolbar id & command id.
  1164. //
  1165. // Arguments: [idToolbar] -
  1166. // [idCommand] - Command id given by snapin (therfore may not be unique).
  1167. //
  1168. // Returns: the toolbutton object.
  1169. //
  1170. //--------------------------------------------------------------------
  1171. CMMCToolbarButton* CAMCViewToolbars::GetToolbarButton(CToolbarNotify* pNotifyCallbk, int idCommandIDFromSnapin)
  1172. {
  1173. ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
  1174. for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
  1175. {
  1176. CMMCToolbarButton* pToolButton = (itBtn);
  1177. if ( (pToolButton->GetToolbarNotify() == pNotifyCallbk) &&
  1178. (pToolButton->GetCommandIDFromSnapin() == idCommandIDFromSnapin) )
  1179. {
  1180. return (pToolButton);
  1181. }
  1182. }
  1183. return NULL;
  1184. }
  1185. const int CMMCToolBar::s_nUpdateToolbarSizeMsg =
  1186. RegisterWindowMessage (_T("CMMCToolBar::WM_UpdateToolbarSize"));
  1187. // Command Ids for buttons must start from 1, since 0 is special case by MFC (BUG:451883)
  1188. // For tooltips the child ids of the control is used. This range is 0x0 to 0xFFFF.
  1189. BEGIN_MESSAGE_MAP(CMMCToolBar, CMMCToolBarCtrlEx)
  1190. ON_COMMAND_RANGE(MMC_TOOLBUTTON_ID_FIRST, MMC_TOOLBUTTON_ID_LAST, OnButtonClicked)
  1191. ON_UPDATE_COMMAND_UI_RANGE(MMC_TOOLBUTTON_ID_FIRST, MMC_TOOLBUTTON_ID_LAST, OnUpdateAllCmdUI)
  1192. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0x0000, 0xFFFF, OnToolTipText)
  1193. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0x0000, 0xFFFF, OnToolTipText)
  1194. ON_REGISTERED_MESSAGE(s_nUpdateToolbarSizeMsg, OnUpdateToolbarSize)
  1195. END_MESSAGE_MAP()
  1196. //+-------------------------------------------------------------------
  1197. //
  1198. // Member: ScInit
  1199. //
  1200. // Synopsis: Initialize this toolbar by creating the UI object.
  1201. //
  1202. // Arguments: [pRebar] - The parent rebar where this toolbar should be added.
  1203. //
  1204. // Returns: SC
  1205. //
  1206. //--------------------------------------------------------------------
  1207. SC CMMCToolBar::ScInit(CRebarDockWindow* pRebar)
  1208. {
  1209. AFX_MANAGE_STATE (AfxGetAppModuleState());
  1210. DECLARE_SC (sc, _T("CMMCToolBar::ScInit"));
  1211. sc = ScCheckPointers(pRebar);
  1212. if (sc)
  1213. return sc;
  1214. // Enable tool-tips for the tool-buttons.
  1215. BOOL bRet = Create (NULL, WS_VISIBLE | TBSTYLE_TOOLTIPS, g_rectEmpty, pRebar, ID_TOOLBAR);
  1216. sc = (bRet ? S_OK : E_FAIL);
  1217. if (sc)
  1218. return sc;
  1219. // Set ComCtrl version as 5 to use multiple imagelists.
  1220. LRESULT lOldVer = SendMessage(CCM_SETVERSION, (WPARAM) 5, 0);
  1221. if (lOldVer == -1)
  1222. return (sc = E_FAIL);
  1223. return sc;
  1224. }
  1225. //+-------------------------------------------------------------------
  1226. //
  1227. // Member: OnButtonClicked
  1228. //
  1229. // Synopsis: A button of this toolbar is clicked, tell the
  1230. // toolbars manager to notify the client
  1231. // (std toolbar or snapin) about this.
  1232. //
  1233. // Arguments: [nID] - The ID of the button clicked.
  1234. //
  1235. // Returns: None.
  1236. //
  1237. //--------------------------------------------------------------------
  1238. void CMMCToolBar::OnButtonClicked(UINT nID)
  1239. {
  1240. DECLARE_SC(sc, _T("CMMCToolBar::OnButtonClicked"));
  1241. sc = ScCheckPointers(m_pActiveAMCViewToolbars, E_UNEXPECTED);
  1242. if (sc)
  1243. return;
  1244. // Inform the active view toolbar object about button click.
  1245. sc = m_pActiveAMCViewToolbars->ScButtonClickedNotify(nID);
  1246. if (sc)
  1247. return;
  1248. return;
  1249. }
  1250. //+-------------------------------------------------------------------
  1251. //
  1252. // Member: OnToolTipText
  1253. //
  1254. // Synopsis: Tool-tips are requested for a button. (message handler).
  1255. //
  1256. // Arguments:
  1257. // [nCID] - Not used.
  1258. // [pNMHDR] - Tool-tips for what?
  1259. // [pResult] - tool-tip text.
  1260. //
  1261. // Returns: BOOL.
  1262. //
  1263. //--------------------------------------------------------------------
  1264. BOOL CMMCToolBar::OnToolTipText(UINT nCID, NMHDR* pNMHDR, LRESULT* pResult)
  1265. {
  1266. AFX_MANAGE_STATE (AfxGetAppModuleState());
  1267. ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
  1268. DECLARE_SC(sc, _T("CMMCToolBar::OnToolTipText"));
  1269. CString strTipText = _T("\n");
  1270. // need to handle both ANSI and UNICODE versions of the message
  1271. TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
  1272. TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
  1273. UINT nID = pNMHDR->idFrom;
  1274. if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
  1275. pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
  1276. {
  1277. // idFrom is actually the HWND of the tool,
  1278. // this cannot be true since we did not set this.
  1279. ASSERT(FALSE);
  1280. }
  1281. if (nID != 0) // will be zero on a separator // this is the command id, not the button index
  1282. {
  1283. // Ask the active view's CViewToolBarData for tooltip
  1284. // corresponding to toolbar with command-id nID.
  1285. sc = ScCheckPointers(m_pActiveAMCViewToolbars, E_UNEXPECTED);
  1286. if (sc)
  1287. return FALSE;
  1288. sc = m_pActiveAMCViewToolbars->ScGetToolTip(nID, strTipText);
  1289. if (sc)
  1290. {
  1291. // No match.
  1292. #ifdef DBG
  1293. strTipText = _T("Unable to get tooltip\nUnable to get tooltip");
  1294. #else
  1295. strTipText = _T("\n");
  1296. #endif
  1297. }
  1298. }
  1299. /*
  1300. * Common control provides either TOOLTIPTEXTA or TOOLTIPTEXTW. So MMC needs to
  1301. * provide wide char string or ansi string as tooltip. So below we have two kind
  1302. * of string buffers.
  1303. *
  1304. * Also common control does not free the given string, but it copies the tooltip
  1305. * as soon as this method returns. So we make the strings as static so that we
  1306. * can reuse them.
  1307. *
  1308. * Also see ID: Q180646.
  1309. */
  1310. static std::string strToolTipTextBuf;
  1311. static std::wstring wstrToolTipTextBuf;
  1312. USES_CONVERSION;
  1313. if (pNMHDR->code == TTN_NEEDTEXTA)
  1314. {
  1315. wstrToolTipTextBuf = L"\0";
  1316. ASSERT(pTTTA->hinst == NULL);
  1317. strToolTipTextBuf = T2CA((LPCTSTR)strTipText);
  1318. pTTTA->lpszText = const_cast<LPSTR>(strToolTipTextBuf.data());
  1319. }
  1320. else
  1321. {
  1322. strToolTipTextBuf = "\0";
  1323. ASSERT(pTTTW->hinst == NULL);
  1324. wstrToolTipTextBuf = T2CW((LPCTSTR)strTipText);
  1325. pTTTW->lpszText = const_cast<LPWSTR>(wstrToolTipTextBuf.data());
  1326. }
  1327. *pResult = 0;
  1328. return TRUE; // message was handled
  1329. }
  1330. //+-------------------------------------------------------------------
  1331. //
  1332. // Member: CMMCToolBar::ScOnActivateAMCViewToolbars
  1333. //
  1334. // Synopsis: A cAMCViewToolbars object become the active one (since
  1335. // that objects parent view become active). Cache the
  1336. // object to inform it of toolbutton events.
  1337. //
  1338. // Arguments: [pToolbarsOfView] -
  1339. //
  1340. // Returns: SC
  1341. //
  1342. //--------------------------------------------------------------------
  1343. SC CMMCToolBar::ScOnActivateAMCViewToolbars (CAMCViewToolbars *pAMCViewToolbars)
  1344. {
  1345. DECLARE_SC(sc, _T("CMMCToolBar::ScOnActivateAMCViewToolbars"));
  1346. sc = ScCheckPointers(pAMCViewToolbars);
  1347. if (sc)
  1348. return sc;
  1349. m_pActiveAMCViewToolbars = pAMCViewToolbars;
  1350. return (sc);
  1351. }
  1352. //+-------------------------------------------------------------------
  1353. //
  1354. // Member: CAMCView::ScOnDeactivateAMCViewToolbars
  1355. //
  1356. // Synopsis: The CAMCViewToolbars object became inactive (as its parent
  1357. // became inactive). Reset the cached active toolbar object.
  1358. //
  1359. // Arguments:
  1360. //
  1361. // Returns: SC
  1362. //
  1363. //--------------------------------------------------------------------
  1364. SC CMMCToolBar::ScOnDeactivateAMCViewToolbars ()
  1365. {
  1366. DECLARE_SC(sc, _T("CAMCView::ScOnDeactivateAMCViewToolbars"));
  1367. m_pActiveAMCViewToolbars = NULL;
  1368. return (sc);
  1369. }
  1370. //+-------------------------------------------------------------------
  1371. //
  1372. // Member: CMMCToolBar::ScHideButton
  1373. //
  1374. // Synopsis: Hide or Un-hide a button & update the toolbar
  1375. // separators & size.
  1376. //
  1377. // Arguments: [idCommand] - Command ID of the button to [un]hide.
  1378. // [fHiding] - Hide or Unhide.
  1379. //
  1380. // Returns: SC
  1381. //
  1382. // Note: Do not call this method to hide separators.
  1383. //
  1384. //--------------------------------------------------------------------
  1385. SC CMMCToolBar::ScHideButton (int idCommand, BOOL fHiding)
  1386. {
  1387. AFX_MANAGE_STATE (AfxGetAppModuleState());
  1388. DECLARE_SC(sc, _T("CMMCToolBar::ScHideButton"));
  1389. int nIndex = CommandToIndex(idCommand);
  1390. TBBUTTON tbButton;
  1391. BOOL bRet = GetButton(nIndex, &tbButton);
  1392. sc = bRet ? S_OK : E_FAIL;
  1393. if (sc)
  1394. return sc;
  1395. // Dont call this method to hide separators.
  1396. if (tbButton.fsStyle & TBSTYLE_SEP)
  1397. return (sc = S_FALSE);
  1398. bRet = HideButton(idCommand, fHiding);
  1399. sc = bRet ? S_OK : E_FAIL;
  1400. if (sc)
  1401. return sc;
  1402. UpdateSeparators (idCommand, fHiding);
  1403. UpdateToolbarSize(true /* Update Asynch'ly*/);
  1404. return (sc);
  1405. }
  1406. //+-------------------------------------------------------------------
  1407. //
  1408. // Member: UpdateToolbarSize
  1409. //
  1410. // Synopsis: Update the toobar, needed to lazy update (not update
  1411. // after adding each button, cache all the buttons) of
  1412. // toolbar size.
  1413. //
  1414. // Arguments: [bAsync] - Asynchronous or Synch update.
  1415. //
  1416. // Returns: void
  1417. //
  1418. //--------------------------------------------------------------------
  1419. void CMMCToolBar::UpdateToolbarSize(bool bAsync)
  1420. {
  1421. MSG msg;
  1422. HWND hWnd = m_hWnd;
  1423. if (!bAsync)
  1424. CToolBarCtrlEx::UpdateToolbarSize();
  1425. else if (!PeekMessage (&msg, m_hWnd, s_nUpdateToolbarSizeMsg, s_nUpdateToolbarSizeMsg, PM_NOREMOVE))
  1426. ::PostMessage (m_hWnd, s_nUpdateToolbarSizeMsg, 0, 0);
  1427. }
  1428. //+-------------------------------------------------------------------
  1429. //
  1430. // Member: OnUpdateToolbarSize
  1431. //
  1432. // Synopsis: Our registered message handler.
  1433. //
  1434. // Arguments: None used.
  1435. //
  1436. // Returns: LRESULT
  1437. //
  1438. //--------------------------------------------------------------------
  1439. LRESULT CMMCToolBar::OnUpdateToolbarSize(WPARAM , LPARAM)
  1440. {
  1441. CToolBarCtrlEx::UpdateToolbarSize();
  1442. return 0;
  1443. }
  1444. /*--------------------------------------------------------------------------*
  1445. * CMMCToolBar::UpdateSeparators
  1446. *
  1447. * The legend for the comments below is:
  1448. *
  1449. * L = left edge
  1450. * R = right edge
  1451. * * = target button
  1452. * B = visible non-separator
  1453. * b = hidden non-separator
  1454. * S = visible separator
  1455. * s = hidden separator
  1456. * h = 0 or more hidden buttons, separator or non-separator
  1457. *--------------------------------------------------------------------------*/
  1458. void CMMCToolBar::UpdateSeparators (int idCommand, BOOL fHiding)
  1459. {
  1460. int nButtonIndex = CommandToIndex (idCommand);
  1461. if (nButtonIndex == -1)
  1462. return;
  1463. int nLeftVisible;
  1464. int nRightVisible;
  1465. int cButtons = GetButtonCount ();
  1466. /*
  1467. * If the button is being hidden, turn off any separators
  1468. * that are now redundant. There are three situations where
  1469. * we'll need to turn off a separator (see legend above):
  1470. *
  1471. * 1. Lh*hS
  1472. * 2. Sh*hS
  1473. * 3. Sh*hR
  1474. *
  1475. * These situations are mutually exclusive.
  1476. */
  1477. if (fHiding)
  1478. {
  1479. TBBUTTON btnLeft;
  1480. TBBUTTON btnRight;
  1481. /*
  1482. * look to the left of the button being hidden for the
  1483. * left edge or a visible button
  1484. */
  1485. for (nLeftVisible = nButtonIndex-1; nLeftVisible >= 0; nLeftVisible--)
  1486. {
  1487. GetButton (nLeftVisible, &btnLeft);
  1488. if (!(btnLeft.fsState & TBSTATE_HIDDEN))
  1489. break;
  1490. }
  1491. ASSERT (nLeftVisible < nButtonIndex);
  1492. ASSERT (nLeftVisible >= -1);
  1493. /*
  1494. * look to the right of the button being hidden for the
  1495. * right edge or a visible separator
  1496. */
  1497. for (nRightVisible = nButtonIndex+1; nRightVisible < cButtons; nRightVisible++)
  1498. {
  1499. GetButton (nRightVisible, &btnRight);
  1500. if (!(btnRight.fsState & TBSTATE_HIDDEN))
  1501. break;
  1502. }
  1503. ASSERT (nRightVisible > nButtonIndex);
  1504. ASSERT (nRightVisible <= cButtons);
  1505. /*
  1506. * case 1: Lh*hS
  1507. */
  1508. if ((nLeftVisible == -1) &&
  1509. (nRightVisible != cButtons) &&
  1510. (btnRight.fsStyle & TBSTYLE_SEP))
  1511. HideButton (btnRight.idCommand, true);
  1512. /*
  1513. * case 2: Sh*hS
  1514. */
  1515. else if ((nLeftVisible != -1) &&
  1516. (nRightVisible != cButtons) &&
  1517. (btnLeft.fsStyle & TBSTYLE_SEP) &&
  1518. (btnRight.fsStyle & TBSTYLE_SEP))
  1519. HideButton (btnRight.idCommand, true);
  1520. /*
  1521. * case 3: Sh*hR
  1522. */
  1523. else if ((nLeftVisible != -1) &&
  1524. (nRightVisible == cButtons) &&
  1525. (btnLeft.fsStyle & TBSTYLE_SEP))
  1526. HideButton (btnLeft.idCommand, true);
  1527. }
  1528. /*
  1529. * Otherwise, the button is being shown; turn on any separators
  1530. * that are no longer redundant. There are two situations where
  1531. * we'll need to turn on a separator (see legend above):
  1532. *
  1533. * 1. Bhsh*
  1534. * 2. *hshB
  1535. *
  1536. * Both 1 and 2 can occur simultaneously.
  1537. */
  1538. else do // not a loop
  1539. {
  1540. TBBUTTON btn;
  1541. /*
  1542. * look to the left of the button being shown for the
  1543. * left edge or a visible button
  1544. */
  1545. int idLeftSeparatorCommand = -1;
  1546. for (nLeftVisible = nButtonIndex-1; nLeftVisible >= 0; nLeftVisible--)
  1547. {
  1548. GetButton (nLeftVisible, &btn);
  1549. if (btn.fsStyle & TBSTYLE_SEP)
  1550. idLeftSeparatorCommand = btn.idCommand;
  1551. if (!(btn.fsState & TBSTATE_HIDDEN))
  1552. break;
  1553. }
  1554. ASSERT (nLeftVisible < nButtonIndex);
  1555. ASSERT (nLeftVisible >= -1);
  1556. /*
  1557. * look to the right of the button being shown for the
  1558. * right edge or a hidden separator
  1559. */
  1560. int idRightSeparatorCommand = -1;
  1561. for (nRightVisible = nButtonIndex+1; nRightVisible < cButtons; nRightVisible++)
  1562. {
  1563. GetButton (nRightVisible, &btn);
  1564. if (btn.fsStyle & TBSTYLE_SEP)
  1565. idRightSeparatorCommand = btn.idCommand;
  1566. if (!(btn.fsState & TBSTATE_HIDDEN))
  1567. break;
  1568. }
  1569. ASSERT (nRightVisible > nButtonIndex);
  1570. ASSERT (nRightVisible <= cButtons);
  1571. /*
  1572. * case 1: Bhsh*
  1573. */
  1574. if ((nLeftVisible != -1) && (idLeftSeparatorCommand != -1))
  1575. HideButton (idLeftSeparatorCommand, false);
  1576. /*
  1577. * case 2: *hshB
  1578. */
  1579. if ((nRightVisible != cButtons) && (idRightSeparatorCommand != -1))
  1580. HideButton (idRightSeparatorCommand, false);
  1581. } while (0);
  1582. }