📄 atlsnap.h
字号:
// This is a part of the Active Template Library.
// Copyright (C) 1996-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.
#ifndef __ATL_SNAPIN_H__
#define __ATL_SNAPIN_H__
#include <mmc.h>
#include <commctrl.h>
#pragma comment(lib, "mmc.lib")
#pragma comment(lib, "comctl32.lib")
template <class T, bool bAutoDelete = true>
class ATL_NO_VTABLE CSnapInPropertyPageImpl : public CDialogImplBase
{
public:
PROPSHEETPAGE m_psp;
operator PROPSHEETPAGE*() { return &m_psp; }
// Construction
CSnapInPropertyPageImpl(LPCTSTR lpszTitle = NULL)
{
// initialize PROPSHEETPAGE struct
memset(&m_psp, 0, sizeof(PROPSHEETPAGE));
m_psp.dwSize = sizeof(PROPSHEETPAGE);
m_psp.dwFlags = PSP_USECALLBACK;
m_psp.hInstance = _Module.GetResourceInstance();
m_psp.pszTemplate = MAKEINTRESOURCE(T::IDD);
m_psp.pfnDlgProc = (DLGPROC)T::StartDialogProc;
m_psp.pfnCallback = T::PropPageCallback;
m_psp.lParam = (LPARAM)this;
if(lpszTitle != NULL)
{
m_psp.pszTitle = lpszTitle;
m_psp.dwFlags |= PSP_USETITLE;
}
}
static UINT CALLBACK PropPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
{
ATLASSERT(hWnd == NULL);
if(uMsg == PSPCB_CREATE)
{
CDialogImplBase* pPage = (CDialogImplBase*)ppsp->lParam;
_Module.AddCreateWndData(&pPage->m_thunk.cd, pPage);
}
if (bAutoDelete && uMsg == PSPCB_RELEASE)
{
T* pPage = (T*)ppsp->lParam;
delete pPage;
}
return 1;
}
HPROPSHEETPAGE Create()
{
return ::CreatePropertySheetPage(&m_psp);
}
BOOL EndDialog(int)
{
// do nothing here, calling ::EndDialog will close the whole sheet
ATLASSERT(FALSE);
return FALSE;
}
// Operations
void CancelToClose()
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
::SendMessage(GetParent(), PSM_CANCELTOCLOSE, 0, 0L);
}
void SetModified(BOOL bChanged = TRUE)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
if(bChanged)
::SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0L);
else
::SendMessage(GetParent(), PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
}
LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(GetParent() != NULL);
return ::SendMessage(GetParent(), PSM_QUERYSIBLINGS, wParam, lParam);
}
typedef CSnapInPropertyPageImpl< T, bAutoDelete > thisClass;
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
END_MSG_MAP()
// Message handler
LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
ATLASSERT(::IsWindow(m_hWnd));
NMHDR* pNMHDR = (NMHDR*)lParam;
// don't handle messages not from the page/sheet itself
if(pNMHDR->hwndFrom != m_hWnd && pNMHDR->hwndFrom != ::GetParent(m_hWnd))
{
bHandled = FALSE;
return 1;
}
T* pT = (T*)this;
LRESULT lResult = 0;
// handle default
switch(pNMHDR->code)
{
case PSN_SETACTIVE:
lResult = pT->OnSetActive() ? 0 : -1;
break;
case PSN_KILLACTIVE:
lResult = !pT->OnKillActive();
break;
case PSN_APPLY:
lResult = pT->OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
break;
case PSN_RESET:
pT->OnReset();
break;
case PSN_QUERYCANCEL:
lResult = !pT->OnQueryCancel();
break;
case PSN_WIZNEXT:
lResult = !pT->OnWizardNext();
break;
case PSN_WIZBACK:
lResult = !pT->OnWizardBack();
break;
case PSN_WIZFINISH:
lResult = !pT->OnWizardFinish();
break;
case PSN_HELP:
lResult = pT->OnHelp();
break;
default:
bHandled = FALSE; // not handled
}
return lResult;
}
// Overridables
BOOL OnSetActive()
{
return TRUE;
}
BOOL OnKillActive()
{
return TRUE;
}
BOOL OnApply()
{
return TRUE;
}
void OnReset()
{
}
BOOL OnQueryCancel()
{
return TRUE; // ok to cancel
}
BOOL OnWizardBack()
{
return TRUE;
}
BOOL OnWizardNext()
{
return TRUE;
}
BOOL OnWizardFinish()
{
return TRUE;
}
BOOL OnHelp()
{
return TRUE;
}
};
class CSnapInItem;
class CSnapInObjectRootBase;
class CObjectData
{
public:
CSnapInItem* m_pItem;
DATA_OBJECT_TYPES m_type;
};
class ATL_NO_VTABLE CSnapInItem
{
public:
virtual ~CSnapInItem()
{
}
STDMETHOD(Notify)(MMC_NOTIFY_TYPE event,
long arg,
long param,
IComponentData* pComponentData,
IComponent* pComponent,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(GetScopePaneInfo)(SCOPEDATAITEM *pScopeDataItem) = 0;
STDMETHOD(GetResultViewType)(LPOLESTR *ppViewType,
long *pViewOptions) = 0;
STDMETHOD(GetResultPaneInfo)(RESULTDATAITEM *pResultDataItem) = 0;
STDMETHOD(AddMenuItems)(LPCONTEXTMENUCALLBACK piCallback,
long *pInsertionAllowed,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(Command)(long lCommandID,
CSnapInObjectRootBase* pObj,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(CreatePropertyPages)(LPPROPERTYSHEETCALLBACK lpProvider,
long handle,
IUnknown* pUnk,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(QueryPagesFor)(DATA_OBJECT_TYPES type) = 0;
STDMETHOD(SetControlbar)(IControlbar *pControlbar,
IExtendControlbar *pExtendControlbar,
CSimpleMap<UINT, IUnknown*>* pToolbarMap) = 0;
STDMETHOD(ControlbarNotify)(IControlbar *pControlbar,
IExtendControlbar *pExtendControlbar,
CSimpleMap<UINT, IUnknown*>* pToolbarMap,
MMC_NOTIFY_TYPE event,
long arg,
long param,
CSnapInObjectRootBase* pObj,
DATA_OBJECT_TYPES type) = 0;
STDMETHOD(GetScopeData)(SCOPEDATAITEM * *pScopeDataItem) = 0;
STDMETHOD(GetResultData)(RESULTDATAITEM * *pResultDataItem) = 0;
STDMETHOD(FillData)(CLIPFORMAT cf,
LPSTREAM pStream) = 0;
virtual void InitDataClass(IDataObject* pDataObject, CSnapInItem* pDefault)
{
_ASSERTE(0 && "Override this function in derived class");
}
static HRESULT GetDataClass(IDataObject* pDataObj, CSnapInItem** ppItem, DATA_OBJECT_TYPES* pType)
{
if (ppItem == NULL)
return E_POINTER;
if (pType == NULL)
return E_POINTER;
if (IS_SPECIAL_DATAOBJECT(pDataObj))
return E_NOTIMPL;
*ppItem = NULL;
*pType = CCT_UNINITIALIZED;
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
FORMATETC formatetc = { m_CCF_SNAPIN_GETOBJECTDATA,
NULL,
DVASPECT_CONTENT,
-1,
TYMED_HGLOBAL
};
stgmedium.hGlobal = GlobalAlloc(0, sizeof(CObjectData));
if (stgmedium.hGlobal == NULL)
return E_OUTOFMEMORY;
HRESULT hr = pDataObj->GetDataHere(&formatetc, &stgmedium);
if (SUCCEEDED(hr))
{
CObjectData* pData = (CObjectData*)stgmedium.hGlobal;
*ppItem = pData->m_pItem;
*pType = pData->m_type;
}
GlobalFree(stgmedium.hGlobal);
return hr;
}
virtual HRESULT STDMETHODCALLTYPE GetDataObject(IDataObject** pDataObj, DATA_OBJECT_TYPES type) = 0;
static void Init()
{
m_CCF_NODETYPE = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_NODETYPE"));
m_CCF_SZNODETYPE = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_SZNODETYPE"));
m_CCF_DISPLAY_NAME = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_DISPLAY_NAME"));
m_CCF_SNAPIN_CLASSID = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_SNAPIN_CLASSID"));
m_CCF_SNAPIN_GETOBJECTDATA = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_GETOBJECTDATA"));
m_CCF_MMC_MULTISELECT_DATAOBJECT = (CLIPFORMAT) RegisterClipboardFormat(_T("CCF_MMC_MULTISELECT_DATAOBJECT"));
}
public:
static CLIPFORMAT m_CCF_NODETYPE;
static CLIPFORMAT m_CCF_SZNODETYPE;
static CLIPFORMAT m_CCF_DISPLAY_NAME;
static CLIPFORMAT m_CCF_SNAPIN_CLASSID;
static CLIPFORMAT m_CCF_SNAPIN_GETOBJECTDATA;
static CLIPFORMAT m_CCF_MMC_MULTISELECT_DATAOBJECT;
};
class CSnapInObjectRootBase
{
public:
CComPtr <IControlbar> m_spControlbar;
CSimpleMap <UINT, IUnknown*> m_toolbarMap;
const int m_nType;
CSnapInObjectRootBase(int n = 0) : m_nType(n)
{
}
HRESULT GetDataClass(IDataObject* pDataObject, CSnapInItem** ppItem, DATA_OBJECT_TYPES* pType)
{
return CSnapInItem::GetDataClass(pDataObject, ppItem, pType);
}
};
template <int n, class ComponentData>
class CSnapInObjectRoot : public CSnapInObjectRootBase
{
public :
CSnapInObjectRoot() : CSnapInObjectRootBase(n)
{
m_pComponentData = NULL;
}
ComponentData* m_pComponentData;
};
#define EXTENSION_SNAPIN_DATACLASS(dataClass) dataClass m_##dataClass;
#define BEGIN_EXTENSION_SNAPIN_NODEINFO_MAP(classname) \
HRESULT GetDataClass(IDataObject* pDataObject, CSnapInItem** ppItem, DATA_OBJECT_TYPES* pType) \
{ \
if (ppItem == NULL) \
return E_POINTER; \
if (pType == NULL) \
return E_POINTER; \
\
*ppItem = NULL; \
\
*pType = CCT_UNINITIALIZED; \
\
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; \
FORMATETC formatetc = { CSnapInItem::m_CCF_NODETYPE, \
NULL, \
DVASPECT_CONTENT, \
-1, \
TYMED_HGLOBAL \
}; \
\
stgmedium.hGlobal = GlobalAlloc(0, sizeof(GUID)); \
if (stgmedium.hGlobal == NULL) \
return E_OUTOFMEMORY; \
\
HRESULT hr = pDataObject->GetDataHere(&formatetc, &stgmedium); \
if (FAILED(hr)) \
{ \
GlobalFree(stgmedium.hGlobal); \
return hr; \
} \
\
GUID guid; \
memcpy(&guid, stgmedium.hGlobal, sizeof(GUID)); \
\
GlobalFree(stgmedium.hGlobal); \
hr = S_OK;
#define EXTENSION_SNAPIN_NODEINFO_ENTRY(dataClass) \
if (IsEqualGUID(guid, *(GUID*)m_##dataClass.GetNodeType())) \
{ \
*ppItem = m_##dataClass.GetExtNodeObject(pDataObject, &m_##dataClass); \
_ASSERTE(*ppItem != NULL); \
(*ppItem)->InitDataClass(pDataObject, &m_##dataClass); \
return hr; \
}
#define END_EXTENSION_SNAPIN_NODEINFO_MAP() \
return CSnapInItem::GetDataClass(pDataObject, ppItem, pType); \
};
class ATL_NO_VTABLE CSnapInDataObjectImpl : public IDataObject,
public CComObjectRoot
{
public:
BEGIN_COM_MAP(CSnapInDataObjectImpl)
COM_INTERFACE_ENTRY(IDataObject)
END_COM_MAP()
STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::GetData\n"));
}
STDMETHOD(GetDataHere)(FORMATETC* pformatetc, STGMEDIUM* pmedium)
{
ATLTRACE2(atlTraceSnapin, 0, _T("SnapInDataObjectImpl::GetDataHere\n"));
if (pmedium == NULL)
return E_POINTER;
HRESULT hr = DV_E_TYMED;
// Make sure the type medium is HGLOBAL
if (pmedium->tymed == TYMED_HGLOBAL)
{
// Create the stream on the hGlobal passed in
CComPtr<IStream> spStream;
hr = CreateStreamOnHGlobal(pmedium->hGlobal, FALSE, &spStream);
if (SUCCEEDED(hr))
if (pformatetc->cfFormat == CSnapInItem::m_CCF_SNAPIN_GETOBJECTDATA)
{
hr = DV_E_CLIPFORMAT;
ULONG uWritten;
hr = spStream->Write(&m_objectData, sizeof(CObjectData), &uWritten);
}
else
hr = m_objectData.m_pItem->FillData(pformatetc->cfFormat, spStream);
}
return hr;
}
STDMETHOD(QueryGetData)(FORMATETC* /* pformatetc */)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::QueryGetData\n"));
}
STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::GetCanonicalFormatEtc\n"));
}
STDMETHOD(SetData)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetData\n"));
}
STDMETHOD(EnumFormatEtc)(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::EnumFormatEtc\n"));
}
STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink,
DWORD *pdwConnection)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetData\n"));
}
STDMETHOD(DUnadvise)(DWORD dwConnection)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetDatan\n"));
}
STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise)
{
ATLTRACENOTIMPL(_T("SnapInDataObjectImpl::SetData\n"));
}
CObjectData m_objectData;
};
template <class T, class Component>
class ATL_NO_VTABLE IComponentDataImpl : public IComponentData
{
public :
IComponentDataImpl()
{
m_pNode = NULL;
}
STDMETHOD(Initialize)(LPUNKNOWN pUnknown)
{
ATLTRACE2(atlTraceSnapin, 0, _T("IComponentDataImpl::Initialize\n"));
HRESULT hr = E_POINTER;
ATLASSERT(pUnknown != NULL);
if (pUnknown == NULL)
ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::Initialize called with pUnknown == NULL\n"));
else
{
hr = pUnknown->QueryInterface(&m_spConsole);
if (FAILED(hr))
ATLTRACE2(atlTraceSnapin, 0, _T("QI for IConsole failed\n"));
}
return hr;
}
STDMETHOD(CreateComponent)(LPCOMPONENT *ppComponent)
{
ATLTRACE2(atlTraceSnapin, 0, _T("IComponentDataImpl::CreateComponent\n"));
HRESULT hr = E_POINTER;
ATLASSERT(ppComponent != NULL);
if (ppComponent == NULL)
ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::CreateComponent called with ppComponent == NULL\n"));
else
{
*ppComponent = NULL;
CComObject< Component >* pComponent;
hr = CComObject< Component >::CreateInstance(&pComponent);
ATLASSERT(SUCCEEDED(hr));
if (FAILED(hr))
ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::CreateComponent : Could not create IComponent object\n"));
else
{
pComponent->m_pComponentData = static_cast<T*>(this);
hr = pComponent->QueryInterface(IID_IComponent, (void**)ppComponent);
}
}
return hr;
}
STDMETHOD(Notify)(
LPDATAOBJECT lpDataObject,
MMC_NOTIFY_TYPE event,
long arg,
long param)
{
ATLTRACE2(atlTraceSnapin, 0, _T("IComponentDataImpl::Notify\n"));
ATLASSERT(lpDataObject != NULL && _T("Override Notify in derived class handle notifications for which lpDataObject == NULL"));
HRESULT hr = E_POINTER;
ATLASSERT(lpDataObject != NULL);
if (lpDataObject == NULL)
ATLTRACE2(atlTraceSnapin, 0, _T("IComponentData::Notify called with lpDataObject == NULL\n"));
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -