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.

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