463 lines
10 KiB
C
463 lines
10 KiB
C
|
//____________________________________________________________________________
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
||
|
//
|
||
|
// File: multisel.h
|
||
|
//
|
||
|
// Contents:
|
||
|
//
|
||
|
// Classes:
|
||
|
//
|
||
|
// Functions:
|
||
|
//
|
||
|
// History: 6/12/1997 RaviR Created
|
||
|
//____________________________________________________________________________
|
||
|
//
|
||
|
|
||
|
|
||
|
#ifndef _MULTISEL_H_
|
||
|
#define _MULTISEL_H_
|
||
|
|
||
|
class CSnapIn;
|
||
|
class CNode;
|
||
|
class CSnapInNode;
|
||
|
class CMTSnapInNode;
|
||
|
class CMultiSelection;
|
||
|
class CComponent;
|
||
|
class CComponentPtrArray;
|
||
|
class CScopeTree;
|
||
|
class CMMCClipBoardDataObject;
|
||
|
|
||
|
// local classes
|
||
|
class CSnapinSelData;
|
||
|
class CSnapinSelDataList;
|
||
|
class CMultiSelectDataObject;
|
||
|
|
||
|
|
||
|
class CSnapinSelData
|
||
|
{
|
||
|
public:
|
||
|
CSnapinSelData()
|
||
|
: m_nNumOfItems(0),
|
||
|
m_lCookie(111), // 0)
|
||
|
m_bScopeItem(FALSE),
|
||
|
m_ID(-1),
|
||
|
m_pComponent(NULL),
|
||
|
m_pSnapIn(NULL)
|
||
|
{
|
||
|
DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapinSelData);
|
||
|
}
|
||
|
|
||
|
~CSnapinSelData()
|
||
|
{
|
||
|
DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapinSelData);
|
||
|
}
|
||
|
|
||
|
UINT GetNumOfItems() const
|
||
|
{
|
||
|
return m_nNumOfItems;
|
||
|
}
|
||
|
|
||
|
MMC_COOKIE GetCookie() const
|
||
|
{
|
||
|
return m_lCookie;
|
||
|
}
|
||
|
|
||
|
BOOL IsScopeItem() const
|
||
|
{
|
||
|
return m_bScopeItem;
|
||
|
}
|
||
|
|
||
|
void IncrementNumOfItems()
|
||
|
{
|
||
|
++m_nNumOfItems;
|
||
|
}
|
||
|
|
||
|
void SetNumOfItems(UINT count)
|
||
|
{
|
||
|
m_nNumOfItems = count;
|
||
|
}
|
||
|
|
||
|
void SetCookie(MMC_COOKIE lCookie)
|
||
|
{
|
||
|
m_lCookie = lCookie;
|
||
|
}
|
||
|
|
||
|
void SetIsScopeItem(BOOL bScopeItem)
|
||
|
{
|
||
|
m_bScopeItem = bScopeItem;
|
||
|
}
|
||
|
|
||
|
void AddObjectType(GUID& guid)
|
||
|
{
|
||
|
m_objectTypeGuidList.AddHead(guid);
|
||
|
}
|
||
|
|
||
|
CList<GUID, GUID&>& GetObjectTypeGuidList()
|
||
|
{
|
||
|
return m_objectTypeGuidList;
|
||
|
}
|
||
|
|
||
|
void SetSnapIn(CSnapIn* pSnapIn)
|
||
|
{
|
||
|
m_pSnapIn = pSnapIn;
|
||
|
}
|
||
|
|
||
|
CSnapIn* GetSnapIn()
|
||
|
{
|
||
|
return m_pSnapIn;
|
||
|
}
|
||
|
|
||
|
COMPONENTID GetID()
|
||
|
{
|
||
|
return m_ID;
|
||
|
}
|
||
|
|
||
|
void SetID(COMPONENTID id)
|
||
|
{
|
||
|
m_ID = id;
|
||
|
}
|
||
|
|
||
|
void SetDataObject(IDataObject* pDO)
|
||
|
{
|
||
|
m_spDataObject = pDO;
|
||
|
}
|
||
|
|
||
|
IDataObject* GetDataObject()
|
||
|
{
|
||
|
ASSERT(m_spDataObject != NULL);
|
||
|
return m_spDataObject;
|
||
|
}
|
||
|
|
||
|
void SetComponent(CComponent* pComponent)
|
||
|
{
|
||
|
ASSERT(m_pComponent == NULL);
|
||
|
m_pComponent = pComponent;
|
||
|
}
|
||
|
|
||
|
CComponent* GetComponent()
|
||
|
{
|
||
|
ASSERT(m_pComponent != NULL);
|
||
|
return m_pComponent;
|
||
|
}
|
||
|
|
||
|
void SetConsoleVerb(IConsoleVerb* pConsoleVerb)
|
||
|
{
|
||
|
m_spConsoleVerb = pConsoleVerb;
|
||
|
}
|
||
|
|
||
|
IConsoleVerb* GetConsoleVerb()
|
||
|
{
|
||
|
return m_spConsoleVerb;
|
||
|
}
|
||
|
|
||
|
|
||
|
// methods to access array of scope nodes included in multiselection
|
||
|
// this data is particularly valuable, when data is put on clipboard
|
||
|
// to be detect if contined data is affected by CNode being deleted
|
||
|
typedef std::vector<CNode *> CNodePtrArray;
|
||
|
|
||
|
void AddScopeNodes(const CNodePtrArray& nodes) { m_vecScopeNodes.insert( m_vecScopeNodes.end(), nodes.begin(), nodes.end() ); }
|
||
|
const CNodePtrArray& GetScopeNodes() { return m_vecScopeNodes; }
|
||
|
|
||
|
private:
|
||
|
UINT m_nNumOfItems;
|
||
|
BOOL m_bScopeItem;
|
||
|
MMC_COOKIE m_lCookie;
|
||
|
COMPONENTID m_ID;
|
||
|
CSnapIn* m_pSnapIn;
|
||
|
CComponent* m_pComponent;
|
||
|
IConsoleVerbPtr m_spConsoleVerb;
|
||
|
IDataObjectPtr m_spDataObject;
|
||
|
CList<GUID, GUID&> m_objectTypeGuidList;
|
||
|
|
||
|
CNodePtrArray m_vecScopeNodes;
|
||
|
|
||
|
}; // class CSnapinSelData
|
||
|
|
||
|
|
||
|
class CSnapinSelDataList : public CList<CSnapinSelData*, CSnapinSelData*>
|
||
|
{
|
||
|
public:
|
||
|
CSnapinSelDataList()
|
||
|
{
|
||
|
DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapinSelDataList);
|
||
|
}
|
||
|
|
||
|
~CSnapinSelDataList()
|
||
|
{
|
||
|
POSITION pos = GetHeadPosition();
|
||
|
while (pos)
|
||
|
{
|
||
|
delete GetNext(pos);
|
||
|
}
|
||
|
|
||
|
DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapinSelDataList);
|
||
|
}
|
||
|
|
||
|
void Add(CSnapinSelData& snapinSelData, BOOL bStaticNode);
|
||
|
};
|
||
|
|
||
|
class CMultiSelection
|
||
|
{
|
||
|
public:
|
||
|
CMultiSelection(CNode* pNode);
|
||
|
|
||
|
void AddRef()
|
||
|
{
|
||
|
++m_cRef;
|
||
|
}
|
||
|
void Release()
|
||
|
{
|
||
|
ASSERT(m_cRef > 0);
|
||
|
--m_cRef;
|
||
|
if (m_cRef == 0)
|
||
|
{
|
||
|
ReleaseMultiSelDataObject();
|
||
|
delete this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT Init();
|
||
|
HRESULT GetMultiSelDataObject(IDataObject** ppDataObject);
|
||
|
HRESULT GetExtensionSnapins(LPCTSTR pszExtensionTypeKey,
|
||
|
CList<GUID, GUID&>& snapinGuidList);
|
||
|
bool IsSingleSnapinSelection()
|
||
|
{
|
||
|
if (m_rgStaticNodes.size() > 0 || m_snapinSelDataList.GetCount() > 1)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
IDataObject* GetSingleSnapinSelDataObject()
|
||
|
{
|
||
|
if (!IsSingleSnapinSelection())
|
||
|
return NULL;
|
||
|
|
||
|
CSnapinSelData* pSnapinSelData = m_snapinSelDataList.GetHead();
|
||
|
ASSERT(pSnapinSelData != NULL);
|
||
|
return pSnapinSelData->GetDataObject();
|
||
|
}
|
||
|
CComponent* GetPrimarySnapinComponent()
|
||
|
{
|
||
|
if (!IsSingleSnapinSelection())
|
||
|
return NULL;
|
||
|
|
||
|
CSnapinSelData* pSnapinSelData = m_snapinSelDataList.GetHead();
|
||
|
return pSnapinSelData->GetComponent();
|
||
|
}
|
||
|
BOOL IsAnExtensionSnapIn(const CLSID& rclsid);
|
||
|
BOOL HasNodes()
|
||
|
{
|
||
|
return m_bHasNodes;
|
||
|
}
|
||
|
BOOL HasStaticData()
|
||
|
{
|
||
|
return (m_rgStaticNodes.size() > 0);
|
||
|
}
|
||
|
BOOL HasSnapinData()
|
||
|
{
|
||
|
return (m_snapinSelDataList.IsEmpty() == FALSE);
|
||
|
}
|
||
|
BOOL HasData()
|
||
|
{
|
||
|
if (HasSnapinData() == FALSE)
|
||
|
return HasStaticData();
|
||
|
return TRUE;
|
||
|
}
|
||
|
void SetScopeTree(CScopeTree* pCScopeTree)
|
||
|
{
|
||
|
m_pCScopeTree = pCScopeTree;
|
||
|
}
|
||
|
CScopeTree* GetScopeTree()
|
||
|
{
|
||
|
ASSERT(m_pCScopeTree != NULL);
|
||
|
return m_pCScopeTree;
|
||
|
}
|
||
|
BOOL IsInUse()
|
||
|
{
|
||
|
return m_bInUse;
|
||
|
}
|
||
|
|
||
|
SC ScVerbInvoked(MMC_CONSOLE_VERB verb);
|
||
|
bool RemoveStaticNode(CMTNode* pMTNode);
|
||
|
void ReleaseMultiSelDataObject()
|
||
|
{
|
||
|
m_spDataObjectMultiSel = NULL;
|
||
|
ASSERT(m_spDataObjectMultiSel == NULL);
|
||
|
}
|
||
|
|
||
|
SC ScIsVerbEnabledInclusively(MMC_CONSOLE_VERB mmcVerb, BOOL& bEnable);
|
||
|
|
||
|
SC ScGetSnapinDataObjects(CMMCClipBoardDataObject *pResultObject);
|
||
|
|
||
|
private:
|
||
|
DWORD m_cRef;
|
||
|
CNode* m_pNode;
|
||
|
CSnapInNode* m_pSINode;
|
||
|
CMTSnapInNode* m_pMTSINode;
|
||
|
CScopeTree* m_pCScopeTree;
|
||
|
|
||
|
CSnapinSelDataList m_snapinSelDataList;
|
||
|
CMTNodePtrArray m_rgStaticNodes;
|
||
|
IDataObjectPtr m_spDataObjectMultiSel;
|
||
|
|
||
|
BOOL m_bHasNodes;
|
||
|
BOOL m_bInUse;
|
||
|
|
||
|
CMTSnapInNode* _GetStaticMasterNode()
|
||
|
{
|
||
|
return m_pMTSINode;
|
||
|
}
|
||
|
|
||
|
CSnapInNode* _GetStaticNode()
|
||
|
{
|
||
|
return m_pSINode;
|
||
|
}
|
||
|
|
||
|
void _SetInUse(BOOL b)
|
||
|
{
|
||
|
m_bInUse = b;
|
||
|
}
|
||
|
|
||
|
SC _ScVerbInvoked(MMC_CONSOLE_VERB verb);
|
||
|
bool _IsTargetCut();
|
||
|
|
||
|
#ifdef DBG
|
||
|
BOOL m_bInit;
|
||
|
#endif
|
||
|
|
||
|
HRESULT _ComputeSelectionDataList();
|
||
|
CComponent* _GetComponent(CSnapinSelData* pSnapinSelData);
|
||
|
HRESULT _GetObjectTypeForSingleSel(CSnapinSelData* pSnapinSelData);
|
||
|
HRESULT _GetObjectTypesForMultipleSel(CSnapinSelData* pSnapinSelData);
|
||
|
HRESULT _FindSnapinsThatExtendObjectTypes(CSnapinSelDataList& snapinSelDataList,
|
||
|
CList<GUID, GUID&>& snapinGuidList);
|
||
|
|
||
|
~CMultiSelection();
|
||
|
|
||
|
}; // class CMultiSelection
|
||
|
|
||
|
|
||
|
class CMultiSelectDataObject : public IDataObject,
|
||
|
public CComObjectRoot
|
||
|
{
|
||
|
public:
|
||
|
// ATL Maps
|
||
|
DECLARE_NOT_AGGREGATABLE(CMultiSelectDataObject)
|
||
|
BEGIN_COM_MAP(CMultiSelectDataObject)
|
||
|
COM_INTERFACE_ENTRY(IDataObject)
|
||
|
END_COM_MAP()
|
||
|
|
||
|
|
||
|
#ifdef DBG
|
||
|
int dbg_cRef;
|
||
|
ULONG InternalAddRef()
|
||
|
{
|
||
|
++dbg_cRef;
|
||
|
int tmp1 = dbg_cRef;
|
||
|
int tmp2 = tmp1 * 4;
|
||
|
return CComObjectRoot::InternalAddRef();
|
||
|
}
|
||
|
ULONG InternalRelease()
|
||
|
{
|
||
|
--dbg_cRef;
|
||
|
int tmp1 = dbg_cRef;
|
||
|
int tmp2 = tmp1 * 4;
|
||
|
return CComObjectRoot::InternalRelease();
|
||
|
}
|
||
|
#endif // DBG
|
||
|
|
||
|
|
||
|
// Construction/Destruction
|
||
|
CMultiSelectDataObject() : m_ppDataObjects(NULL), m_count(0),
|
||
|
m_ppMTNodes(NULL), m_nSize(0), m_pMS(NULL)
|
||
|
{
|
||
|
|
||
|
#ifdef DBG
|
||
|
dbg_cRef = 0;
|
||
|
#endif
|
||
|
DEBUG_INCREMENT_INSTANCE_COUNTER(CMultiSelectDataObject);
|
||
|
}
|
||
|
|
||
|
~CMultiSelectDataObject();
|
||
|
|
||
|
void SetDataObjects(LPDATAOBJECT* ppDataObjects, UINT count)
|
||
|
{
|
||
|
if (ppDataObjects != NULL)
|
||
|
{
|
||
|
ASSERT(m_ppDataObjects == NULL);
|
||
|
ASSERT(m_count == 0);
|
||
|
m_ppDataObjects = ppDataObjects;
|
||
|
m_count = count;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(count == 0);
|
||
|
delete [] m_ppDataObjects;
|
||
|
m_ppDataObjects = NULL;
|
||
|
m_count = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SetStaticNodes(CMTNodePtrArray &rgMTNodes, int nSize)
|
||
|
{
|
||
|
typedef CMTNode* _PMTNODE;
|
||
|
ASSERT(m_ppMTNodes == NULL);
|
||
|
ASSERT(m_nSize == 0);
|
||
|
m_ppMTNodes = new _PMTNODE[nSize];
|
||
|
if(m_ppMTNodes != NULL)
|
||
|
{
|
||
|
m_nSize = nSize;
|
||
|
for(int i=0; i<nSize; i++)
|
||
|
m_ppMTNodes[i] = rgMTNodes[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SetMultiSelection(CMultiSelection* pMS)
|
||
|
{
|
||
|
ASSERT(pMS != NULL);
|
||
|
m_pMS = pMS;
|
||
|
m_pMS->AddRef();
|
||
|
}
|
||
|
CMultiSelection* GetMultiSelection()
|
||
|
{
|
||
|
ASSERT(m_pMS != NULL);
|
||
|
return m_pMS;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Standard IDataObject methods
|
||
|
public:
|
||
|
// Implemented
|
||
|
STDMETHOD(GetDataHere)(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium);
|
||
|
STDMETHOD(GetData)(LPFORMATETC lpFormatetcIn, LPSTGMEDIUM lpMedium);
|
||
|
STDMETHOD(EnumFormatEtc)(DWORD dwDirection, LPENUMFORMATETC* ppEnumFormatEtc);
|
||
|
STDMETHOD(QueryGetData)(LPFORMATETC lpFormatetc);
|
||
|
|
||
|
// Not Implemented
|
||
|
STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC lpFormatetcIn, LPFORMATETC lpFormatetcOut) { return E_NOTIMPL; };
|
||
|
STDMETHOD(SetData)(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium, BOOL bRelease) { return E_NOTIMPL; };
|
||
|
STDMETHOD(DAdvise)(LPFORMATETC lpFormatetc, DWORD advf,LPADVISESINK pAdvSink, LPDWORD pdwConnection) { return E_NOTIMPL; };
|
||
|
STDMETHOD(DUnadvise)(DWORD dwConnection) { return E_NOTIMPL; };
|
||
|
STDMETHOD(EnumDAdvise)(LPENUMSTATDATA* ppEnumAdvise) { return E_NOTIMPL; }
|
||
|
|
||
|
private:
|
||
|
LPDATAOBJECT* m_ppDataObjects;
|
||
|
UINT m_count;
|
||
|
|
||
|
CMTNode** m_ppMTNodes;
|
||
|
int m_nSize;
|
||
|
|
||
|
CMultiSelection* m_pMS; // To be used only for Drag-Drop
|
||
|
|
||
|
}; // class CMultiSelectDataObject
|
||
|
|
||
|
|
||
|
bool IsMultiSelectDataObject(IDataObject* pdtobjCBSelData);
|
||
|
|
||
|
#endif // _MULTISEL_H_
|
||
|
|
||
|
|