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
1917 lines
60 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1999
|
|
//
|
|
// File: toolbar.cpp
|
|
//
|
|
// Contents: ToolBars implementation
|
|
//
|
|
// History: 09-30-99 AnandhaG Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "ChildFrm.h"
|
|
#include "mainfrm.h"
|
|
#include "controls.h"
|
|
#include "toolbar.h"
|
|
#include "bitmap.h"
|
|
#include "amcview.h"
|
|
#include "util.h"
|
|
|
|
int CAMCViewToolbars::s_idCommand = MMC_TOOLBUTTON_ID_FIRST;
|
|
|
|
CAMCViewToolbars::~CAMCViewToolbars()
|
|
{
|
|
// Ask the toolbars (on nodemgr side) that reference this object to
|
|
// remove their references.
|
|
TBarToBitmapIndex::iterator itToolbars = m_mapTBarToBitmapIndex.begin();
|
|
for (;itToolbars != m_mapTBarToBitmapIndex.end(); ++itToolbars)
|
|
{
|
|
CToolbarNotify* pNotifyCallbk = itToolbars->first;
|
|
SC sc = ScCheckPointers(pNotifyCallbk, E_UNEXPECTED);
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
continue;
|
|
}
|
|
|
|
sc = pNotifyCallbk->ScAMCViewToolbarsBeingDestroyed();
|
|
if (sc)
|
|
{
|
|
sc.TraceAndClear();
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScInit
|
|
//
|
|
// Synopsis: Initialize the object by createing imagelist.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScInit (CMMCToolBar *pMainToolbar, CAMCView* pAMCViewOwner)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScInit"));
|
|
|
|
sc = ScCheckPointers(pMainToolbar, pAMCViewOwner);
|
|
if(sc)
|
|
return sc;
|
|
|
|
m_pMainToolbar = pMainToolbar;
|
|
m_pAMCViewOwner = pAMCViewOwner;
|
|
|
|
if (m_ImageList.m_hImageList)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Create an imagelist.
|
|
BOOL b = m_ImageList.Create(BUTTON_BITMAP_SIZE, BUTTON_BITMAP_SIZE,
|
|
ILC_COLORDDB|ILC_MASK,
|
|
20 /*Initial imagelist size*/, 10 /* grow */);
|
|
|
|
|
|
if (!b)
|
|
return (sc = E_FAIL);
|
|
|
|
m_ImageList.SetBkColor(CLR_NONE);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScCreateToolBar
|
|
//
|
|
// Synopsis: Create a Toolbar (Just return CMMCToolbarIntf).
|
|
//
|
|
// Arguments:
|
|
// [ppToolbarIntf] - corresponds to IToolbar imp.
|
|
// call this interface to manipulate toolbar UI.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScCreateToolBar (CMMCToolbarIntf** ppToolbarIntf)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScCreateToolBar"));
|
|
sc = ScCheckPointers(ppToolbarIntf);
|
|
if (sc)
|
|
return sc;
|
|
|
|
*ppToolbarIntf = this;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScDisableToolbars
|
|
//
|
|
// Synopsis: Disable all the toolbar buttons (reqd during LV multiselect).
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScDisableToolbars ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScDisableToolbars"));
|
|
|
|
if (! m_fViewActive)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Now iterate thro all toolbuttons & disable them.
|
|
ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
|
|
for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
|
|
{
|
|
CMMCToolbarButton *pToolButton = itBtn;
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Set the UI button state.
|
|
sc = ScSetButtonStateInToolbar(pToolButton, TBSTATE_ENABLED, FALSE);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Save the new state.
|
|
BYTE byOldState = pToolButton->GetState();
|
|
pToolButton->SetState(byOldState & ~TBSTATE_ENABLED);
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScAddBitmap
|
|
//
|
|
// Synopsis: Add the given bitmap into the view toolbars imagelist.
|
|
// Also store the start index & number of images in an object
|
|
// mapped by the CToolbarNotify (which identifies snapin toolbar
|
|
// or std bar).
|
|
//
|
|
// Arguments: [pNotifyCallbk] - The toolbar identifier (Button click callback interface).
|
|
// [nImages] - Number of bitmaps.
|
|
// [hbmp] - Handle to the bitmap.
|
|
// [crMask] - Color used to generate a mask to overlay
|
|
// the images on the toolbar button.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScAddBitmap (CToolbarNotify* pNotifyCallbk, INT nImages,
|
|
HBITMAP hbmp, COLORREF crMask)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScAddBitmap"));
|
|
sc = ScCheckPointers(pNotifyCallbk, hbmp);
|
|
if (sc)
|
|
return sc;
|
|
|
|
/*
|
|
* make a copy of the input bitmap because ImageList_AddMasked will
|
|
* modify the input bitmap
|
|
*/
|
|
CBitmap bmpCopy;
|
|
bmpCopy.Attach (CopyBitmap (hbmp));
|
|
|
|
if (bmpCopy.GetSafeHandle() == NULL)
|
|
return (sc.FromLastError());
|
|
|
|
sc = ScCheckPointers(m_ImageList.m_hImageList, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
MMCToolbarImages imagesNew;
|
|
|
|
int cImagesOld = m_ImageList.GetImageCount();
|
|
|
|
// First add the bitmap into the imagelist.
|
|
imagesNew.iStart = m_ImageList.Add (bmpCopy, crMask);
|
|
|
|
imagesNew.cCount = m_ImageList.GetImageCount() - cImagesOld;
|
|
|
|
if (imagesNew.iStart == -1)
|
|
return (sc = E_FAIL);
|
|
|
|
/*
|
|
* Assume a snapin adds 3 bitmaps initialy & then 4 for a toolbar.
|
|
* Then while adding buttons it will specify bitmap index as 5.
|
|
*
|
|
* So this toolbar will have two MMCToolbarImages objects in the multimap.
|
|
*
|
|
* The first MMCToolbarImages has cCount = 3, iStartWRTSnapin = 0, thus
|
|
* images from 0 (iStartWRTSnapin) to 3 (iStartWRTSnapin + cCount) with respect
|
|
* to snapin.
|
|
* The second MMCToolbarImages has cCount = 4, iStartWRTSnapin = 3, thus
|
|
* images from 3(iStartWRTSnapin) to 7(iStartWRTSnapin + cCount) wrt snapin.
|
|
*
|
|
* The iStartWRTSnapin member is nothing but the largest of iStartWRTSnapin + cCount
|
|
* in all of this toolbars MMCToolbarImages.
|
|
*
|
|
*/
|
|
|
|
std::pair<TBarToBitmapIndex::iterator, TBarToBitmapIndex::iterator>
|
|
range = m_mapTBarToBitmapIndex.equal_range(pNotifyCallbk);
|
|
|
|
imagesNew.iStartWRTSnapin = 0;
|
|
while (range.first != range.second)
|
|
{
|
|
// Go thro each item and get the correct start index.
|
|
MMCToolbarImages imagesOld = (range.first)->second;
|
|
int nLastImageIndex = imagesOld.iStartWRTSnapin + imagesOld.cCount;
|
|
if ( imagesNew.iStartWRTSnapin < nLastImageIndex )
|
|
imagesNew.iStartWRTSnapin = nLastImageIndex;
|
|
|
|
(range.first)++;
|
|
}
|
|
|
|
// Now store the start index, number of bitmaps identified
|
|
// by CToolbarNotify in a multi-map.
|
|
m_mapTBarToBitmapIndex.insert(
|
|
TBarToBitmapIndex::value_type(pNotifyCallbk, imagesNew) );
|
|
|
|
// To be compatible with SysInfo snapin dont return error.
|
|
if ((cImagesOld + nImages) > m_ImageList.GetImageCount())
|
|
{
|
|
sc = E_INVALIDARG;
|
|
TraceSnapinError(_T("IToolbar::AddBitmap, Number of bitmaps is less than number mentioned"), sc);
|
|
sc.Clear();
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScValidateButton
|
|
//
|
|
// Synopsis: Validate the MMCBUTTON data.
|
|
//
|
|
// Arguments:
|
|
// [nButtons] - Number of elements in MMCBUTTON array.
|
|
// [lpButtons] - MMCBUTTON array.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScValidateButton(int nButtons, LPMMCBUTTON lpButtons)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC (sc, _T("CAMCViewToolbars::ScValidateButton"));
|
|
|
|
if ( (lpButtons == NULL) || (nButtons < 1) )
|
|
return (sc = E_INVALIDARG);
|
|
|
|
for (int i=0; i < nButtons; i++)
|
|
{
|
|
if (lpButtons[i].nBitmap > GetImageCount())
|
|
{
|
|
sc = E_INVALIDARG;
|
|
return sc;
|
|
}
|
|
|
|
// There should be button text if it is not a separator.
|
|
if (((lpButtons[i].fsType & TBSTYLE_SEP) == 0) &&
|
|
((lpButtons[i].lpButtonText == NULL) ||
|
|
(lpButtons[i].lpTooltipText == NULL)))
|
|
{
|
|
sc = E_INVALIDARG;
|
|
return sc;
|
|
}
|
|
|
|
// There should be no bitmap set if it is a separator.
|
|
if ( ((lpButtons[i].fsType & TBSTYLE_SEP) != 0) &&
|
|
(lpButtons[i].nBitmap > 0) )
|
|
{
|
|
sc = E_INVALIDARG;
|
|
return sc;
|
|
}
|
|
|
|
// Reset any TBSTATE_WRAP state.
|
|
lpButtons[i].fsState &= (~TBSTATE_WRAP);
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScInsertButtonToToolbar
|
|
//
|
|
// Synopsis: Inserts the toolbar button into the main toolbar UI.
|
|
//
|
|
// Arguments: [pToolButton] - The CMMCToolbarButton object.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScInsertButtonToToolbar (CMMCToolbarButton* pToolButton)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScInsertButtonToToolbar"));
|
|
sc = ScCheckPointers(pToolButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Button can be added only if view is active, button is not already added
|
|
// to the toolbar & toolbar is attached.
|
|
if (! m_fViewActive)
|
|
return (sc);
|
|
|
|
if (pToolButton->IsButtonIsAddedToUI())
|
|
return sc;
|
|
|
|
if (! IsToolbarAttached(pToolButton->GetToolbarNotify()))
|
|
return sc;
|
|
|
|
// Now get the main toolbar & add the button.
|
|
CMMCToolBar* pToolBarUI = GetMainToolbar();
|
|
sc = ScCheckPointers(pToolBarUI, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
TBBUTTON tbButton;
|
|
ZeroMemory(&tbButton, sizeof(tbButton));
|
|
tbButton.idCommand = pToolButton->GetUniqueCommandID();
|
|
tbButton.fsStyle = pToolButton->GetStyle();
|
|
tbButton.iBitmap = pToolButton->GetBitmap();
|
|
tbButton.fsState = pToolButton->GetState();
|
|
|
|
// The toolbar is hidden by customize view dialog.
|
|
// If so insert the button as hidden. (Do not record
|
|
// the hidden status into the CMMCToolbarButton).
|
|
if (IsToolbarHidden(pToolButton->GetToolbarNotify()))
|
|
tbButton.fsState |= TBSTATE_HIDDEN;
|
|
|
|
// Insert the button.
|
|
BOOL bRet = pToolBarUI->InsertButton(-1, &tbButton);
|
|
sc = (bRet ? S_OK : E_FAIL);
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
pToolButton->SetButtonIsAddedToUI(true);
|
|
|
|
// Bug 225711: If the button is supposed to be hidden, hide it now.
|
|
if (tbButton.fsState & TBSTATE_HIDDEN)
|
|
sc = pToolBarUI->ScHideButton(tbButton.idCommand, true);
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScInsertButtonToDataStr
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: [pNotifyCallbk] - The callbk interface for IToolbar imp.
|
|
// [nIndex] - Index of the button.
|
|
// [lpButton] - MMCBUTTON ptr.
|
|
// [pToolButton] - Return value, the button added (or found
|
|
// in case of dup buttons).
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScInsertButtonToDataStr (CToolbarNotify* pNotifyCallbk,
|
|
int nIndex,
|
|
LPMMCBUTTON lpButton,
|
|
CMMCToolbarButton** ppToolButton)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScInsertButtonToDataStr"));
|
|
|
|
sc = ScCheckPointers(pNotifyCallbk, ppToolButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = ScValidateButton(1, lpButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Make sure snapin does not add duplicate buttons
|
|
// For compatibility (services snapin) this is not a bug.
|
|
*ppToolButton = GetToolbarButton(pNotifyCallbk, lpButton->idCommand);
|
|
if (*ppToolButton)
|
|
{
|
|
// if snapin added the button we already have,
|
|
// we still need to ensure its state (BUG: 439229)
|
|
if ((*ppToolButton)->GetState() != lpButton->fsState)
|
|
{
|
|
// update the object
|
|
(*ppToolButton)->SetState(lpButton->fsState);
|
|
// do we need to update the UI as well?
|
|
if (m_fViewActive && (*ppToolButton)->IsButtonIsAddedToUI())
|
|
{
|
|
INT iCommandID = (*ppToolButton)->GetUniqueCommandID();
|
|
if (!m_pMainToolbar->SetState(iCommandID, lpButton->fsState))
|
|
return (sc = E_FAIL);
|
|
}
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
// If this button belongs to different toolbar from last button
|
|
// then insert a separator in between.
|
|
if (! m_vToolbarButtons.empty())
|
|
{
|
|
CMMCToolbarButton& lastBtn = m_vToolbarButtons.back();
|
|
if (lastBtn.GetToolbarNotify() != pNotifyCallbk)
|
|
{
|
|
CMMCToolbarButton separatorBtn(-1, GetUniqueCommandID(), -1, -1, 0, TBSTYLE_SEP, pNotifyCallbk);
|
|
m_vToolbarButtons.push_back(separatorBtn);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Assume a snapin adds 3 bitmaps initialy & then 4 for a toolbar.
|
|
* Then while adding buttons it will specify bitmap index as 5.
|
|
*
|
|
* So this toolbar will have two MMCToolbarImages objects in the multimap.
|
|
*
|
|
* The first MMCToolbarImages has cCount = 3, iStartWRTSnapin = 0, thus
|
|
* images from 0 (iStartWRTSnapin) to 3 (iStartWRTSnapin + cCount) with respect
|
|
* to snapin.
|
|
* The second MMCToolbarImages has cCount = 4, iStartWRTSnapin = 3, thus
|
|
* images from 3(iStartWRTSnapin) to 7(iStartWRTSnapin + cCount) wrt snapin.
|
|
*
|
|
* The iStartWRTSnapin member is nothing but the largest of iStartWRTSnapin + cCount
|
|
* in all of this toolbars MMCToolbarImages.
|
|
*
|
|
* Below we run thro different MMCToolbarImages for this toolbar and see in which
|
|
* one the given index falls under and calculate the real index by adding that
|
|
* object's iStart.
|
|
*
|
|
*/
|
|
|
|
// Now we need to compute the bitmap index. Find this toolbar in the multimap.
|
|
int iBitmap = -1;
|
|
|
|
std::pair<TBarToBitmapIndex::iterator, TBarToBitmapIndex::iterator>
|
|
range = m_mapTBarToBitmapIndex.equal_range(pNotifyCallbk);
|
|
|
|
while (range.first != range.second)
|
|
{
|
|
MMCToolbarImages images = (range.first)->second;
|
|
|
|
// We need to find the bitmap whose start index is greater than or
|
|
// equal to given index and upper index is less than given index.
|
|
int nLastImageIndex = images.iStartWRTSnapin + images.cCount -1;
|
|
if ( (lpButton->nBitmap >= images.iStartWRTSnapin ) &&
|
|
( lpButton->nBitmap <= nLastImageIndex ) )
|
|
{
|
|
iBitmap = images.iStart + lpButton->nBitmap;
|
|
break;
|
|
}
|
|
|
|
(range.first)++;
|
|
}
|
|
|
|
// No bitmaps for separators.
|
|
if ( (-1 == iBitmap) && (!(TBSTYLE_SEP & lpButton->fsType)) )
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
|
|
// Create CMMCToolbarButton for each button, init it with unique command-id, toolbar id.
|
|
// There is only one imagelist per view that contains bitmaps from different toolbars.
|
|
// We use a multimap to identify a particular toolbar's bitmap start indices.
|
|
CMMCToolbarButton newButton(lpButton->idCommand,
|
|
GetUniqueCommandID(),
|
|
nIndex,
|
|
(lpButton->fsType & TBSTYLE_SEP) ? 0 : iBitmap,
|
|
lpButton->fsState,
|
|
lpButton->fsType,
|
|
pNotifyCallbk);
|
|
|
|
USES_CONVERSION;
|
|
// First save the button data in CMMCToolButton.
|
|
if (lpButton->lpTooltipText)
|
|
newButton.SetTooltip(OLE2CT(lpButton->lpTooltipText));
|
|
|
|
if (lpButton->lpButtonText)
|
|
newButton.SetButtonText(OLE2CT(lpButton->lpButtonText));
|
|
|
|
// Add this button to the end of our array.
|
|
ToolbarButtons::iterator itBtn = m_vToolbarButtons.insert(m_vToolbarButtons.end(), newButton);
|
|
if (m_vToolbarButtons.end() == itBtn)
|
|
return (sc = E_FAIL);
|
|
|
|
*ppToolButton = itBtn;
|
|
sc = ScCheckPointers(*ppToolButton, E_OUTOFMEMORY);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScInsertButton
|
|
//
|
|
// Synopsis: Insert a button in our array & if the our view is active
|
|
// add the button to the UI.
|
|
//
|
|
// Arguments: [pNotifyCallbk] - The callbk interface for IToolbar imp.
|
|
// [nIndex] - Index of the button.
|
|
// [lpButton] - MMCBUTTON ptr.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScInsertButton (CToolbarNotify* pNotifyCallbk, int nIndex, LPMMCBUTTON lpButton)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScInsertButton"));
|
|
|
|
CMMCToolbarButton *pToolbarButton = NULL;
|
|
|
|
sc = ScInsertButtonToDataStr(pNotifyCallbk, nIndex, lpButton, &pToolbarButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = ScInsertButtonToToolbar(pToolbarButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScAddButtons
|
|
//
|
|
// Synopsis: Save the buttons in our array and add them to UI if view is active.
|
|
//
|
|
// Arguments: [pNotifyCallbk] - Button click callback interface.
|
|
// [nButtons] - Number of buttons in lpButtons array.
|
|
// [lpButtons] - MMCBUTTONs (array) bo be added.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScAddButtons (CToolbarNotify* pNotifyCallbk, int nButtons, LPMMCBUTTON lpButtons)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScAddButtons"));
|
|
|
|
for (int i = 0; i < nButtons; i++)
|
|
{
|
|
sc = ScInsertButton(pNotifyCallbk, -1, &(lpButtons[i]));
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScDeleteButtonFromToolbar
|
|
//
|
|
// Synopsis: Deletes a button from the toolbar UI if it exists.
|
|
//
|
|
// Arguments: [pToolButton] - The CMMCToolbarButton object.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScDeleteButtonFromToolbar (CMMCToolbarButton* pToolButton)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScDeleteButtonFromToolbar"));
|
|
|
|
sc = ScCheckPointers(pToolButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if (! m_fViewActive)
|
|
return (sc);
|
|
|
|
if (! pToolButton->IsButtonIsAddedToUI())
|
|
return sc;
|
|
|
|
CMMCToolBar* pToolBarUI = GetMainToolbar();
|
|
sc = ScCheckPointers(pToolBarUI, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
int nIndexOfBtn = pToolBarUI->CommandToIndex(pToolButton->GetUniqueCommandID());
|
|
|
|
// Update the separators before deleting the button.
|
|
pToolBarUI->UpdateSeparators(pToolButton->GetUniqueCommandID(), true);
|
|
|
|
// Delete the button.
|
|
BOOL bRet = pToolBarUI->DeleteButton(nIndexOfBtn);
|
|
sc = (bRet ? S_OK : E_FAIL);
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
pToolButton->SetButtonIsAddedToUI(false);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScDeleteButton
|
|
//
|
|
// Synopsis: Delete button at given index (index is wrt snapin).
|
|
//
|
|
// Arguments: [pNotifyCallbk]
|
|
// [nIndex[
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScDeleteButton (CToolbarNotify* pNotifyCallbk, int nIndex)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScDeleteButton"));
|
|
|
|
sc = ScCheckPointers(pNotifyCallbk);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Now iterate thro all toolbuttons & find the one with
|
|
// given toolbar-id & index and if it is added to the
|
|
// toolbar UI then delete it.
|
|
ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
|
|
for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
|
|
{
|
|
CMMCToolbarButton *pToolButton = itBtn;
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if ( (pToolButton->GetToolbarNotify() == pNotifyCallbk) &&
|
|
(pToolButton->GetIndexFromSnapin() == nIndex) )
|
|
{
|
|
sc = ScDeleteButtonFromToolbar(pToolButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
// To be compatible with services snapin on Windows2000 return S_OK.
|
|
sc = S_OK;
|
|
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);
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScAttach
|
|
//
|
|
// Synopsis: Make the toolbars visible (Add the toolbar buttons
|
|
// to the toolbar UI). First get the CMMCToolbarData
|
|
// and set attached flag. Then add the buttons to toolbar.
|
|
//
|
|
// Arguments: [pNotifyCallbk] - The toolbar identifier (corresponds
|
|
// to the IToolbar imp).
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScAttach (CToolbarNotify* pNotifyCallbk)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScAttach"));
|
|
|
|
sc = ScCheckPointers(pNotifyCallbk);
|
|
if (sc)
|
|
return sc;
|
|
|
|
SetToolbarAttached(pNotifyCallbk, true);
|
|
|
|
// Go thro all ToolButtons of this toolbar and add those
|
|
// buttons that are not yet added to the toolbar UI.
|
|
ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
|
|
for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
|
|
{
|
|
CMMCToolbarButton *pToolButton = itBtn;
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if (pToolButton->GetToolbarNotify() == pNotifyCallbk)
|
|
{
|
|
// Add this button to toolbar UI.
|
|
sc = ScInsertButtonToToolbar(pToolButton);
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScDetach
|
|
//
|
|
// Synopsis: Remove the toolbar buttons from the toolbar UI for
|
|
// given toolbar.
|
|
//
|
|
// Arguments: [pNotifyCallbk] - The given (IToolbar) toolbar.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScDetach (CToolbarNotify* pNotifyCallbk)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScDetach"));
|
|
|
|
sc = ScCheckPointers(pNotifyCallbk);
|
|
if (sc)
|
|
return sc;
|
|
|
|
SetToolbarAttached(pNotifyCallbk, false);
|
|
|
|
// Go thro all ToolButtons of this toolbar and delete those
|
|
// buttons that are added to the toolbar UI.
|
|
ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
|
|
for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
|
|
{
|
|
CMMCToolbarButton *pToolButton = itBtn;
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if (pToolButton->GetToolbarNotify() == pNotifyCallbk)
|
|
{
|
|
// Delete this button from the toolbar UI.
|
|
sc = ScDeleteButtonFromToolbar(pToolButton);
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScGetButtonStateInToolbar
|
|
//
|
|
// Synopsis: Get the state of given button from toolbar UI.
|
|
//
|
|
// Arguments: [pToolButton] - The CMMCToolbarButton object.
|
|
// [byState] - The TBSTATE needed.
|
|
// [pbState] - The button state.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScGetButtonStateInToolbar(CMMCToolbarButton *pToolButton,
|
|
BYTE byState,
|
|
BOOL* pbState)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScGetButtonStateInToolbar"));
|
|
|
|
sc = ScCheckPointers(pToolButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
ASSERT(NULL != m_pMainToolbar);
|
|
int idCommand = pToolButton->GetUniqueCommandID();
|
|
|
|
// Make sure button with this command-id exists.
|
|
if (m_pMainToolbar->GetState(idCommand) == -1)
|
|
return (sc = E_INVALIDARG);
|
|
|
|
switch (byState)
|
|
{
|
|
case TBSTATE_ENABLED:
|
|
*pbState = m_pMainToolbar->IsButtonEnabled(idCommand);
|
|
break;
|
|
case TBSTATE_CHECKED:
|
|
*pbState = m_pMainToolbar->IsButtonChecked(idCommand);
|
|
break;
|
|
case TBSTATE_HIDDEN:
|
|
*pbState = m_pMainToolbar->IsButtonHidden(idCommand);
|
|
break;
|
|
case TBSTATE_INDETERMINATE:
|
|
*pbState = m_pMainToolbar->IsButtonIndeterminate(idCommand);
|
|
break;
|
|
case TBSTATE_PRESSED:
|
|
*pbState = m_pMainToolbar->IsButtonPressed(idCommand);
|
|
break;
|
|
default:
|
|
sc = E_NOTIMPL;
|
|
ASSERT(FALSE); // Invalid option
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScGetButtonState
|
|
//
|
|
// Synopsis: Get the state of the given button.
|
|
//
|
|
// Arguments: [pNotifyCallbk] - The toolbar (IToolbar).
|
|
// [idCommand] - Snapin given command-id of button.
|
|
// [byState] - The state needed.
|
|
// [pbState] - bool ret val.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScGetButtonState (CToolbarNotify* pNotifyCallbk,
|
|
int idCommandFromSnapin, BYTE byState,
|
|
BOOL* pbState)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScGetButtonState"));
|
|
|
|
sc = ScCheckPointers(pNotifyCallbk, pbState);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Get the toolbutton of given toolbar id & command-id.
|
|
CMMCToolbarButton *pToolButton = GetToolbarButton(pNotifyCallbk, idCommandFromSnapin);
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// The toolbutton is not available if view is not active or toolbar is hidden by
|
|
// customize view dialog, then return the state from our data-structure.
|
|
if (m_fViewActive && pToolButton->IsButtonIsAddedToUI() && (!IsToolbarHidden(pNotifyCallbk)) )
|
|
sc = ScGetButtonStateInToolbar(pToolButton, byState, pbState);
|
|
else
|
|
// We cant access the toolbar UI. Return the state we saved.
|
|
*pbState = (pToolButton->GetState() & byState);
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScSetButtonStateInToolbar
|
|
//
|
|
// Synopsis: Set the state of a button in main toolbar UI.
|
|
//
|
|
// Arguments: [pToolButton] - The CMMCToolbarButton object.
|
|
// [byState] - The button state to be set.
|
|
// [bState] - Set or Reset the state.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScSetButtonStateInToolbar (CMMCToolbarButton* pToolButton,
|
|
BYTE byState,
|
|
BOOL bState)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScSetButtonStateInToolbar"));
|
|
|
|
sc = ScCheckPointers(pToolButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if(! m_fViewActive)
|
|
return sc;
|
|
|
|
if (! pToolButton->IsButtonIsAddedToUI())
|
|
return sc;
|
|
|
|
ASSERT(NULL != m_pMainToolbar);
|
|
|
|
int idCommand = pToolButton->GetUniqueCommandID();
|
|
|
|
BOOL bRet = FALSE;
|
|
switch (byState)
|
|
{
|
|
case TBSTATE_ENABLED:
|
|
bRet = m_pMainToolbar->EnableButton(idCommand, bState);
|
|
break;
|
|
|
|
case TBSTATE_CHECKED:
|
|
bRet = m_pMainToolbar->CheckButton(idCommand, bState);
|
|
break;
|
|
|
|
case TBSTATE_HIDDEN:
|
|
{
|
|
int nButtonIndex = m_pMainToolbar->CommandToIndex(idCommand);
|
|
|
|
// ignore unknown buttons
|
|
if (nButtonIndex == -1)
|
|
break;
|
|
|
|
// ignore ineffectual changes (negate both sides to insure pure bool)
|
|
if (!m_pMainToolbar->IsButtonHidden(idCommand) == !bState)
|
|
{
|
|
bRet = TRUE;
|
|
break;
|
|
}
|
|
|
|
sc = m_pMainToolbar->ScHideButton(idCommand, bState);
|
|
return sc;
|
|
break;
|
|
}
|
|
|
|
case TBSTATE_INDETERMINATE:
|
|
bRet = m_pMainToolbar->Indeterminate(idCommand, bState);
|
|
break;
|
|
|
|
case TBSTATE_PRESSED:
|
|
bRet = m_pMainToolbar->PressButton(idCommand, bState);
|
|
break;
|
|
|
|
default:
|
|
sc = E_NOTIMPL;
|
|
ASSERT(FALSE); // Invalid option
|
|
return sc;
|
|
}
|
|
|
|
sc = (bRet ? S_OK : E_FAIL);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScSetButtonState
|
|
//
|
|
// Synopsis: Set the state of a button.
|
|
//
|
|
// Arguments: [pNotifyCallbk] - The toolbar (IToolbar).
|
|
// [byState] - The button state to be set.
|
|
// [bState] - Set or Reset the state.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScSetButtonState (CToolbarNotify* pNotifyCallbk,
|
|
int idCommandFromSnapin,
|
|
BYTE byState, BOOL bSetState)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScSetButtonState"));
|
|
|
|
sc = ScCheckPointers(pNotifyCallbk);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Reset any TBSTATE_WRAP state.
|
|
byState &= (~TBSTATE_WRAP);
|
|
|
|
// Get the toolbutton of given toolbar id & command-id.
|
|
CMMCToolbarButton *pToolButton = GetToolbarButton(pNotifyCallbk, idCommandFromSnapin);
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return (sc = S_OK); // Not an error.
|
|
|
|
BYTE byNewState = (bSetState) ? (pToolButton->GetState() | byState) :
|
|
(pToolButton->GetState() & (~byState) );
|
|
|
|
pToolButton->SetState(byNewState);
|
|
|
|
// The toolbar can be hidden by customize view dialog.
|
|
|
|
// If the snapin tries to unhide a button in hidden toolbar just return.
|
|
if ( (byState & TBSTATE_HIDDEN) && (!bSetState) && IsToolbarHidden(pNotifyCallbk) )
|
|
return (sc = S_OK);
|
|
|
|
sc = ScSetButtonStateInToolbar(pToolButton, byState, bSetState);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScOnActivateView
|
|
//
|
|
// Synopsis: The view of this object is active, add its toolbuttons.
|
|
//
|
|
// Arguments: [pAMCView] - The AMCView ptr.
|
|
// [bFirstActiveView] - Is this first active view.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScOnActivateView (CAMCView *pAMCView, // We dont care about this arg.
|
|
bool bFirstActiveView)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScOnActivateView"));
|
|
|
|
// If this is the first active view then insert the toolbar band.
|
|
CMMCToolBar* pMainToolbar = GetMainToolbar();
|
|
sc = ScCheckPointers(pMainToolbar, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = ScFireEvent(CAMCViewToolbarsObserver::ScOnActivateAMCViewToolbars, this);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
m_fViewActive = true;
|
|
|
|
pMainToolbar->SetImageList(GetImageList());
|
|
|
|
// Go thro all ToolButtons of this toolbar and add them to the UI.
|
|
ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
|
|
for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
|
|
{
|
|
CMMCToolbarButton *pToolButton = itBtn;
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Add this button to toolbar UI.
|
|
sc = ScInsertButtonToToolbar(pToolButton);
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
|
|
bool bToolbarBandVisible = pMainToolbar->IsBandVisible();
|
|
bool bThereAreVisibleButtons = IsThereAVisibleButton();
|
|
|
|
// If there are visible buttons show the band.
|
|
if (bThereAreVisibleButtons)
|
|
pMainToolbar->Show(true, true);
|
|
else if (bToolbarBandVisible) // Otherwise hide it if it is currently visible.
|
|
pMainToolbar->Show(false);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScOnDeactivateView
|
|
//
|
|
// Synopsis: The view of this object is de-activated. Disable the
|
|
// imagelists & this object should not manipulate the
|
|
// toolbar UI till OnActivateView is fired.
|
|
//
|
|
// Arguments: [pAMCView] - The view to be de-activated.
|
|
// [bLastActiveView] - Is this the last view.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScOnDeactivateView (CAMCView *pAMCView, bool bLastActiveView)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScOnDeactivateView"));
|
|
|
|
CMMCToolBar* pMainToolbar = GetMainToolbar();
|
|
sc = ScCheckPointers(pMainToolbar, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
|
|
for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
|
|
{
|
|
CMMCToolbarButton *pToolButton = itBtn;
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = ScDeleteButtonFromToolbar(pToolButton);
|
|
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
|
|
sc = ScFireEvent(CAMCViewToolbarsObserver::ScOnDeactivateAMCViewToolbars);
|
|
if (sc)
|
|
sc.TraceAndClear();
|
|
|
|
// If this is last view then delete the band if it is visible.
|
|
if (bLastActiveView && pMainToolbar->IsBandVisible())
|
|
pMainToolbar->Show(FALSE);
|
|
|
|
m_bLastActiveView = bLastActiveView;
|
|
|
|
m_fViewActive = false;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CAMCViewToolbars::ScOnViewDestroyed
|
|
//
|
|
// PURPOSE: When the AMCView is destroyed, need to remove our own reference to it.
|
|
//
|
|
// PARAMETERS:
|
|
// CAMCView * pAMCView :
|
|
//
|
|
// RETURNS:
|
|
// SC
|
|
//
|
|
//****************************************************************************
|
|
SC CAMCViewToolbars::ScOnViewDestroyed (CAMCView *pAMCView)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CAMCViewToolbars::ScOnViewDestroyed"));
|
|
|
|
ASSERT(m_pAMCViewOwner == pAMCView);
|
|
|
|
m_pAMCViewOwner = NULL;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScButtonClickedNotify
|
|
//
|
|
// Synopsis: A button of this object is clicked. Get the context
|
|
// and inform the CToolbarNotify object.
|
|
//
|
|
// Arguments: [nID] - command id of the button clicked.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScButtonClickedNotify (UINT nID)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScButtonClickedNotify"));
|
|
|
|
CMMCToolbarButton* pButton = GetToolbarButton(nID);
|
|
sc = ScCheckPointers(pButton, m_pAMCViewOwner, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Get the context, (the currently selected HNODE,
|
|
// lParam (if result item)) etc...
|
|
HNODE hNode;
|
|
bool bScope;
|
|
LPARAM lParam;
|
|
|
|
sc = m_pAMCViewOwner->ScGetFocusedItem (hNode, lParam, bScope);
|
|
if (sc)
|
|
return sc;
|
|
|
|
CToolbarNotify* pNotifyCallbk = pButton->GetToolbarNotify();
|
|
sc = ScCheckPointers(pNotifyCallbk, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Deactivate if theming (fusion or V6 common-control) context before calling snapins.
|
|
ULONG_PTR ulpCookie;
|
|
if (! MmcDownlevelActivateActCtx(NULL, &ulpCookie))
|
|
return E_FAIL;
|
|
|
|
|
|
// the ScNotifyToolBarClick could cause this object to be deleted. Therefore, this
|
|
// class was changed to be reference counted. The object is locked here and released at the end
|
|
// of the function to avoid an AV in ScFireEvent.
|
|
AddRef();
|
|
|
|
do // this while ensures that the release is called.
|
|
{
|
|
sc = pNotifyCallbk->ScNotifyToolBarClick(hNode, bScope, lParam, pButton->GetCommandIDFromSnapin());
|
|
|
|
MmcDownlevelDeactivateActCtx(0, ulpCookie);
|
|
if (sc)
|
|
break;
|
|
|
|
// fire event informing about execution
|
|
sc = ScFireEvent(CAMCViewToolbarsObserver::ScOnToolbarButtonClicked);
|
|
if (sc)
|
|
break;
|
|
}
|
|
while(0);
|
|
|
|
Release();
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScGetToolTip
|
|
//
|
|
// Synopsis: Tooltip is requested for a button of this object.
|
|
//
|
|
// Arguments: [nCommandID] - Command id of the button.
|
|
// [strTipText] - CString to hold the tooltip.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScGetToolTip (int nCommandID, CString& strTipText)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScGetToolTip"));
|
|
|
|
// Get the toolbutton.
|
|
CMMCToolbarButton* pButton = GetToolbarButton(nCommandID);
|
|
sc = ScCheckPointers(pButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
strTipText = pButton->GetTooltip();
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScDelete
|
|
//
|
|
// Synopsis: A toolbar needs to be deleted. First remove the buttons
|
|
// from UI & remove buttons from our data structure,
|
|
// remove the toolbar reference from our data structures.
|
|
//
|
|
// Arguments: [pNotifyCallbk] - The toolbar (IToolbar).
|
|
//
|
|
// Returns: SC
|
|
//
|
|
// Note: This method should remove its reference of CToolbarNotify
|
|
// object when it returns (even if it encounters intermediate errors).
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScDelete (CToolbarNotify* pNotifyCallbk)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScDelete"));
|
|
sc = ScCheckPointers(pNotifyCallbk);
|
|
if (sc)
|
|
return sc;
|
|
|
|
ToolbarButtons::iterator itBtn;
|
|
// Detach the toolbar first.
|
|
sc = ScDetach(pNotifyCallbk);
|
|
if (sc)
|
|
goto Cleanup;
|
|
|
|
// Delete the buttons from m_vToolbarButtons.
|
|
itBtn = m_vToolbarButtons.begin();
|
|
while (itBtn != m_vToolbarButtons.end())
|
|
{
|
|
CMMCToolbarButton* pToolButton = itBtn;
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
goto Cleanup;
|
|
|
|
if (pToolButton->GetToolbarNotify() == pNotifyCallbk)
|
|
{
|
|
sc = ScDeleteButtonFromToolbar(pToolButton);
|
|
if (sc)
|
|
goto Cleanup;
|
|
|
|
itBtn = m_vToolbarButtons.erase(itBtn);
|
|
}
|
|
else
|
|
++itBtn;
|
|
}
|
|
|
|
Cleanup:
|
|
// The toolbar client has asked us to remove our reference
|
|
// to it. So even if there is any error encountered we
|
|
// should remove the reference.
|
|
m_mapTBarToBitmapIndex.erase(pNotifyCallbk);
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::ScShow
|
|
//
|
|
// Synopsis: Show/Hide buttons of a toolbar.
|
|
//
|
|
// Arguments: [pNotifyCallbk] - Identifies the toolbar
|
|
// [bShow] - Show/Hide.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CAMCViewToolbars::ScShow (CToolbarNotify* pNotifyCallbk, BOOL bShow)
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCViewToolbars::ScShow"));
|
|
|
|
if (m_bLastActiveView)
|
|
return sc;
|
|
|
|
sc = ScCheckPointers(pNotifyCallbk);
|
|
if (sc)
|
|
return sc;
|
|
|
|
sc = ScCheckPointers(m_pMainToolbar, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Go thro all ToolButtons of this toolbar and hide or show them.
|
|
ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
|
|
for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
|
|
{
|
|
CMMCToolbarButton *pToolButton = itBtn;
|
|
sc = ScCheckPointers(pToolButton, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if ( (pToolButton->GetToolbarNotify() == pNotifyCallbk) &&
|
|
(pToolButton->IsButtonIsAddedToUI()) )
|
|
{
|
|
// Do not show the buttons which should be hidden (TBSTATE_HIDDEN).
|
|
BOOL bHide = (bShow == FALSE) || (pToolButton->GetState() & TBSTATE_HIDDEN);
|
|
|
|
sc = m_pMainToolbar->ScHideButton(pToolButton->GetUniqueCommandID(), bHide);
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
// The toolbar is hidden/shown by customize view dialog.
|
|
SetToolbarStatusHidden(pNotifyCallbk, (FALSE == bShow) );
|
|
|
|
if (bShow)
|
|
m_pMainToolbar->Show(TRUE, true /* insert band in new line*/ );
|
|
else if ( (false == IsThereAVisibleButton()) && // If there is no visible
|
|
(m_pMainToolbar->IsBandVisible()) ) // buttons hide the band.
|
|
m_pMainToolbar->Show(FALSE);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::IsThereAVisibleButton
|
|
//
|
|
// Synopsis: Returns true if there is any visible button. If not
|
|
// the band should be hidden (or removed).
|
|
//
|
|
// Returns: bool
|
|
//
|
|
//--------------------------------------------------------------------
|
|
bool CAMCViewToolbars::IsThereAVisibleButton()
|
|
{
|
|
if (! m_pMainToolbar)
|
|
return false;
|
|
|
|
int cButtons = m_pMainToolbar->GetButtonCount();
|
|
|
|
for (int i = 0; i < cButtons; ++i)
|
|
{
|
|
TBBUTTON tbButton;
|
|
|
|
if (m_pMainToolbar->GetButton(i, &tbButton))
|
|
{
|
|
// If the button is not hidden return true to
|
|
// IsThereAVisibleButton question.
|
|
if ( !(tbButton.fsState & TBSTATE_HIDDEN) )
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::GetToolbarButton
|
|
//
|
|
// Synopsis: Given the command ID return the button object.
|
|
//
|
|
// Arguments: [nCommandID] -
|
|
//
|
|
// Returns: CMMCToolbarButton obj.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
CMMCToolbarButton* CAMCViewToolbars::GetToolbarButton(int nUniqueCommandID)
|
|
{
|
|
ToolbarButtons::iterator itBtns = m_vToolbarButtons.begin();
|
|
|
|
for (; itBtns != m_vToolbarButtons.end(); ++itBtns)
|
|
{
|
|
if ((itBtns)->GetUniqueCommandID() == nUniqueCommandID)
|
|
return (itBtns);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCViewToolbars::GetToolbarButton
|
|
//
|
|
// Synopsis: Search for the button with given toolbar id & command id.
|
|
//
|
|
// Arguments: [idToolbar] -
|
|
// [idCommand] - Command id given by snapin (therfore may not be unique).
|
|
//
|
|
// Returns: the toolbutton object.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
CMMCToolbarButton* CAMCViewToolbars::GetToolbarButton(CToolbarNotify* pNotifyCallbk, int idCommandIDFromSnapin)
|
|
{
|
|
ToolbarButtons::iterator itBtn = m_vToolbarButtons.begin();
|
|
for (;itBtn != m_vToolbarButtons.end(); ++itBtn)
|
|
{
|
|
CMMCToolbarButton* pToolButton = (itBtn);
|
|
if ( (pToolButton->GetToolbarNotify() == pNotifyCallbk) &&
|
|
(pToolButton->GetCommandIDFromSnapin() == idCommandIDFromSnapin) )
|
|
{
|
|
return (pToolButton);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
const int CMMCToolBar::s_nUpdateToolbarSizeMsg =
|
|
RegisterWindowMessage (_T("CMMCToolBar::WM_UpdateToolbarSize"));
|
|
|
|
// Command Ids for buttons must start from 1, since 0 is special case by MFC (BUG:451883)
|
|
// For tooltips the child ids of the control is used. This range is 0x0 to 0xFFFF.
|
|
BEGIN_MESSAGE_MAP(CMMCToolBar, CMMCToolBarCtrlEx)
|
|
ON_COMMAND_RANGE(MMC_TOOLBUTTON_ID_FIRST, MMC_TOOLBUTTON_ID_LAST, OnButtonClicked)
|
|
ON_UPDATE_COMMAND_UI_RANGE(MMC_TOOLBUTTON_ID_FIRST, MMC_TOOLBUTTON_ID_LAST, OnUpdateAllCmdUI)
|
|
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0x0000, 0xFFFF, OnToolTipText)
|
|
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0x0000, 0xFFFF, OnToolTipText)
|
|
ON_REGISTERED_MESSAGE(s_nUpdateToolbarSizeMsg, OnUpdateToolbarSize)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScInit
|
|
//
|
|
// Synopsis: Initialize this toolbar by creating the UI object.
|
|
//
|
|
// Arguments: [pRebar] - The parent rebar where this toolbar should be added.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CMMCToolBar::ScInit(CRebarDockWindow* pRebar)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC (sc, _T("CMMCToolBar::ScInit"));
|
|
sc = ScCheckPointers(pRebar);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Enable tool-tips for the tool-buttons.
|
|
BOOL bRet = Create (NULL, WS_VISIBLE | TBSTYLE_TOOLTIPS, g_rectEmpty, pRebar, ID_TOOLBAR);
|
|
sc = (bRet ? S_OK : E_FAIL);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Set ComCtrl version as 5 to use multiple imagelists.
|
|
LRESULT lOldVer = SendMessage(CCM_SETVERSION, (WPARAM) 5, 0);
|
|
if (lOldVer == -1)
|
|
return (sc = E_FAIL);
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: OnButtonClicked
|
|
//
|
|
// Synopsis: A button of this toolbar is clicked, tell the
|
|
// toolbars manager to notify the client
|
|
// (std toolbar or snapin) about this.
|
|
//
|
|
// Arguments: [nID] - The ID of the button clicked.
|
|
//
|
|
// Returns: None.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void CMMCToolBar::OnButtonClicked(UINT nID)
|
|
{
|
|
DECLARE_SC(sc, _T("CMMCToolBar::OnButtonClicked"));
|
|
|
|
sc = ScCheckPointers(m_pActiveAMCViewToolbars, E_UNEXPECTED);
|
|
if (sc)
|
|
return;
|
|
|
|
// Inform the active view toolbar object about button click.
|
|
sc = m_pActiveAMCViewToolbars->ScButtonClickedNotify(nID);
|
|
if (sc)
|
|
return;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: OnToolTipText
|
|
//
|
|
// Synopsis: Tool-tips are requested for a button. (message handler).
|
|
//
|
|
// Arguments:
|
|
// [nCID] - Not used.
|
|
// [pNMHDR] - Tool-tips for what?
|
|
// [pResult] - tool-tip text.
|
|
//
|
|
// Returns: BOOL.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL CMMCToolBar::OnToolTipText(UINT nCID, NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
|
|
DECLARE_SC(sc, _T("CMMCToolBar::OnToolTipText"));
|
|
|
|
CString strTipText = _T("\n");
|
|
|
|
// need to handle both ANSI and UNICODE versions of the message
|
|
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
|
|
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
|
|
|
|
UINT nID = pNMHDR->idFrom;
|
|
|
|
if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
|
|
pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
|
|
{
|
|
// idFrom is actually the HWND of the tool,
|
|
// this cannot be true since we did not set this.
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
if (nID != 0) // will be zero on a separator // this is the command id, not the button index
|
|
{
|
|
// Ask the active view's CViewToolBarData for tooltip
|
|
// corresponding to toolbar with command-id nID.
|
|
sc = ScCheckPointers(m_pActiveAMCViewToolbars, E_UNEXPECTED);
|
|
if (sc)
|
|
return FALSE;
|
|
|
|
sc = m_pActiveAMCViewToolbars->ScGetToolTip(nID, strTipText);
|
|
|
|
if (sc)
|
|
{
|
|
// No match.
|
|
#ifdef DBG
|
|
strTipText = _T("Unable to get tooltip\nUnable to get tooltip");
|
|
#else
|
|
strTipText = _T("\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Common control provides either TOOLTIPTEXTA or TOOLTIPTEXTW. So MMC needs to
|
|
* provide wide char string or ansi string as tooltip. So below we have two kind
|
|
* of string buffers.
|
|
*
|
|
* Also common control does not free the given string, but it copies the tooltip
|
|
* as soon as this method returns. So we make the strings as static so that we
|
|
* can reuse them.
|
|
*
|
|
* Also see ID: Q180646.
|
|
*/
|
|
static std::string strToolTipTextBuf;
|
|
static std::wstring wstrToolTipTextBuf;
|
|
|
|
USES_CONVERSION;
|
|
|
|
if (pNMHDR->code == TTN_NEEDTEXTA)
|
|
{
|
|
wstrToolTipTextBuf = L"\0";
|
|
ASSERT(pTTTA->hinst == NULL);
|
|
strToolTipTextBuf = T2CA((LPCTSTR)strTipText);
|
|
pTTTA->lpszText = const_cast<LPSTR>(strToolTipTextBuf.data());
|
|
}
|
|
else
|
|
{
|
|
strToolTipTextBuf = "\0";
|
|
ASSERT(pTTTW->hinst == NULL);
|
|
wstrToolTipTextBuf = T2CW((LPCTSTR)strTipText);
|
|
pTTTW->lpszText = const_cast<LPWSTR>(wstrToolTipTextBuf.data());
|
|
}
|
|
|
|
*pResult = 0;
|
|
|
|
return TRUE; // message was handled
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CMMCToolBar::ScOnActivateAMCViewToolbars
|
|
//
|
|
// Synopsis: A cAMCViewToolbars object become the active one (since
|
|
// that objects parent view become active). Cache the
|
|
// object to inform it of toolbutton events.
|
|
//
|
|
// Arguments: [pToolbarsOfView] -
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CMMCToolBar::ScOnActivateAMCViewToolbars (CAMCViewToolbars *pAMCViewToolbars)
|
|
{
|
|
DECLARE_SC(sc, _T("CMMCToolBar::ScOnActivateAMCViewToolbars"));
|
|
sc = ScCheckPointers(pAMCViewToolbars);
|
|
if (sc)
|
|
return sc;
|
|
|
|
m_pActiveAMCViewToolbars = pAMCViewToolbars;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CAMCView::ScOnDeactivateAMCViewToolbars
|
|
//
|
|
// Synopsis: The CAMCViewToolbars object became inactive (as its parent
|
|
// became inactive). Reset the cached active toolbar object.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CMMCToolBar::ScOnDeactivateAMCViewToolbars ()
|
|
{
|
|
DECLARE_SC(sc, _T("CAMCView::ScOnDeactivateAMCViewToolbars"));
|
|
|
|
m_pActiveAMCViewToolbars = NULL;
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CMMCToolBar::ScHideButton
|
|
//
|
|
// Synopsis: Hide or Un-hide a button & update the toolbar
|
|
// separators & size.
|
|
//
|
|
// Arguments: [idCommand] - Command ID of the button to [un]hide.
|
|
// [fHiding] - Hide or Unhide.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
// Note: Do not call this method to hide separators.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CMMCToolBar::ScHideButton (int idCommand, BOOL fHiding)
|
|
{
|
|
AFX_MANAGE_STATE (AfxGetAppModuleState());
|
|
DECLARE_SC(sc, _T("CMMCToolBar::ScHideButton"));
|
|
|
|
int nIndex = CommandToIndex(idCommand);
|
|
|
|
TBBUTTON tbButton;
|
|
BOOL bRet = GetButton(nIndex, &tbButton);
|
|
sc = bRet ? S_OK : E_FAIL;
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Dont call this method to hide separators.
|
|
if (tbButton.fsStyle & TBSTYLE_SEP)
|
|
return (sc = S_FALSE);
|
|
|
|
bRet = HideButton(idCommand, fHiding);
|
|
sc = bRet ? S_OK : E_FAIL;
|
|
if (sc)
|
|
return sc;
|
|
|
|
UpdateSeparators (idCommand, fHiding);
|
|
UpdateToolbarSize(true /* Update Asynch'ly*/);
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: UpdateToolbarSize
|
|
//
|
|
// Synopsis: Update the toobar, needed to lazy update (not update
|
|
// after adding each button, cache all the buttons) of
|
|
// toolbar size.
|
|
//
|
|
// Arguments: [bAsync] - Asynchronous or Synch update.
|
|
//
|
|
// Returns: void
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void CMMCToolBar::UpdateToolbarSize(bool bAsync)
|
|
{
|
|
MSG msg;
|
|
|
|
HWND hWnd = m_hWnd;
|
|
|
|
if (!bAsync)
|
|
CToolBarCtrlEx::UpdateToolbarSize();
|
|
else if (!PeekMessage (&msg, m_hWnd, s_nUpdateToolbarSizeMsg, s_nUpdateToolbarSizeMsg, PM_NOREMOVE))
|
|
::PostMessage (m_hWnd, s_nUpdateToolbarSizeMsg, 0, 0);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: OnUpdateToolbarSize
|
|
//
|
|
// Synopsis: Our registered message handler.
|
|
//
|
|
// Arguments: None used.
|
|
//
|
|
// Returns: LRESULT
|
|
//
|
|
//--------------------------------------------------------------------
|
|
LRESULT CMMCToolBar::OnUpdateToolbarSize(WPARAM , LPARAM)
|
|
{
|
|
CToolBarCtrlEx::UpdateToolbarSize();
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*
|
|
* CMMCToolBar::UpdateSeparators
|
|
*
|
|
* The legend for the comments below is:
|
|
*
|
|
* L = left edge
|
|
* R = right edge
|
|
* * = target button
|
|
* B = visible non-separator
|
|
* b = hidden non-separator
|
|
* S = visible separator
|
|
* s = hidden separator
|
|
* h = 0 or more hidden buttons, separator or non-separator
|
|
*--------------------------------------------------------------------------*/
|
|
void CMMCToolBar::UpdateSeparators (int idCommand, BOOL fHiding)
|
|
{
|
|
int nButtonIndex = CommandToIndex (idCommand);
|
|
|
|
if (nButtonIndex == -1)
|
|
return;
|
|
|
|
int nLeftVisible;
|
|
int nRightVisible;
|
|
int cButtons = GetButtonCount ();
|
|
|
|
/*
|
|
* If the button is being hidden, turn off any separators
|
|
* that are now redundant. There are three situations where
|
|
* we'll need to turn off a separator (see legend above):
|
|
*
|
|
* 1. Lh*hS
|
|
* 2. Sh*hS
|
|
* 3. Sh*hR
|
|
*
|
|
* These situations are mutually exclusive.
|
|
*/
|
|
if (fHiding)
|
|
{
|
|
TBBUTTON btnLeft;
|
|
TBBUTTON btnRight;
|
|
|
|
/*
|
|
* look to the left of the button being hidden for the
|
|
* left edge or a visible button
|
|
*/
|
|
for (nLeftVisible = nButtonIndex-1; nLeftVisible >= 0; nLeftVisible--)
|
|
{
|
|
GetButton (nLeftVisible, &btnLeft);
|
|
|
|
if (!(btnLeft.fsState & TBSTATE_HIDDEN))
|
|
break;
|
|
}
|
|
ASSERT (nLeftVisible < nButtonIndex);
|
|
ASSERT (nLeftVisible >= -1);
|
|
|
|
|
|
/*
|
|
* look to the right of the button being hidden for the
|
|
* right edge or a visible separator
|
|
*/
|
|
for (nRightVisible = nButtonIndex+1; nRightVisible < cButtons; nRightVisible++)
|
|
{
|
|
GetButton (nRightVisible, &btnRight);
|
|
|
|
if (!(btnRight.fsState & TBSTATE_HIDDEN))
|
|
break;
|
|
}
|
|
ASSERT (nRightVisible > nButtonIndex);
|
|
ASSERT (nRightVisible <= cButtons);
|
|
|
|
|
|
/*
|
|
* case 1: Lh*hS
|
|
*/
|
|
if ((nLeftVisible == -1) &&
|
|
(nRightVisible != cButtons) &&
|
|
(btnRight.fsStyle & TBSTYLE_SEP))
|
|
HideButton (btnRight.idCommand, true);
|
|
|
|
/*
|
|
* case 2: Sh*hS
|
|
*/
|
|
else if ((nLeftVisible != -1) &&
|
|
(nRightVisible != cButtons) &&
|
|
(btnLeft.fsStyle & TBSTYLE_SEP) &&
|
|
(btnRight.fsStyle & TBSTYLE_SEP))
|
|
HideButton (btnRight.idCommand, true);
|
|
|
|
/*
|
|
* case 3: Sh*hR
|
|
*/
|
|
else if ((nLeftVisible != -1) &&
|
|
(nRightVisible == cButtons) &&
|
|
(btnLeft.fsStyle & TBSTYLE_SEP))
|
|
HideButton (btnLeft.idCommand, true);
|
|
}
|
|
|
|
/*
|
|
* Otherwise, the button is being shown; turn on any separators
|
|
* that are no longer redundant. There are two situations where
|
|
* we'll need to turn on a separator (see legend above):
|
|
*
|
|
* 1. Bhsh*
|
|
* 2. *hshB
|
|
*
|
|
* Both 1 and 2 can occur simultaneously.
|
|
*/
|
|
else do // not a loop
|
|
{
|
|
TBBUTTON btn;
|
|
|
|
/*
|
|
* look to the left of the button being shown for the
|
|
* left edge or a visible button
|
|
*/
|
|
int idLeftSeparatorCommand = -1;
|
|
for (nLeftVisible = nButtonIndex-1; nLeftVisible >= 0; nLeftVisible--)
|
|
{
|
|
GetButton (nLeftVisible, &btn);
|
|
|
|
if (btn.fsStyle & TBSTYLE_SEP)
|
|
idLeftSeparatorCommand = btn.idCommand;
|
|
|
|
if (!(btn.fsState & TBSTATE_HIDDEN))
|
|
break;
|
|
}
|
|
ASSERT (nLeftVisible < nButtonIndex);
|
|
ASSERT (nLeftVisible >= -1);
|
|
|
|
|
|
/*
|
|
* look to the right of the button being shown for the
|
|
* right edge or a hidden separator
|
|
*/
|
|
int idRightSeparatorCommand = -1;
|
|
for (nRightVisible = nButtonIndex+1; nRightVisible < cButtons; nRightVisible++)
|
|
{
|
|
GetButton (nRightVisible, &btn);
|
|
|
|
if (btn.fsStyle & TBSTYLE_SEP)
|
|
idRightSeparatorCommand = btn.idCommand;
|
|
|
|
if (!(btn.fsState & TBSTATE_HIDDEN))
|
|
break;
|
|
}
|
|
ASSERT (nRightVisible > nButtonIndex);
|
|
ASSERT (nRightVisible <= cButtons);
|
|
|
|
|
|
/*
|
|
* case 1: Bhsh*
|
|
*/
|
|
if ((nLeftVisible != -1) && (idLeftSeparatorCommand != -1))
|
|
HideButton (idLeftSeparatorCommand, false);
|
|
|
|
/*
|
|
* case 2: *hshB
|
|
*/
|
|
if ((nRightVisible != cButtons) && (idRightSeparatorCommand != -1))
|
|
HideButton (idRightSeparatorCommand, false);
|
|
|
|
} while (0);
|
|
}
|
|
|
|
|
|
|