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.
1393 lines
38 KiB
1393 lines
38 KiB
//____________________________________________________________________________
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: ctrlbar.cpp
|
|
//
|
|
// Contents:
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History:
|
|
//____________________________________________________________________________
|
|
//
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "menubtn.h"
|
|
#include "viewdata.h"
|
|
#include "amcmsgid.h"
|
|
#include "regutil.h"
|
|
|
|
#include "commctrl.h"
|
|
#include "multisel.h"
|
|
#include "rsltitem.h"
|
|
#include "conview.h"
|
|
#include "util.h"
|
|
#include "nodemgrdebug.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
// Snapin name needed for debug information.
|
|
inline void Debug_SetControlbarSnapinName(const CLSID& clsidSnapin, CControlbar* pControlbar)
|
|
{
|
|
#ifdef DBG
|
|
tstring tszSnapinName;
|
|
bool bRet = GetSnapinNameFromCLSID(clsidSnapin, tszSnapinName);
|
|
if (bRet)
|
|
pControlbar->SetSnapinName(tszSnapinName.data());
|
|
#endif
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// IControlbar implementation
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(CControlbar);
|
|
|
|
CControlbar::CControlbar()
|
|
: m_pCache(NULL)
|
|
{
|
|
TRACE(_T("CControlbar::CControlbar()\n"));
|
|
DEBUG_INCREMENT_INSTANCE_COUNTER(CControlbar);
|
|
m_pMenuButton=NULL;
|
|
m_ToolbarsList.clear();
|
|
|
|
#ifdef DBG
|
|
dbg_cRef = 0;
|
|
#endif
|
|
}
|
|
|
|
CControlbar::~CControlbar()
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::~CControlbar"));
|
|
DEBUG_DECREMENT_INSTANCE_COUNTER(CControlbar);
|
|
|
|
// Remove the toolbars & menubuttons references.
|
|
sc = ScCleanup();
|
|
// sc dtor will trace error if there is one.
|
|
|
|
// release reference prior to m_ToolbarsList destruction
|
|
// The destructor of CToolbar will try to remove itself from the list!
|
|
m_spExtendControlbar = NULL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: Create
|
|
//
|
|
// Synopsis: Create a toolbar or menubutton object
|
|
//
|
|
// Arguments:
|
|
// [nType] - Type of object to be created (Toolbar or Menubutton).
|
|
// [pExtendControlbar] - IExtendControlbar associated with this IControlbar.
|
|
// [ppUnknown] - IUnknown* of the object created.
|
|
//
|
|
// Returns: HR
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP CControlbar::Create(MMC_CONTROL_TYPE nType,
|
|
LPEXTENDCONTROLBAR pExtendControlbar,
|
|
LPUNKNOWN* ppUnknown)
|
|
{
|
|
DECLARE_SC_FOR_PUBLIC_INTERFACE(sc, _T("IControlbar::Create"));
|
|
|
|
if (ppUnknown == NULL || pExtendControlbar == NULL)
|
|
{
|
|
sc = E_INVALIDARG;
|
|
TraceSnapinError(_T("Invalid Arguments"), sc);
|
|
return sc.ToHr();
|
|
}
|
|
|
|
*ppUnknown = NULL;
|
|
|
|
switch (nType)
|
|
{
|
|
case TOOLBAR:
|
|
sc = ScCreateToolbar(pExtendControlbar, ppUnknown);
|
|
break;
|
|
|
|
case MENUBUTTON:
|
|
sc = ScCreateMenuButton(pExtendControlbar, ppUnknown);
|
|
break;
|
|
default:
|
|
sc = E_NOTIMPL;
|
|
break;
|
|
}
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
return (sc.ToHr());
|
|
}
|
|
|
|
|
|
HRESULT CControlbar::ControlbarNotify(MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
|
|
{
|
|
ASSERT(m_spExtendControlbar != NULL);
|
|
if (m_spExtendControlbar == NULL)
|
|
return E_FAIL;
|
|
|
|
HRESULT hr;
|
|
|
|
// Deactivate if theming (fusion or V6 common-control) context before calling snapins.
|
|
ULONG_PTR ulpCookie;
|
|
if (! MmcDownlevelActivateActCtx(NULL, &ulpCookie))
|
|
return E_FAIL;
|
|
|
|
__try
|
|
{
|
|
hr = m_spExtendControlbar->ControlbarNotify(event, arg, param);
|
|
MmcDownlevelDeactivateActCtx(0, ulpCookie);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_FAIL;
|
|
TraceSnapinException(m_clsidSnapin, TEXT("IExtendControlbar::ControlbarNotify"), event);
|
|
MmcDownlevelDeactivateActCtx(0, ulpCookie);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: Attach
|
|
//
|
|
// Synopsis: Attach given toolbar or menubutton object
|
|
//
|
|
// Arguments:
|
|
// [nType] - Toolbar or Menubutton.
|
|
// [lpUnknown] - IUnknown* of the object to be attached.
|
|
//
|
|
// Returns: HR
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP CControlbar::Attach(MMC_CONTROL_TYPE nType, LPUNKNOWN lpUnknown)
|
|
{
|
|
DECLARE_SC_FOR_PUBLIC_INTERFACE(sc, _T("IControlbar::Attach"));
|
|
|
|
if (lpUnknown == NULL)
|
|
{
|
|
sc = E_INVALIDARG;
|
|
TraceSnapinError(_T("Invalid Arguments"), sc);
|
|
return sc.ToHr();
|
|
}
|
|
|
|
switch (nType)
|
|
{
|
|
case TOOLBAR:
|
|
sc = ScAttachToolbar(lpUnknown);
|
|
break;
|
|
case MENUBUTTON:
|
|
sc = ScAttachMenuButtons(lpUnknown);
|
|
break;
|
|
case COMBOBOXBAR:
|
|
sc = E_NOTIMPL;
|
|
break;
|
|
}
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
return (sc.ToHr());
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: Detach
|
|
//
|
|
// Synopsis: Detach given toolbar or menubutton object
|
|
//
|
|
// Arguments: [lpUnknown] - IUnknown* of the object to be detached
|
|
//
|
|
// Returns: HR
|
|
//
|
|
//--------------------------------------------------------------------
|
|
STDMETHODIMP CControlbar::Detach(LPUNKNOWN lpUnknown)
|
|
{
|
|
DECLARE_SC_FOR_PUBLIC_INTERFACE(sc, _T("IControlbar::Detach"));
|
|
|
|
if (lpUnknown == NULL)
|
|
{
|
|
sc = E_INVALIDARG;
|
|
TraceSnapinError(_T("Invalid Arguments"), sc);
|
|
return sc.ToHr();
|
|
}
|
|
|
|
// Is it a toolbar
|
|
IToolbarPtr spToolbar = lpUnknown;
|
|
if (spToolbar != NULL)
|
|
{
|
|
sc = ScDetachToolbar(spToolbar);
|
|
return sc.ToHr();
|
|
}
|
|
|
|
// Is it a menu button
|
|
IMenuButtonPtr spMenuButton = lpUnknown;
|
|
if (spMenuButton != NULL)
|
|
{
|
|
sc = ScDetachMenuButton(spMenuButton);
|
|
return sc.ToHr();
|
|
}
|
|
|
|
|
|
// The passed lpUnknown is neither toolbar nor menubutton.
|
|
// The Snapin has passed invalid object.
|
|
sc = E_INVALIDARG;
|
|
TraceSnapinError(_T("lpUnknown passed is neither toolbar nor menubutton"), sc);
|
|
|
|
return sc.ToHr();
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScDetachToolbar
|
|
//
|
|
// Synopsis: Detach given toolbar object
|
|
//
|
|
// Arguments: [lpToolbar] - IToolbar* of the object to be detached
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScDetachToolbar(LPTOOLBAR lpToolbar)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::SCDetachToolbar"));
|
|
|
|
if (NULL == lpToolbar)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Get the CToolbar object.
|
|
CToolbar* pToolbar = dynamic_cast<CToolbar*>(lpToolbar);
|
|
if (NULL == pToolbar)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Get the CMMCToolbarIntf interface.
|
|
CMMCToolbarIntf* pToolbarIntf = pToolbar->GetMMCToolbarIntf();
|
|
if (NULL == pToolbarIntf)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Detach the toolbar from UI.
|
|
sc = pToolbarIntf->ScDetach(pToolbar);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Remove the CControlbar reference.
|
|
pToolbar->SetControlbar(NULL);
|
|
|
|
// Remove the reference to the toolbar.
|
|
m_ToolbarsList.remove(pToolbar);
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScDetachMenuButton
|
|
//
|
|
// Synopsis: Detach given toolbar or menubutton object
|
|
//
|
|
// Arguments: [lpUnknown] - IUnknown* of the object to be detached
|
|
//
|
|
// Returns: HR
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScDetachMenuButton(LPMENUBUTTON lpMenuButton)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScDetachMenuButton"));
|
|
|
|
if (NULL == lpMenuButton)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
CMenuButton* pMenuButton = dynamic_cast<CMenuButton*>(lpMenuButton);
|
|
if (NULL == pMenuButton)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
sc = pMenuButton->ScDetach();
|
|
if (sc)
|
|
return sc;
|
|
|
|
// If this is same as the cached menubutton object
|
|
// then remove the (cached) ref.
|
|
if (m_pMenuButton == pMenuButton)
|
|
m_pMenuButton = NULL;
|
|
else
|
|
{
|
|
// The IControlbar implementation is supposed to
|
|
// have only one CMenuButton obj. How come it is
|
|
// not same as one we have cached.
|
|
sc = E_UNEXPECTED;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScCreateToolbar
|
|
//
|
|
// Synopsis: Create a toolbar for the given snapin (IExtendControlbar).
|
|
//
|
|
// Arguments: [pExtendControlbar] - IExtendControlbar of the snapin.
|
|
// [ppUnknown] - IUnknown* (IToolbar) of created toolbar.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScCreateToolbar(LPEXTENDCONTROLBAR pExtendControlbar,
|
|
LPUNKNOWN* ppUnknown)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScCreateToolbar"));
|
|
|
|
if ( (NULL == pExtendControlbar) ||
|
|
(NULL == ppUnknown) )
|
|
return (sc = E_INVALIDARG);
|
|
|
|
ASSERT(m_spExtendControlbar == NULL ||
|
|
m_spExtendControlbar == pExtendControlbar);
|
|
|
|
// Create the new CToolbar object.
|
|
CComObject<CToolbar>* pToolbar = NULL;
|
|
sc = CComObject<CToolbar>::CreateInstance(&pToolbar);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if (NULL == pToolbar)
|
|
return (sc = E_FAIL);
|
|
|
|
sc = pToolbar->QueryInterface(IID_IToolbar,
|
|
reinterpret_cast<void**>(ppUnknown));
|
|
if (sc)
|
|
return sc;
|
|
|
|
CMMCToolbarIntf* pToolbarIntf = NULL;
|
|
|
|
// Get the toolbars mgr.
|
|
CAMCViewToolbarsMgr* pAMCViewToolbarsMgr = GetAMCViewToolbarsMgr();
|
|
if (NULL == pAMCViewToolbarsMgr)
|
|
{
|
|
sc = E_UNEXPECTED;
|
|
goto ToolbarUICreateError;
|
|
}
|
|
|
|
// Ask it to create the toolbar UI.
|
|
sc = pAMCViewToolbarsMgr->ScCreateToolBar(&pToolbarIntf);
|
|
if (sc)
|
|
goto ToolbarUICreateError;
|
|
|
|
// Let the IToolbar imp be aware of toolbar UI interface.
|
|
pToolbar->SetMMCToolbarIntf(pToolbarIntf);
|
|
|
|
Cleanup:
|
|
return(sc);
|
|
|
|
ToolbarUICreateError:
|
|
// Destroy the CToolbar object created.
|
|
if (*ppUnknown)
|
|
(*ppUnknown)->Release();
|
|
|
|
*ppUnknown = NULL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScCreateMenuButton
|
|
//
|
|
// Synopsis: Create a menu button object.
|
|
//
|
|
// Arguments: [pExtendControlbar] - IExtendControlbar of the snapin
|
|
// that is creating MenuButton object.
|
|
// [ppUnknown] - IUnknown if MenuButton object.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScCreateMenuButton(LPEXTENDCONTROLBAR pExtendControlbar,
|
|
LPUNKNOWN* ppUnknown)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScCreateMenuButton"));
|
|
|
|
if ( (NULL == pExtendControlbar) ||
|
|
(NULL == ppUnknown) )
|
|
return (sc = E_INVALIDARG);
|
|
|
|
ASSERT(m_spExtendControlbar == NULL ||
|
|
m_spExtendControlbar == pExtendControlbar);
|
|
|
|
// Create the new IMenuButton object
|
|
CComObject<CMenuButton>* pMenuButton;
|
|
sc = CComObject<CMenuButton>::CreateInstance(&pMenuButton);
|
|
if (sc)
|
|
return sc;
|
|
|
|
if (NULL == pMenuButton)
|
|
return (sc = E_FAIL);
|
|
|
|
sc = pMenuButton->QueryInterface(IID_IMenuButton,
|
|
reinterpret_cast<void**>(ppUnknown));
|
|
|
|
if (sc)
|
|
return sc;
|
|
|
|
pMenuButton->SetControlbar(this);
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScNotifySnapinOfToolBtnClick
|
|
//
|
|
// Synopsis: Notify the snapin about a tool button is click.
|
|
//
|
|
// Arguments: [hNode] - Node that owns result pane.
|
|
// [bScopePane] - Scope or Result.
|
|
// [lResultItemCookie] - If Result pane is selected the item param.
|
|
// [nID] - Command ID of the tool button clicked.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScNotifySnapinOfToolBtnClick(HNODE hNode, bool bScopePane,
|
|
LPARAM lResultItemCookie,
|
|
UINT nID)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScNotifySnapinOfToolBtnClick"));
|
|
|
|
LPDATAOBJECT pDataObject = NULL;
|
|
CNode* pNode = CNode::FromHandle(hNode);
|
|
if (NULL == pNode)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
bool bScopeItem = bScopePane;
|
|
// Get the data object of the currently selected item.
|
|
sc = pNode->ScGetDataObject(bScopePane, lResultItemCookie, bScopeItem, &pDataObject);
|
|
if (sc)
|
|
return sc;
|
|
|
|
ASSERT(m_spExtendControlbar != NULL);
|
|
|
|
// Notify the snapin
|
|
sc = ControlbarNotify(MMCN_BTN_CLICK, reinterpret_cast<LPARAM>(pDataObject),
|
|
static_cast<LPARAM>(nID));
|
|
|
|
// Release the dataobject if it is not special dataobject.
|
|
RELEASE_DATAOBJECT(pDataObject);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScNotifySnapinOfMenuBtnClick
|
|
//
|
|
// Synopsis: Notify the snapin about a menu button is click.
|
|
//
|
|
// Arguments: [hNode] - Node that owns result pane.
|
|
// [bScopePane] - Scope or Result.
|
|
// [lResultItemCookie] - If Result pane is selected the item param.
|
|
// [lpmenuButtonData] - MENUBUTTONDATA
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScNotifySnapinOfMenuBtnClick(HNODE hNode, bool bScopePane,
|
|
LPARAM lResultItemCookie,
|
|
LPMENUBUTTONDATA lpmenuButtonData)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScNotifySnapinOfMenuBtnClick"));
|
|
|
|
LPDATAOBJECT pDataObject = NULL;
|
|
CNode* pNode = CNode::FromHandle(hNode);
|
|
if (NULL == pNode)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
bool bScopeItem = bScopePane;
|
|
// Get the data object of the currently selected item.
|
|
sc = pNode->ScGetDataObject(bScopePane, lResultItemCookie, bScopeItem, &pDataObject);
|
|
if (sc)
|
|
return sc;
|
|
|
|
ASSERT(m_spExtendControlbar != NULL);
|
|
|
|
// Notify the snapin
|
|
sc = ControlbarNotify(MMCN_MENU_BTNCLICK, reinterpret_cast<LPARAM>(pDataObject),
|
|
reinterpret_cast<LPARAM>(lpmenuButtonData));
|
|
|
|
// Release the dataobject if it is not special dataobject.
|
|
RELEASE_DATAOBJECT(pDataObject);
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScAttachToolbar
|
|
//
|
|
// Synopsis: Attach given toolbar object
|
|
//
|
|
// Arguments: [lpUnknown] - IUnknown* of the object to be attached
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScAttachToolbar(LPUNKNOWN lpUnknown)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScAttachToolbar"));
|
|
|
|
ASSERT(NULL != lpUnknown);
|
|
|
|
IToolbarPtr spToolbar = lpUnknown;
|
|
if (NULL == spToolbar)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Get the toolbar object (IToolbar implementation).
|
|
CToolbar* pToolbarC = dynamic_cast<CToolbar*>(spToolbar.GetInterfacePtr());
|
|
if (NULL == pToolbarC)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Get the toolbar UI interface.
|
|
CMMCToolbarIntf* pToolbarIntf = pToolbarC->GetMMCToolbarIntf();
|
|
if (NULL == pToolbarIntf)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Attach the toolbar.
|
|
sc = pToolbarIntf->ScAttach(pToolbarC);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Make the CToolbar aware of this IControlbar.
|
|
pToolbarC->SetControlbar(this);
|
|
|
|
// Add this CToolbar to our list of toolbars.
|
|
ToolbarsList::iterator itToolbar = std::find(m_ToolbarsList.begin(), m_ToolbarsList.end(), pToolbarC);
|
|
if (m_ToolbarsList.end() == itToolbar)
|
|
{
|
|
m_ToolbarsList.push_back(pToolbarC);
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScAttachMenuButtons
|
|
//
|
|
// Synopsis: Attach a menu button object.
|
|
//
|
|
// Arguments: [lpUnknown] - IUnknown if MenuButton object.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// Note: Only one CMenuButton object per Controlbar/snapin.
|
|
// Snapins can create many menu buttons using a
|
|
// single CMenuButton object.
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScAttachMenuButtons(LPUNKNOWN lpUnknown)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScAttachMenuButtons"));
|
|
|
|
ASSERT(NULL != lpUnknown);
|
|
|
|
CMenuButton* pMenuButton = dynamic_cast<CMenuButton*>(lpUnknown);
|
|
if (pMenuButton == NULL)
|
|
return (sc = E_INVALIDARG);
|
|
|
|
if (m_pMenuButton == pMenuButton)
|
|
{
|
|
// Already attached.
|
|
sc = S_FALSE;
|
|
TraceNodeMgrLegacy(_T("The menubutton is already attached"), sc);
|
|
return sc;
|
|
}
|
|
else if (m_pMenuButton != NULL)
|
|
{
|
|
// There is already a CMenuButton object attached by this
|
|
// Controlbar (Snapin). Detach that before attaching this
|
|
// CMenuButton Object (See the note above).
|
|
sc = m_pMenuButton->ScDetach();
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
|
|
// Cache the ref to CMenuButton object.
|
|
// Used when selection moves away from the snapin.
|
|
// MMC has to remove the menubutton put by this snapin.
|
|
m_pMenuButton = pMenuButton;
|
|
|
|
if (pMenuButton->GetControlbar() != this)
|
|
pMenuButton->SetControlbar(this);
|
|
|
|
sc = pMenuButton->ScAttach();
|
|
if (sc)
|
|
return sc;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScCleanup
|
|
//
|
|
// Synopsis: Remove all the toolbars and menu buttons owned
|
|
// by this controlbar.
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScCleanup()
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScCleanup"));
|
|
|
|
ASSERT(m_spExtendControlbar != NULL);
|
|
if (m_spExtendControlbar != NULL)
|
|
m_spExtendControlbar->SetControlbar(NULL);
|
|
|
|
sc = ScDetachToolbars();
|
|
if (sc)
|
|
return sc;
|
|
|
|
// If there is a menu button, detach (remove it
|
|
// from the UI).
|
|
if (m_pMenuButton)
|
|
{
|
|
sc = m_pMenuButton->ScDetach();
|
|
m_pMenuButton = NULL;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScDetachToolbars
|
|
//
|
|
// Synopsis: Detach all the toolbars.
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScDetachToolbars()
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScDetachToolbars"));
|
|
|
|
ToolbarsList::iterator itToolbar = m_ToolbarsList.begin();
|
|
while (itToolbar != m_ToolbarsList.end())
|
|
{
|
|
CToolbar* pToolbar = (*itToolbar);
|
|
if (NULL == pToolbar)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
CMMCToolbarIntf* pToolbarIntf = pToolbar->GetMMCToolbarIntf();
|
|
if (NULL == pToolbarIntf)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
// Detach the toolbar UI.
|
|
sc = pToolbarIntf->ScDetach(pToolbar);
|
|
if (sc)
|
|
return sc;
|
|
|
|
// Detach the controlbar from toolbar.
|
|
pToolbar->SetControlbar(NULL);
|
|
|
|
// Remove the toolbar reference from the list.
|
|
itToolbar = m_ToolbarsList.erase(itToolbar);
|
|
}
|
|
|
|
return (sc);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScShowToolbars
|
|
//
|
|
// Synopsis: Show/Hide all the toolbars.
|
|
//
|
|
// Arguments: [bool] - Show or Hide.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CControlbar::ScShowToolbars(bool bShow)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbar::ScShowToolbars"));
|
|
|
|
ToolbarsList::iterator itToolbar = m_ToolbarsList.begin();
|
|
for (; itToolbar != m_ToolbarsList.end(); ++itToolbar)
|
|
{
|
|
CToolbar* pToolbar = (*itToolbar);
|
|
if (NULL == pToolbar)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
CMMCToolbarIntf* pToolbarIntf = pToolbar->GetMMCToolbarIntf();
|
|
if (NULL == pToolbarIntf)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
sc = pToolbarIntf->ScShow(pToolbar, bShow);
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
CViewData* CControlbar::GetViewData()
|
|
{
|
|
ASSERT(m_pCache != NULL);
|
|
return m_pCache->GetViewData();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CSelData implementation
|
|
//
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(CSelData);
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScReset
|
|
//
|
|
// Synopsis: Init all the data members.
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CSelData::ScReset()
|
|
{
|
|
DECLARE_SC(sc, _T("CSelData::ScReset"));
|
|
|
|
if (m_pCtrlbarPrimary != NULL)
|
|
{
|
|
sc = ScDestroyPrimaryCtrlbar();
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
|
|
sc = ScDestroyExtensionCtrlbars();
|
|
if (sc)
|
|
return sc;
|
|
|
|
m_bScopeSel = false;
|
|
m_bSelect = false;
|
|
m_pNodeScope = NULL;
|
|
m_pMS = NULL;
|
|
m_pCtrlbarPrimary = NULL;
|
|
m_lCookie = -1;
|
|
m_pCompPrimary = NULL;
|
|
m_spDataObject = NULL;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScShowToolbars
|
|
//
|
|
// Synopsis: Show/Hide primary & extension toolbars.
|
|
//
|
|
// Arguments: [bool] - Show/Hide.
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CSelData::ScShowToolbars(bool bShow)
|
|
{
|
|
DECLARE_SC(sc, _T("CSelData::ScShowToolbars"));
|
|
|
|
if (m_pCtrlbarPrimary != NULL)
|
|
{
|
|
sc = m_pCtrlbarPrimary->ScShowToolbars(bShow);
|
|
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
|
|
POSITION pos = m_listExtCBs.GetHeadPosition();
|
|
bool bReturn = true;
|
|
while (pos != NULL)
|
|
{
|
|
CControlbar* pControlbar = m_listExtCBs.GetNext(pos);
|
|
if (pControlbar)
|
|
{
|
|
sc = pControlbar->ScShowToolbars(bShow);
|
|
if (sc)
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
CControlbar* CSelData::GetControlbar(const CLSID& clsidSnapin)
|
|
{
|
|
POSITION pos = m_listExtCBs.GetHeadPosition();
|
|
while (pos)
|
|
{
|
|
CControlbar* pControlbar = m_listExtCBs.GetNext(pos);
|
|
if (pControlbar && pControlbar->IsSameSnapin(clsidSnapin) == TRUE)
|
|
return pControlbar;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScDestroyPrimaryCtrlbar
|
|
//
|
|
// Synopsis: Ask primary controlbar to release its toolbar/menubutton
|
|
// ref and cleanup our reference to the controlbar.
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CSelData::ScDestroyPrimaryCtrlbar()
|
|
{
|
|
DECLARE_SC(sc, _T("CSelData::ScDestroyPrimaryCtrlbar"));
|
|
|
|
if (NULL == m_pCtrlbarPrimary)
|
|
return (sc = E_UNEXPECTED);
|
|
|
|
sc = m_pCtrlbarPrimary->ScCleanup();
|
|
if (sc)
|
|
return sc;
|
|
|
|
/*
|
|
* In CreateControlbar we had a ref on IControlbar
|
|
* (detaching smart ptr). Let us now undo that ref.
|
|
*/
|
|
m_pCtrlbarPrimary->Release();
|
|
m_pCtrlbarPrimary = NULL;
|
|
|
|
return sc;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: ScDestroyExtensionCtrlbars
|
|
//
|
|
// Synopsis: Ask extension controlbars to release their toolbar/menubutton
|
|
// ref and cleanup our reference to the controlbars.
|
|
//
|
|
// Arguments: None
|
|
//
|
|
// Returns: SC
|
|
//
|
|
//--------------------------------------------------------------------
|
|
SC CSelData::ScDestroyExtensionCtrlbars()
|
|
{
|
|
DECLARE_SC(sc, _T("CSelData::ScDestroyExtensionCtrlbars"));
|
|
|
|
POSITION pos = m_listExtCBs.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CControlbar* pControlbar = m_listExtCBs.GetNext(pos);
|
|
if (pControlbar)
|
|
{
|
|
sc = pControlbar->ScCleanup();
|
|
if (sc)
|
|
return sc;
|
|
|
|
/*
|
|
* In CreateControlbar we had a ref on IControlbar
|
|
* (detaching smart ptr). Let us now undo that ref.
|
|
*/
|
|
pControlbar->Release();
|
|
}
|
|
}
|
|
|
|
m_listExtCBs.RemoveAll();
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CControlbarsCache implementation
|
|
//
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(CControlbarsCache);
|
|
|
|
|
|
void CControlbarsCache::SetViewData(CViewData* pViewData)
|
|
{
|
|
ASSERT(pViewData != 0);
|
|
m_pViewData = pViewData;
|
|
}
|
|
|
|
CViewData* CControlbarsCache::GetViewData()
|
|
{
|
|
ASSERT(m_pViewData != NULL);
|
|
return m_pViewData;
|
|
}
|
|
|
|
|
|
CControlbar* CControlbarsCache::CreateControlbar(IExtendControlbarPtr& spECB,
|
|
const CLSID& clsidSnapin)
|
|
{
|
|
DECLARE_SC(sc, _T("CControlbarsCache::CreateControlbar"));
|
|
|
|
CComObject<CControlbar>* pControlbar;
|
|
sc = CComObject<CControlbar>::CreateInstance(&pControlbar);
|
|
if (sc)
|
|
return NULL;
|
|
|
|
IControlbarPtr spControlbar = pControlbar;
|
|
if (NULL == spControlbar)
|
|
{
|
|
ASSERT(NULL != pControlbar); // QI fails but object is created how?
|
|
sc = E_UNEXPECTED;
|
|
return NULL;
|
|
}
|
|
|
|
pControlbar->SetCache(this);
|
|
pControlbar->SetExtendControlbar(spECB, clsidSnapin);
|
|
|
|
sc = spECB->SetControlbar(spControlbar);
|
|
if (sc)
|
|
return NULL; // spControlbar smart ptr (object will be destroyed).
|
|
|
|
// Snapin must return S_OK to be valid
|
|
if (S_OK == sc.ToHr())
|
|
{
|
|
// Detach, thus hold a ref count on the Controlbar object
|
|
// CSelData holds this reference & releases the ref in
|
|
// ScDestroyPrimaryCtrlbar() or ScDestroyExtensionCtrlbars().
|
|
spControlbar.Detach();
|
|
|
|
// This is for debug info.
|
|
Debug_SetControlbarSnapinName(clsidSnapin, pControlbar);
|
|
|
|
return pControlbar;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CControlbarsCache::OnMultiSelect(
|
|
CNode* pNodeScope,
|
|
CMultiSelection* pMultiSelection,
|
|
IDataObject* pDOMultiSel,
|
|
BOOL bSelect)
|
|
{
|
|
ASSERT(pNodeScope != NULL);
|
|
ASSERT(pMultiSelection != NULL);
|
|
ASSERT(pDOMultiSel != NULL);
|
|
if (pNodeScope == NULL || pMultiSelection == NULL || pDOMultiSel == NULL)
|
|
return E_FAIL;
|
|
|
|
CSelData selData(false, (bool)bSelect);
|
|
selData.m_pMS = pMultiSelection;
|
|
|
|
if (selData == m_SelData)
|
|
return S_FALSE;
|
|
|
|
if (!bSelect)
|
|
return _OnDeSelect(selData);
|
|
|
|
selData.m_pCompPrimary = pMultiSelection->GetPrimarySnapinComponent();
|
|
|
|
CList<GUID, GUID&> extnSnapins;
|
|
HRESULT hr = pMultiSelection->GetExtensionSnapins(g_szToolbar, extnSnapins);
|
|
CHECK_HRESULT(hr);
|
|
|
|
selData.m_spDataObject.Attach(pDOMultiSel, TRUE);
|
|
return _ProcessSelection(selData, extnSnapins);
|
|
}
|
|
|
|
HRESULT
|
|
CControlbarsCache::OnResultSelChange(
|
|
CNode* pNode,
|
|
MMC_COOKIE cookie,
|
|
BOOL bSelected)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CControlbarsCache::OnResultSelChange"));
|
|
|
|
sc = ScCheckPointers (pNode);
|
|
if (sc)
|
|
return (sc.ToHr());
|
|
|
|
CSelData selData(false, (bool)bSelected);
|
|
selData.m_lCookie = cookie;
|
|
|
|
if (selData == m_SelData)
|
|
return (sc = S_FALSE).ToHr();
|
|
|
|
if (!bSelected)
|
|
{
|
|
sc = _OnDeSelect(selData);
|
|
return sc.ToHr();
|
|
}
|
|
|
|
IDataObjectPtr spDataObject = NULL;
|
|
CComponent* pCCResultItem = NULL;
|
|
CList<CLSID, CLSID&> extnSnapins;
|
|
|
|
BOOL bListPadItem = GetViewData()->HasListPad() && !IS_SPECIAL_LVDATA(cookie);
|
|
|
|
if (GetViewData()->IsVirtualList())
|
|
{
|
|
pCCResultItem = pNode->GetPrimaryComponent();
|
|
sc = ScCheckPointers(pCCResultItem, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
sc = pCCResultItem->QueryDataObject(cookie, CCT_RESULT, &spDataObject);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
}
|
|
else if ( (GetViewData()->HasOCX()) || (GetViewData()->HasWebBrowser() && !bListPadItem) )
|
|
{
|
|
selData.m_pCompPrimary = pNode->GetPrimaryComponent();
|
|
sc = _ProcessSelection(selData, extnSnapins);
|
|
return sc.ToHr();
|
|
}
|
|
else
|
|
{
|
|
CResultItem* pri = CResultItem::FromHandle(cookie);
|
|
sc = ScCheckPointers(pri, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
if (pri->IsScopeItem())
|
|
{
|
|
// Get the data object from IComponentData
|
|
pNode = CNode::FromResultItem (pri);
|
|
sc = ScCheckPointers(pNode, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
if (pNode->IsInitialized() == FALSE)
|
|
{
|
|
sc = pNode->InitComponents();
|
|
if (sc)
|
|
return sc.ToHr();
|
|
}
|
|
|
|
pCCResultItem = pNode->GetPrimaryComponent();
|
|
sc = pNode->QueryDataObject(CCT_SCOPE, &spDataObject);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
}
|
|
else // Must be a leaf item inserted by a snapin
|
|
{
|
|
pCCResultItem = pNode->GetComponent(pri->GetOwnerID());
|
|
sc = ScCheckPointers(pCCResultItem, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
sc = pCCResultItem->QueryDataObject(pri->GetSnapinData(), CCT_RESULT,
|
|
&spDataObject);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
}
|
|
}
|
|
|
|
// Create extension snapin list
|
|
if (spDataObject != NULL)
|
|
{
|
|
ASSERT(pCCResultItem != NULL);
|
|
|
|
GUID guidObjType;
|
|
sc = ::ExtractObjectTypeGUID(spDataObject, &guidObjType);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
CSnapIn* pSnapIn = pNode->GetPrimarySnapIn();
|
|
|
|
CMTNode* pmtNode = pNode->GetMTNode();
|
|
sc = ScCheckPointers(pmtNode, E_UNEXPECTED);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
CArray<GUID, GUID&> DynExtens;
|
|
ExtractDynExtensions(spDataObject, DynExtens);
|
|
|
|
CExtensionsIterator it;
|
|
sc = it.ScInitialize(pSnapIn, guidObjType, g_szToolbar, DynExtens.GetData(), DynExtens.GetSize());
|
|
if (!sc.IsError())
|
|
{
|
|
for (; !it.IsEnd(); it.Advance())
|
|
{
|
|
extnSnapins.AddHead(const_cast<GUID&>(it.GetCLSID()));
|
|
}
|
|
}
|
|
|
|
selData.m_pCompPrimary = pCCResultItem;
|
|
selData.m_spDataObject.Attach(spDataObject.Detach());
|
|
}
|
|
|
|
// Finally process selection
|
|
sc = _ProcessSelection(selData, extnSnapins);
|
|
if (sc)
|
|
return sc.ToHr();
|
|
|
|
return sc.ToHr();
|
|
}
|
|
|
|
HRESULT CControlbarsCache::OnScopeSelChange(CNode* pNode, BOOL bSelected)
|
|
{
|
|
DECLARE_SC(sc, TEXT("CControlbarsCache::OnScopeSelChange"));
|
|
|
|
CSelData selData(true, (bool)bSelected);
|
|
selData.m_pNodeScope = pNode;
|
|
if (selData == m_SelData)
|
|
return S_FALSE;
|
|
|
|
if (!bSelected)
|
|
return _OnDeSelect(selData);
|
|
|
|
HRESULT hr = S_OK;
|
|
IDataObjectPtr spDataObject;
|
|
CComponent* pCCPrimary = NULL;
|
|
CList<CLSID, CLSID&> extnSnapins;
|
|
|
|
hr = pNode->QueryDataObject(CCT_SCOPE, &spDataObject);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
pCCPrimary = pNode->GetPrimaryComponent();
|
|
|
|
GUID guidObjType;
|
|
hr = ::ExtractObjectTypeGUID(spDataObject, &guidObjType);
|
|
ASSERT(SUCCEEDED(hr));
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
CSnapIn* pSnapIn = pNode->GetPrimarySnapIn();
|
|
|
|
CArray<GUID, GUID&> DynExtens;
|
|
ExtractDynExtensions(spDataObject, DynExtens);
|
|
|
|
CExtensionsIterator it;
|
|
sc = it.ScInitialize(pSnapIn, guidObjType, g_szToolbar, DynExtens.GetData(), DynExtens.GetSize());
|
|
if (!sc.IsError())
|
|
{
|
|
for (; it.IsEnd() == FALSE; it.Advance())
|
|
{
|
|
extnSnapins.AddHead(const_cast<GUID&>(it.GetCLSID()));
|
|
}
|
|
}
|
|
|
|
// Finally process selection
|
|
selData.m_pCompPrimary = pCCPrimary;
|
|
selData.m_spDataObject.Attach(spDataObject.Detach());
|
|
return _ProcessSelection(selData, extnSnapins);
|
|
}
|
|
|
|
HRESULT CControlbarsCache::_OnDeSelect(CSelData& selData)
|
|
{
|
|
ASSERT(!selData.IsSelect());
|
|
if (selData.m_bScopeSel != m_SelData.m_bScopeSel)
|
|
return S_FALSE;
|
|
|
|
if ( (m_SelData.m_pCtrlbarPrimary != NULL &&
|
|
m_SelData.m_spDataObject == NULL) &&
|
|
(!GetViewData()->HasOCX() ||
|
|
!GetViewData()->HasWebBrowser()) &&
|
|
m_SelData.IsScope())
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
MMC_NOTIFY_TYPE eNotifyCode = MMCN_SELECT;
|
|
LPARAM lDataObject;
|
|
|
|
if (GetViewData()->IsVirtualList())
|
|
{
|
|
eNotifyCode = MMCN_DESELECT_ALL;
|
|
|
|
// Must use NULL data object for MMCN_DESELECT_ALL.
|
|
lDataObject = 0;
|
|
}
|
|
else if ((GetViewData()->HasOCX()) && (!m_SelData.IsScope()))
|
|
lDataObject = reinterpret_cast<LPARAM>(DOBJ_CUSTOMOCX);
|
|
else if ((GetViewData()->HasWebBrowser()) && (!m_SelData.IsScope()))
|
|
{
|
|
if (GetViewData()->HasListPad() && m_SelData.m_spDataObject != NULL)
|
|
{
|
|
lDataObject = reinterpret_cast<LPARAM>(
|
|
static_cast<IDataObject*>(m_SelData.m_spDataObject));
|
|
}
|
|
else
|
|
{
|
|
lDataObject = reinterpret_cast<LPARAM>(DOBJ_CUSTOMWEB);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lDataObject = reinterpret_cast<LPARAM>(
|
|
static_cast<IDataObject*>(m_SelData.m_spDataObject));
|
|
}
|
|
|
|
WORD wScope = static_cast<WORD>(m_SelData.IsScope());
|
|
LPARAM arg = MAKELONG(wScope, FALSE);
|
|
|
|
|
|
if (m_SelData.m_pCtrlbarPrimary != NULL)
|
|
{
|
|
m_SelData.m_pCtrlbarPrimary->ControlbarNotify(eNotifyCode, arg,
|
|
lDataObject);
|
|
}
|
|
|
|
POSITION pos = m_SelData.m_listExtCBs.GetHeadPosition();
|
|
while (pos)
|
|
{
|
|
CControlbar* pCbar = m_SelData.m_listExtCBs.GetNext(pos);
|
|
pCbar->ControlbarNotify(eNotifyCode, arg, lDataObject);
|
|
}
|
|
|
|
m_SelData.m_bSelect = false;
|
|
m_SelData.m_spDataObject = NULL; // Release & set to NULL
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CControlbarsCache::_ProcessSelection(
|
|
CSelData& selData,
|
|
CList<CLSID, CLSID&>& extnSnapins)
|
|
{
|
|
LPARAM lDataObject = reinterpret_cast<LPARAM>(
|
|
static_cast<IDataObject*>(selData.m_spDataObject));
|
|
|
|
if (NULL == lDataObject)
|
|
{
|
|
if ( (GetViewData()->HasOCX()) && (!selData.IsScope()) )
|
|
lDataObject = reinterpret_cast<LPARAM>(DOBJ_CUSTOMOCX);
|
|
else if ( (GetViewData()->HasWebBrowser()) && (!selData.IsScope()) )
|
|
lDataObject = reinterpret_cast<LPARAM>(DOBJ_CUSTOMWEB);
|
|
}
|
|
|
|
WORD wScope = static_cast<WORD>(selData.IsScope());
|
|
long arg = MAKELONG(wScope, TRUE);
|
|
|
|
m_SelData.m_bScopeSel = selData.m_bScopeSel;
|
|
m_SelData.m_bSelect = selData.m_bSelect;
|
|
m_SelData.m_pNodeScope = selData.m_pNodeScope;
|
|
m_SelData.m_lCookie = selData.m_lCookie;
|
|
m_SelData.m_spDataObject.Attach(selData.m_spDataObject.Detach());
|
|
|
|
// Handle primary controlbar first
|
|
if (m_SelData.m_pCompPrimary != selData.m_pCompPrimary)
|
|
{
|
|
if (m_SelData.m_pCtrlbarPrimary != NULL)
|
|
{
|
|
// Ask controlbar to destroy its ref & destroy our ref
|
|
// to controlbar.
|
|
m_SelData.ScDestroyPrimaryCtrlbar();
|
|
}
|
|
|
|
m_SelData.m_pCompPrimary = selData.m_pCompPrimary;
|
|
|
|
if (m_SelData.m_pCompPrimary != NULL &&
|
|
m_SelData.m_pCtrlbarPrimary == NULL)
|
|
{
|
|
IExtendControlbarPtr spECBPrimary =
|
|
m_SelData.m_pCompPrimary->GetIComponent();
|
|
if (spECBPrimary != NULL)
|
|
{
|
|
m_SelData.m_pCtrlbarPrimary =
|
|
CreateControlbar(spECBPrimary,
|
|
m_SelData.m_pCompPrimary->GetCLSID());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_SelData.m_pCtrlbarPrimary != NULL)
|
|
{
|
|
m_SelData.m_pCtrlbarPrimary->ControlbarNotify(MMCN_SELECT, arg,
|
|
lDataObject);
|
|
}
|
|
|
|
// Handle extension controlbars
|
|
|
|
CControlbarsList newCBs;
|
|
|
|
POSITION pos = extnSnapins.GetHeadPosition();
|
|
|
|
while (pos)
|
|
{
|
|
CControlbar* pCbar = NULL;
|
|
|
|
CLSID& clsid = extnSnapins.GetNext(pos);
|
|
|
|
POSITION pos2 = m_SelData.m_listExtCBs.GetHeadPosition();
|
|
POSITION pos2Prev = 0;
|
|
while (pos2)
|
|
{
|
|
pos2Prev = pos2;
|
|
pCbar = m_SelData.m_listExtCBs.GetNext(pos2);
|
|
ASSERT(pCbar != NULL);
|
|
if (pCbar->IsSameSnapin(clsid) == TRUE)
|
|
break;
|
|
pCbar = NULL;
|
|
}
|
|
|
|
if (pCbar != NULL)
|
|
{
|
|
ASSERT(pos2Prev != 0);
|
|
m_SelData.m_listExtCBs.RemoveAt(pos2Prev);
|
|
}
|
|
else
|
|
{
|
|
IExtendControlbarPtr spECB;
|
|
HRESULT hr = spECB.CreateInstance(clsid, NULL, MMC_CLSCTX_INPROC);
|
|
CHECK_HRESULT(hr);
|
|
if (SUCCEEDED(hr))
|
|
pCbar = CreateControlbar(spECB, clsid);
|
|
}
|
|
|
|
if (pCbar != NULL)
|
|
newCBs.AddHead(pCbar);
|
|
}
|
|
|
|
m_SelData.ScDestroyExtensionCtrlbars();
|
|
|
|
pos = newCBs.GetHeadPosition();
|
|
while (pos)
|
|
{
|
|
CControlbar* pCbar = newCBs.GetNext(pos);
|
|
m_SelData.m_listExtCBs.AddHead(pCbar);
|
|
pCbar->ControlbarNotify(MMCN_SELECT, arg, lDataObject);
|
|
}
|
|
newCBs.RemoveAll();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|