|
|
// This is a part of the Microsoft Management Console.
// Copyright 1995 - 1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Management Console and related
// electronic documentation provided with the interfaces.
#include "stdafx.h"
#include "Service.h"
#include "CSnapin.h"
#include "DataObj.h"
#include "afxdlgs.h"
#include "resource.h"
#include "genpage.h" // Step 3
#include <atlimpl.cpp>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
// All data is static for the sample
FOLDER_DATA FolderData[NUM_FOLDERS] = { {L"User Data", L"1111", L"Info about users", USER}, {L"Company Data", L"2222", L"Info about Companies", COMPANY}, {L"Virtual Data", L"3333", L"Info about virtual items", VIRTUAL}, {L"", L"", L"",STATIC} };
FOLDER_DATA ExtFolderData[NUM_FOLDERS] = { {L"1:", L"1111", L"Info about users", EXT_USER}, {L"2:", L"2222", L"Info about Companies", EXT_COMPANY}, {L"3:", L"3333", L"Infor about virtual items", EXT_VIRTUAL}, {L"", L"", L"",STATIC} };
static MMCBUTTON SnapinButtons[] = { { 0, 1, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Folder", L"New Folder" }, { 1, 2, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Inbox", L"Mail Inbox"}, { 2, 3, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Outbox", L"Mail Outbox" }, { 3, 4, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Send", L"Send Message" }, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, L" ", L"" }, { 4, 5, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Trash", L"Trash" }, { 5, 6, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Open", L"Open Folder"}, { 6, 7, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"News", L"Today's News" }, { 7, 8, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"INews", L"Internet News" },
};
static MMCBUTTON SnapinButtons2[] = { { 0, 10, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Compose", L"Compose Message" }, { 1, 20, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Print", L"Print Message" }, { 2, 30, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Find", L"Find Message" }, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, L" ", L"" }, { 3, 40, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Inbox", L"Inbox" }, { 4, 50, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Smile", L"Smile :-)" }, { 5, 60, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Reply", L"Reply" }, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP , L" ", L"" }, { 6, 70, TBSTATE_ENABLED, TBSTYLE_BUTTON, L"Reply All", L"Reply All" },
};
enum { // Identifiers for each of the commands/views to be inserted into the context menu.
IDM_COMMAND1, IDM_COMMAND2, IDM_DEFAULT_MESSAGE_VIEW, IDM_SAMPLE_OCX_VIEW, IDM_SAMPLE_WEB_VIEW };
static int n_count = 0;
#define ODS OutputDebugString
#ifdef DBX
void DbxPrint(LPTSTR pszFmt, ...) { va_list va; va_start (va, pszFmt); TCHAR buf[250]; wsprintf(buf, pszFmt, va); OutputDebugString(buf); va_end(va); } //#define DBX_PRINT DbxPrint
inline void __DummyTrace(LPTSTR, ...) { } #define DBX_PRINT 1 ? (void)0 : ::__DummyTrace
#else
inline void __DummyTrace(LPTSTR, ...) { } #define DBX_PRINT 1 ? (void)0 : ::__DummyTrace
#endif
//
// The sample snap-in only has 1 property type and it's the workstation name
//
//
// Extracts the coclass guid format from the data object
//
template <class TYPE> TYPE* Extract(LPDATAOBJECT lpDataObject, unsigned int ucf) { ASSERT(lpDataObject != NULL);
TYPE* p = NULL;
CLIPFORMAT cf = (CLIPFORMAT)ucf;
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
// Allocate memory for the stream
int len = (cf == CDataObject::m_cfWorkstation) ? ((MAX_COMPUTERNAME_LENGTH+1) * sizeof(TYPE)) : sizeof(TYPE);
stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, len);
// Get the workstation name from the data object
do { if (stgmedium.hGlobal == NULL) break;
if (FAILED(lpDataObject->GetDataHere(&formatetc, &stgmedium))) break;
p = reinterpret_cast<TYPE*>(stgmedium.hGlobal);
if (p == NULL) break;
} while (FALSE);
return p; }
template<class T> void ReleaseExtracted (T* t) { GlobalFree (reinterpret_cast<HGLOBAL>(t)); }
BOOL IsMMCMultiSelectDataObject(IDataObject* pDataObject) { if (pDataObject == NULL) return FALSE;
static CLIPFORMAT s_cf = 0; if (s_cf == 0) { USES_CONVERSION; s_cf = (CLIPFORMAT)RegisterClipboardFormat(W2T(CCF_MMC_MULTISELECT_DATAOBJECT)); }
FORMATETC fmt = {s_cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
return (pDataObject->QueryGetData(&fmt) == S_OK); }
BOOL IsMyMultiSelectDataObject(IDataObject* pIDataObject) { if (pIDataObject == NULL) return FALSE;
CDataObject* pCDataObject = dynamic_cast<CDataObject*>(pIDataObject); if (pCDataObject == NULL) return FALSE;
return pCDataObject->IsMultiSelDobj(); }
// Data object extraction helpers
CLSID* ExtractClassID(LPDATAOBJECT lpDataObject) { return Extract<CLSID>(lpDataObject, CDataObject::m_cfCoClass); }
GUID* ExtractNodeType(LPDATAOBJECT lpDataObject) { return Extract<GUID>(lpDataObject, CDataObject::m_cfNodeType); }
wchar_t* ExtractWorkstation(LPDATAOBJECT lpDataObject) { return Extract<wchar_t>(lpDataObject, CDataObject::m_cfWorkstation); }
INTERNAL* ExtractInternalFormat(LPDATAOBJECT lpDataObject) { return Extract<INTERNAL>(lpDataObject, CDataObject::m_cfInternal); }
void ReleaseClassID (CLSID* pclsid) { ReleaseExtracted<CLSID>(pclsid); }
void ReleaseNodeType (GUID* pguid) { ReleaseExtracted<GUID>(pguid); }
void ReleaseWorkstation (wchar_t* p) { ReleaseExtracted<wchar_t>(p); }
void ReleaseInternalFormat (INTERNAL* pInternal) { ReleaseExtracted<INTERNAL>(pInternal); }
HRESULT _QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, CComponentDataImpl* pImpl, LPDATAOBJECT* ppDataObject) { ASSERT(ppDataObject != NULL); ASSERT(pImpl != NULL);
CComObject<CDataObject>* pObject;
CComObject<CDataObject>::CreateInstance(&pObject); ASSERT(pObject != NULL);
// Save cookie and type for delayed rendering
pObject->SetType(type); pObject->SetCookie(cookie);
#ifdef _DEBUG
pObject->SetComponentData(pImpl); #endif
// Store the coclass with the data object
pObject->SetClsid(pImpl->GetCoClassID());
return pObject->QueryInterface(IID_IDataObject, reinterpret_cast<void**>(ppDataObject)); }
DWORD GetItemType(MMC_COOKIE cookie) { // folder = CFoder* is cookie
// result = RESULT_DATA* is the cookie
return (*reinterpret_cast<DWORD*>(cookie)); }
/////////////////////////////////////////////////////////////////////////////
// Return TRUE if we are enumerating our main folder
BOOL CSnapin::IsEnumerating(LPDATAOBJECT lpDataObject) { BOOL bResult = FALSE;
ASSERT(lpDataObject); GUID* nodeType = ExtractNodeType(lpDataObject);
// Is this my main node (static folder node type)
if (::IsEqualGUID(*nodeType, cNodeTypeStatic) == TRUE) bResult = TRUE;
// Free resources
::GlobalFree(reinterpret_cast<HANDLE>(nodeType));
return bResult; }
/////////////////////////////////////////////////////////////////////////////
// CSnapin's IComponent implementation
// guid for custom view
static WCHAR* szCalendarGUID = L"{8E27C92B-1264-101C-8A2F-040224009C02}"; static WCHAR* szMicrosoftURL = L"www.microsoft.com";
STDMETHODIMP CSnapin::GetResultViewType(MMC_COOKIE cookie, LPOLESTR* ppViewType, long* pViewOptions) { *pViewOptions = MMC_VIEW_OPTIONS_MULTISELECT;
// if list view
if (m_CustomViewID == VIEW_DEFAULT_LV) { m_bVirtualView = FALSE;
// if static folder not selected
if (cookie != NULL) { // See if virtual data folder is selected
CFolder* pFolder = reinterpret_cast<CFolder*>(cookie); ASSERT(pFolder->itemType == SCOPE_ITEM); FOLDER_TYPES ftype = pFolder->GetType();
m_bVirtualView = (ftype == VIRTUAL || ftype == EXT_VIRTUAL);
if (m_bVirtualView) *pViewOptions |= MMC_VIEW_OPTIONS_OWNERDATALIST; }
return S_FALSE; }
WCHAR szMessageViewGUID[40]; WCHAR* pszView;
switch (m_CustomViewID) { case VIEW_CALENDAR_OCX: pszView = szCalendarGUID; break;
case VIEW_MICROSOFT_URL: pszView = szMicrosoftURL; break;
case VIEW_DEFAULT_MESSAGE_VIEW: StringFromGUID2 (CLSID_MessageView, szMessageViewGUID, ARRAYLEN(szMessageViewGUID)); pszView = szMessageViewGUID; break;
default: ASSERT (false && "CSnapin::GetResultViewType: Unknown view ID"); return (S_FALSE); break; }
UINT uiByteLen = (wcslen(pszView) + 1) * sizeof(WCHAR); LPOLESTR psz = (LPOLESTR)::CoTaskMemAlloc(uiByteLen);
USES_CONVERSION;
if (psz != NULL) { wcscpy(psz, pszView); *ppViewType = psz; return S_OK; }
return S_FALSE; }
STDMETHODIMP CSnapin::Initialize(LPCONSOLE lpConsole) { DBX_PRINT(_T(" ---------- CSnapin::Initialize<0x08x>\n"), this); ASSERT(lpConsole != NULL); m_bInitializedC = true;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Save the IConsole pointer
m_pConsole = lpConsole; m_pConsole->AddRef();
// Load resource strings
LoadResources();
// QI for a IHeaderCtrl
HRESULT hr = m_pConsole->QueryInterface(IID_IHeaderCtrl, reinterpret_cast<void**>(&m_pHeader));
// Give the console the header control interface pointer
if (SUCCEEDED(hr)) m_pConsole->SetHeader(m_pHeader);
m_pConsole->QueryInterface(IID_IResultData, reinterpret_cast<void**>(&m_pResult));
hr = m_pConsole->QueryResultImageList(&m_pImageResult); ASSERT(hr == S_OK);
hr = m_pConsole->QueryConsoleVerb(&m_pConsoleVerb); ASSERT(hr == S_OK);
return S_OK; }
STDMETHODIMP CSnapin::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (IS_SPECIAL_DATAOBJECT(lpDataObject)) { if (event == MMCN_BTN_CLICK) { if (m_CustomViewID != VIEW_DEFAULT_LV) { switch (param) { case MMC_VERB_REFRESH: ::AfxMessageBox(_T("MMCN_BTN_CLICK::MMC_VERB_REFRESH")); _OnRefresh(lpDataObject); break;
case MMC_VERB_PROPERTIES: ::AfxMessageBox(_T("MMCN_BTN_CLICK::MMC_VERB_PROPERTIES")); break;
default: ::AfxMessageBox(_T("MMCN_BTN_CLICK::param unknown")); break; } } } else { switch (event) { case MMCN_REFRESH: ::AfxMessageBox(_T("MMCN_BTN_CLICK::MMCN_REFRESH")); _OnRefresh(lpDataObject); break; } }
return S_OK; }
HRESULT hr = S_OK; MMC_COOKIE cookie;
if (event == MMCN_PROPERTY_CHANGE) { hr = OnPropertyChange(lpDataObject); } else if (event == MMCN_VIEW_CHANGE) { hr = OnUpdateView(lpDataObject); } else if (event == MMCN_DESELECT_ALL) { DBX_PRINT(_T("CSnapin::Notify -> MMCN_DESELECT_ALL \n")); } else if (event == MMCN_COLUMN_CLICK) { DBX_PRINT(_T("CSnapin::Notify -> MMCN_COLUMN_CLICK \n")); } else if (event == MMCN_SNAPINHELP) { AfxMessageBox(_T("CSnapin::Notify ->MMCN_SNAPINHELP")); } else { INTERNAL* pInternal = NULL;
if (IsMMCMultiSelectDataObject(lpDataObject) == FALSE) { pInternal = ExtractInternalFormat(lpDataObject);
if (pInternal == NULL) { ASSERT(FALSE); return S_OK; }
if (pInternal) cookie = pInternal->m_cookie; }
switch(event) { case MMCN_ACTIVATE: break;
case MMCN_CLICK: hr = OnResultItemClk(pInternal->m_type, cookie); break;
case MMCN_DBLCLICK: if (pInternal->m_type == CCT_RESULT) Command(IDM_COMMAND1, lpDataObject); else hr = S_FALSE;
break;
case MMCN_ADD_IMAGES: OnAddImages(cookie, arg, param); break;
case MMCN_SHOW: hr = OnShow(cookie, arg, param); break;
case MMCN_MINIMIZED: hr = OnMinimize(cookie, arg, param); break;
case MMCN_INITOCX: // ::MessageBox(NULL, _T("MMCN_INITOCX"), _T("TRACE"), MB_OK);
ASSERT(param != 0); break;
case MMCN_DESELECT_ALL: case MMCN_SELECT: HandleStandardVerbs((event == MMCN_DESELECT_ALL), arg, lpDataObject); break;
case MMCN_PASTE: AfxMessageBox(_T("CSnapin::MMCN_PASTE")); break;
case MMCN_DELETE: AfxMessageBox(_T("CSnapin::MMCN_DELETE")); break;
case MMCN_CONTEXTHELP: hr = OnContextHelp(lpDataObject); break;
case MMCN_REFRESH: AfxMessageBox(_T("CSnapin::MMCN_REFRESH")); _OnRefresh(lpDataObject); break;
case MMCN_PRINT: AfxMessageBox(_T("CSnapin::MMCN_PRINT")); break;
case MMCN_RENAME: // ODS(_T("\n\n\t\tCSnapin::MMCN_RENAME\n\n"));
break;
case MMCN_RESTORE_VIEW: { // user selected Back or Forward buttons:
// we get the same info back that we gave
// MMC during the GetResultViewType call.
MMC_RESTORE_VIEW* pmrv = (MMC_RESTORE_VIEW*)arg; BOOL * b = (BOOL*)param;
*b = TRUE; // we're handling it
// first, setup m_bVirtualMode
m_bVirtualView = FALSE; CFolder* pFolder = reinterpret_cast<CFolder*>(pmrv->cookie); if (pFolder != NULL) if (pFolder->GetType() == VIRTUAL) m_bVirtualView = TRUE;
WCHAR szMessageViewGUID[40]; StringFromGUID2 (CLSID_MessageView, szMessageViewGUID, ARRAYLEN(szMessageViewGUID));
// also, maintain m_CustomViewID
if (pmrv->pViewType == NULL) m_CustomViewID = VIEW_DEFAULT_LV; else if (!wcscmp (pmrv->pViewType, szCalendarGUID)) m_CustomViewID = VIEW_CALENDAR_OCX; else if (!wcscmp (pmrv->pViewType, szMicrosoftURL)) m_CustomViewID = VIEW_MICROSOFT_URL; else if (!wcscmp (pmrv->pViewType, szMessageViewGUID)) m_CustomViewID = VIEW_DEFAULT_MESSAGE_VIEW; else // doesn't look like one of mine, but it is:
// if the URL leads to another URL. This is
// sent to you can still maintain your checks
// in the view menu.
m_CustomViewID = VIEW_MICROSOFT_URL; // also, you could be re-directed via script or asp.
// also, you may have neglected
} break;
// Note - Future expansion of notify types possible
default: hr = E_UNEXPECTED; break; }
if (pInternal != NULL) { ::GlobalFree(reinterpret_cast<HANDLE>(pInternal)); } }
if (m_pResult) m_pResult->SetDescBarText(L"hello world");
return hr; }
void CSnapin::_OnRefresh(LPDATAOBJECT pDataObject) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); INTERNAL* pInternal = ExtractInternalFormat(pDataObject); if (pInternal == NULL) return;
USES_CONVERSION;
if (pInternal->m_type == CCT_SCOPE) { CComponentDataImpl* pData = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
if (pData->IsPrimaryImpl()) { CFolder* pFolder = pData->FindObject(pInternal->m_cookie);
::AfxMessageBox(pInternal->m_cookie ? OLE2T(pFolder->m_pszName) : _T("Files")); pData->DeleteAndReinsertAll(); } } else { RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(pInternal->m_cookie); ::AfxMessageBox(OLE2T(pData->szName)); } }
HRESULT CSnapin::OnContextHelp(LPDATAOBJECT pdtobj) { TCHAR name[128]; GetItemName(pdtobj, name);
TCHAR buf[200]; wsprintf(buf, _T("Context help requested for item: %s"), name); ::MessageBox(NULL, buf, _T("TRACE"), MB_OK);
return S_OK; }
STDMETHODIMP CSnapin::Destroy(MMC_COOKIE cookie) { DBX_PRINT(_T(" ---------- CSnapin::Destroy<0x08x>\n"), this); ASSERT(m_bInitializedC); m_bDestroyedC = true;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Release the interfaces that we QI'ed
if (m_pConsole != NULL) { // Tell the console to release the header control interface
m_pConsole->SetHeader(NULL); SAFE_RELEASE(m_pHeader);
SAFE_RELEASE(m_pResult); SAFE_RELEASE(m_pImageResult);
// Release the IConsole interface last
SAFE_RELEASE(m_pConsole); SAFE_RELEASE(m_pComponentData); // QI'ed in IComponentDataImpl::CreateComponent
SAFE_RELEASE(m_pConsoleVerb); }
return S_OK; }
typedef CArray<GUID, const GUID&> CGUIDArray;
void GuidArray_Add(CGUIDArray& rgGuids, const GUID& guid) { for (int i=rgGuids.GetUpperBound(); i >= 0; --i) { if (rgGuids[i] == guid) break; }
if (i < 0) rgGuids.Add(guid); }
HRESULT CSnapin::QueryMultiSelectDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { ASSERT(ppDataObject != NULL); if (ppDataObject == NULL) return E_POINTER;
CGUIDArray rgGuids;
if (m_bVirtualView == TRUE) { GuidArray_Add(rgGuids, cNodeTypeCompany); } else { // Determine the items selected
ASSERT(m_pResult != NULL); RESULTDATAITEM rdi; ZeroMemory(&rdi, sizeof(rdi)); rdi.mask = RDI_STATE; rdi.nIndex = -1; rdi.nState = TVIS_SELECTED;
while (m_pResult->GetNextItem(&rdi) == S_OK) { FOLDER_TYPES fType; DWORD* pdw = reinterpret_cast<DWORD*>(rdi.lParam);
if (*pdw == SCOPE_ITEM) { CFolder* pFolder = reinterpret_cast<CFolder*>(rdi.lParam); fType = pFolder->m_type; } else { ASSERT(*pdw == RESULT_ITEM); RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(rdi.lParam); fType = pData->parentType; }
const GUID* pguid; switch (fType) { case STATIC: pguid = &cNodeTypeStatic; break;
case COMPANY: pguid = &cNodeTypeCompany; break;
case USER: pguid = &cNodeTypeUser; break;
case EXT_COMPANY: pguid = &cNodeTypeExtCompany; break;
case EXT_USER: pguid = &cNodeTypeExtUser; break;
case VIRTUAL: case EXT_VIRTUAL: pguid = &cNodeTypeVirtual; break;
default: return E_FAIL; }
GuidArray_Add(rgGuids, *pguid); } }
CComObject<CDataObject>* pObject; CComObject<CDataObject>::CreateInstance(&pObject); ASSERT(pObject != NULL);
// Save cookie and type for delayed rendering
pObject->SetType(type); pObject->SetCookie(cookie); pObject->SetMultiSelDobj();
CComponentDataImpl* pImpl = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
#ifdef _DEBUG
pObject->SetComponentData(pImpl); #endif
// Store the coclass with the data object
pObject->SetClsid(pImpl->GetCoClassID()); UINT cb = rgGuids.GetSize() * sizeof(GUID); GUID* pGuid = new GUID[rgGuids.GetSize()]; CopyMemory(pGuid, rgGuids.GetData(), cb); pObject->SetMultiSelData((BYTE*)pGuid, cb);
return pObject->QueryInterface(IID_IDataObject, reinterpret_cast<void**>(ppDataObject)); return S_OK; }
STDMETHODIMP CSnapin::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { if (cookie == MMC_MULTI_SELECT_COOKIE) return QueryMultiSelectDataObject(cookie, type, ppDataObject);
ASSERT(type == CCT_RESULT);
#ifdef _DEBUG
if (cookie != MMC_MULTI_SELECT_COOKIE && m_bVirtualView == FALSE) { DWORD dwItemType = GetItemType(cookie); ASSERT(dwItemType == RESULT_ITEM); } #endif
// Delegate it to the IComponentData
ASSERT(m_pComponentData != NULL); CComponentDataImpl* pImpl = dynamic_cast<CComponentDataImpl*>(m_pComponentData); ASSERT(pImpl != NULL); return _QueryDataObject(cookie, type, pImpl, ppDataObject); }
/////////////////////////////////////////////////////////////////////////////
// CSnapin's implementation specific members
DEBUG_DECLARE_INSTANCE_COUNTER(CSnapin);
CSnapin::CSnapin() : m_bIsDirty(TRUE), m_bInitializedC(false), m_bDestroyedC(false) { DEBUG_INCREMENT_INSTANCE_COUNTER(CSnapin); Construct(); }
CSnapin::~CSnapin() { #if DBG==1
ASSERT(dbg_cRef == 0); #endif
DEBUG_DECREMENT_INSTANCE_COUNTER(CSnapin);
SAFE_RELEASE(m_pToolbar1); SAFE_RELEASE(m_pToolbar2);
SAFE_RELEASE(m_pMenuButton1);
SAFE_RELEASE(m_pControlbar);
// Make sure the interfaces have been released
ASSERT(m_pConsole == NULL); ASSERT(m_pHeader == NULL); ASSERT(m_pToolbar1 == NULL); ASSERT(m_pToolbar2 == NULL);
delete m_pbmpToolbar1; delete m_pbmpToolbar2;
ASSERT(!m_bInitializedC || m_bDestroyedC);
Construct(); }
void CSnapin::Construct() { #if DBG==1
dbg_cRef = 0; #endif
m_pConsole = NULL; m_pHeader = NULL;
m_pResult = NULL; m_pImageResult = NULL; m_pComponentData = NULL; m_pToolbar1 = NULL; m_pToolbar2 = NULL; m_pControlbar = NULL;
m_pMenuButton1 = NULL;
m_pbmpToolbar1 = NULL; m_pbmpToolbar2 = NULL;
m_pConsoleVerb = NULL;
m_CustomViewID = VIEW_DEFAULT_LV; // m_CustomViewID = VIEW_MICROSOFT_URL;
// m_CustomViewID = VIEW_CALENDAR_OCX;
// m_CustomViewID = VIEW_DEFAULT_MESSAGE_VIEW;
m_bVirtualView = FALSE; m_dwVirtualSortOptions = 0; }
void CSnapin::LoadResources() { // Load strings from resources
m_column1.LoadString(IDS_NAME); m_column2.LoadString(IDS_SIZE); m_column3.LoadString(IDS_TYPE); }
HRESULT CSnapin::InitializeHeaders(MMC_COOKIE cookie) { HRESULT hr = S_OK;
ASSERT(m_pHeader);
USES_CONVERSION;
// Put the correct headers depending on the cookie
// Note - cookie ignored for this sample
m_pHeader->InsertColumn(0, T2COLE(m_column1), LVCFMT_LEFT, 180); // Name
m_pHeader->InsertColumn(1, T2COLE(m_column2), LVCFMT_RIGHT, 90); // Size
m_pHeader->InsertColumn(2, T2COLE(m_column3), LVCFMT_LEFT, 160); // Type
return hr; }
HRESULT CSnapin::InitializeBitmaps(MMC_COOKIE cookie) { ASSERT(m_pImageResult != NULL);
::CBitmap bmp16x16; ::CBitmap bmp32x32;
// Load the bitmaps from the dll
bmp16x16.LoadBitmap(IDB_16x16); bmp32x32.LoadBitmap(IDB_32x32);
// Set the images
m_pImageResult->ImageListSetStrip( reinterpret_cast<PLONG_PTR>(static_cast<HBITMAP>(bmp16x16)), reinterpret_cast<PLONG_PTR>(static_cast<HBITMAP>(bmp32x32)), 0, RGB(255, 0, 255));
return S_OK; }
WCHAR* StringFromFolderType(FOLDER_TYPES type) { static WCHAR* s_szStatic = L"Static"; static WCHAR* s_szCompany = L"Company"; static WCHAR* s_szUser = L"User"; static WCHAR* s_szVirtual = L"Virtual"; static WCHAR* s_szUnknown = L"Unknown";
switch (type) { case STATIC: return s_szStatic; case COMPANY: return s_szCompany; case USER: return s_szUser; case VIRTUAL: return s_szVirtual; default: return s_szUnknown; } }
STDMETHODIMP CSnapin::GetDisplayInfo(LPRESULTDATAITEM pResult) { static WCHAR* s_szSize = L"200";
ASSERT(pResult != NULL);
if (pResult) { if (pResult->bScopeItem == TRUE) { CFolder* pFolder = reinterpret_cast<CFolder*>(pResult->lParam); if (pResult->mask & RDI_STR) { if (pResult->nCol == 0) pResult->str = pFolder->m_pszName; else if (pResult->nCol == 1) pResult->str = (LPOLESTR)s_szSize; else pResult->str = (LPOLESTR)StringFromFolderType(pFolder->m_type);
ASSERT(pResult->str != NULL);
if (pResult->str == NULL) pResult->str = (LPOLESTR)L""; }
if (pResult->mask & RDI_IMAGE) { switch(pFolder->GetType()) { case USER: case EXT_USER: pResult->nImage = USER_IMAGE; break;
case COMPANY: case EXT_COMPANY: pResult->nImage = COMPANY_IMAGE; break;
case VIRTUAL: pResult->nImage = VIRTUAL_IMAGE; break; } } } else { RESULT_DATA* pData;
// if virtual, derive result item from index
// else lParam is the item pointer
if (m_bVirtualView) pData = GetVirtualResultItem(pResult->nIndex); else pData= reinterpret_cast<RESULT_DATA*>(pResult->lParam);
if (pResult->mask & RDI_STR) { if (pResult->nCol == 0) pResult->str = (LPOLESTR)pData->szName; else if(pResult->nCol == 1) pResult->str = (LPOLESTR)pData->szSize; else pResult->str = (LPOLESTR)pData->szType;
ASSERT(pResult->str != NULL);
if (pResult->str == NULL) pResult->str = (LPOLESTR)L""; }
// MMC can request image and indent for virtual data
if (pResult->mask & RDI_IMAGE) pResult->nImage = 4; } }
return S_OK; }
/////////////////////////////////////////////////////////////////////////////
// IExtendContextMenu Implementation
// Array of menu item commands to be inserted into the contest menu.
// Note - the first item is the menu text, // CCM_SPECIAL_DEFAULT_ITEM
// the second item is the status string
static CONTEXTMENUITEM menuItems[] = { { L"Command 1", L"Sample extension menu added by snapin (Command 1)", IDM_COMMAND1, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0 }, { L"Command 2", L"Sample extension menu added by snapin (Command 2)", IDM_COMMAND2, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0 }, { NULL, NULL, 0, 0, 0 } };
// Array of view items to be inserted into the context menu.
static CONTEXTMENUITEM viewItems[] = { { L"Message View", L"Default message view", IDM_DEFAULT_MESSAGE_VIEW, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, 0 }, { L"Calendar", L"Sample OCX custom view", IDM_SAMPLE_OCX_VIEW, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, 0 }, { szMicrosoftURL, L"Sample WEB custom view", IDM_SAMPLE_WEB_VIEW, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, 0 }, { NULL, NULL, 0, 0, 0 }, };
// guid for custom view
static GUID CLSID_SmGraphControl = {0xC4D2D8E0L,0xD1DD,0x11CE,0x94,0x0F,0x00,0x80,0x29,0x00,0x43,0x47};
STDMETHODIMP CSnapin::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long *pInsertionAllowed) { #if 1 //testing
ASSERT(pDataObject != NULL); if (pDataObject && IsMMCMultiSelectDataObject(pDataObject)) { static CLIPFORMAT s_cf = 0; if (s_cf == 0) { USES_CONVERSION; s_cf = (CLIPFORMAT)RegisterClipboardFormat(W2T(CCF_MULTI_SELECT_SNAPINS)); }
FORMATETC fmt = {s_cf, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
STGMEDIUM stgm = { TYMED_HGLOBAL, NULL }; HRESULT hr = pDataObject->GetData(&fmt, &stgm); SMMCDataObjects* pData = (SMMCDataObjects*)stgm.hGlobal; int count = pData->count; IDataObject* pDO = NULL; hr = pData->lpDataObject[0]->QueryInterface(IID_IDataObject, (void**)&pDO); pDO->Release(); }
#endif
viewItems[0].fFlags = (m_CustomViewID == VIEW_DEFAULT_MESSAGE_VIEW) ? MF_CHECKED : 0; viewItems[1].fFlags = (m_CustomViewID == VIEW_CALENDAR_OCX) ? MF_CHECKED : 0; viewItems[2].fFlags = (m_CustomViewID == VIEW_MICROSOFT_URL) ? MF_CHECKED : 0;
CComponentDataImpl* pCCD = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
HRESULT hr = pCCD->AddMenuItems(pDataObject, pContextMenuCallback, pInsertionAllowed);
#if 0
/*
* add do-nothing commands on odd numbered items in the virtual list view */ if (SUCCEEDED (hr) && (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) && m_bVirtualView) { INTERNAL* pInternal = pDataObject ? ExtractInternalFormat(pDataObject) : NULL;
if (pInternal && (pInternal->m_cookie % 2)) { CONTEXTMENUITEM cmi;
cmi.strName = L"Another command (odd, virtual-only)"; cmi.strStatusBarText = NULL; cmi.lCommandID = 0xDDDD; cmi.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP; cmi.fFlags = 0; cmi.fSpecialFlags = 0;
pContextMenuCallback->AddItem (&cmi); ReleaseInternalFormat (pInternal); } } #endif
return (hr); }
STDMETHODIMP CSnapin::Command(long nCommandID, LPDATAOBJECT pDataObject) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); INTERNAL* pInternal = ExtractInternalFormat(pDataObject); if (pInternal == NULL) return E_FAIL;
if (pInternal->m_type == CCT_SCOPE) { // Handle view specific commands here
switch (nCommandID) { case IDM_SAMPLE_WEB_VIEW: case IDM_SAMPLE_OCX_VIEW: case IDM_DEFAULT_MESSAGE_VIEW: m_CustomViewID = (nCommandID == IDM_SAMPLE_OCX_VIEW) ? VIEW_CALENDAR_OCX : (nCommandID == IDM_SAMPLE_WEB_VIEW) ? VIEW_MICROSOFT_URL : VIEW_DEFAULT_MESSAGE_VIEW;
// Ask console to reslelect the node to force a new view
if (pInternal->m_cookie == 0) { CComponentDataImpl* pCCDI = dynamic_cast<CComponentDataImpl*>(m_pComponentData);
ASSERT(pCCDI != NULL);
m_pConsole->SelectScopeItem(pCCDI->m_pStaticRoot); } else { CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie); m_pConsole->SelectScopeItem(pFolder->m_pScopeItem->ID); } break;
case MMCC_STANDARD_VIEW_SELECT: m_CustomViewID = VIEW_DEFAULT_LV; break;
default: // Pass non-view specific commands to ComponentData
return dynamic_cast<CComponentDataImpl*>(m_pComponentData)-> Command(nCommandID, pDataObject); } } else if (pInternal->m_type == CCT_RESULT) {
// Handle each of the commands.
switch (nCommandID) { case IDM_COMMAND1: case IDM_COMMAND2: { m_pResult->ModifyViewStyle(MMC_SINGLESEL, (MMC_RESULT_VIEW_STYLE)0);
RESULTDATAITEM rdi; ZeroMemory(&rdi, sizeof(rdi));
rdi.mask = RDI_STATE; rdi.nState = LVIS_SELECTED; rdi.nIndex = -1; m_pResult->GetNextItem(&rdi);
int iSel = rdi.nIndex; int nImage = rdi.nImage; HRESULTITEM hri = 0;
RESULT_DATA* pData;
// if virtual view, derive result item from the index
if (m_bVirtualView) { pData = GetVirtualResultItem(iSel); } // else get the cookie (which is result item ptr)
else { ZeroMemory(&rdi, sizeof(rdi)); rdi.mask = RDI_PARAM | RDI_IMAGE; rdi.nIndex = iSel; HRESULT hr = m_pResult->GetItem(&rdi); nImage = rdi.nImage; ASSERT(SUCCEEDED(hr)); ASSERT(rdi.lParam != 0);
m_pResult->FindItemByLParam (rdi.lParam, &hri);
pData = reinterpret_cast<RESULT_DATA*>(rdi.lParam); }
#if 0
static int nIconIndex = 12; nIconIndex = (nIconIndex == 12) ? 13 : 12;
HICON hIcon = ExtractIcon (AfxGetInstanceHandle(), _T("%SystemRoot%\\system32\\shell32.dll"), nIconIndex);
IImageList* pil; m_pConsole->QueryResultImageList(&pil);
_asm int 3; pil->ImageListSetIcon((LONG_PTR*) hIcon, nImage); pil->ImageListSetIcon((LONG_PTR*) hIcon, ILSI_SMALL_ICON (nImage)); pil->ImageListSetIcon((LONG_PTR*) hIcon, ILSI_LARGE_ICON (nImage));
pil->Release();
m_pResult->UpdateItem (hri);
#else
CString strBuf = (nCommandID == IDM_COMMAND1) ? _T("\t Command 1 executed.\n\n") : _T("\t Command 2 executed.\n\n");
strBuf += pData->szName; strBuf += _T(" is the currently selected item.");
AfxMessageBox(strBuf);
// change image in list
if (!m_bVirtualView) { ZeroMemory(&rdi, sizeof(rdi)); rdi.mask = RDI_IMAGE; rdi.nIndex = iSel; rdi.nImage = 3; HRESULT hr = m_pResult->SetItem(&rdi); ASSERT(SUCCEEDED(hr)); } #endif
} break;
default: ASSERT(FALSE); // Unknown command!
break; } } else { ASSERT(0); }
::GlobalFree(reinterpret_cast<HANDLE>(pInternal));
return S_OK; }
STDMETHODIMP CSnapin::GetClassID(CLSID *pClassID) { ASSERT(pClassID != NULL);
// Copy the CLSID for this snapin
*pClassID = CLSID_Snapin;
return E_NOTIMPL; }
STDMETHODIMP CSnapin::IsDirty() { // Always save / Always dirty.
return ThisIsDirty() ? S_OK : S_FALSE; }
STDMETHODIMP CSnapin::Load(IStream *pStm) { DBX_PRINT(_T(" ---------- CSnapin::Load<0x08x>\n"), this); ASSERT(m_bInitializedC);
ASSERT(pStm); // Read the string
char psz[10]; ULONG nBytesRead; HRESULT hr = pStm->Read(psz, 10, &nBytesRead);
// Verify that the read succeeded
ASSERT(SUCCEEDED(hr) && nBytesRead == 10);
// check to see if the string is the correct string
ASSERT(strcmp("987654321", psz) == 0);
ClearDirty();
return SUCCEEDED(hr) ? S_OK : E_FAIL; }
STDMETHODIMP CSnapin::Save(IStream *pStm, BOOL fClearDirty) { DBX_PRINT(_T(" ---------- CSnapin::Save<0x08x>\n"), this); ASSERT(m_bInitializedC);
ASSERT(pStm);
// Write the string
ULONG nBytesWritten; HRESULT hr = pStm->Write("987654321", 10, &nBytesWritten);
// Verify that the write operation succeeded
ASSERT(SUCCEEDED(hr) && nBytesWritten == 10); if (FAILED(hr)) return STG_E_CANTSAVE;
if (fClearDirty) ClearDirty(); return S_OK; }
STDMETHODIMP CSnapin::GetSizeMax(ULARGE_INTEGER *pcbSize) { ASSERT(pcbSize);
// Set the size of the string to be saved
ULISet32(*pcbSize, 10);
return S_OK; }
///////////////////////////////////////////////////////////////////////////////
// IComponentData implementation
DEBUG_DECLARE_INSTANCE_COUNTER(CComponentDataImpl);
CComponentDataImpl::CComponentDataImpl() : m_bIsDirty(TRUE), m_pScope(NULL), m_pConsole(NULL), m_bInitializedCD(false), m_bDestroyedCD(false) { DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl);
#ifdef _DEBUG
m_cDataObjects = 0; #endif
}
CComponentDataImpl::~CComponentDataImpl() { DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl);
ASSERT(m_pScope == NULL);
ASSERT(!m_bInitializedCD || m_bDestroyedCD);
// Some snap-in is hanging on to data objects.
// If they access, it will crash!!!
ASSERT(m_cDataObjects <= 1); }
STDMETHODIMP CComponentDataImpl::Initialize(LPUNKNOWN pUnknown) { DBX_PRINT(_T(" ---------- CComponentDataImpl::Initialize<0x08x>\n"), this); m_bInitializedCD = true;
ASSERT(pUnknown != NULL); HRESULT hr;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// MMC should only call ::Initialize once!
ASSERT(m_pScope == NULL); pUnknown->QueryInterface(IID_IConsoleNameSpace, reinterpret_cast<void**>(&m_pScope));
// add the images for the scope tree
::CBitmap bmp16x16; LPIMAGELIST lpScopeImage;
hr = pUnknown->QueryInterface(IID_IConsole, reinterpret_cast<void**>(&m_pConsole)); ASSERT(hr == S_OK);
hr = m_pConsole->QueryScopeImageList(&lpScopeImage);
ASSERT(hr == S_OK);
// Load the bitmaps from the dll
bmp16x16.LoadBitmap(IDB_16x16);
// Set the images
lpScopeImage->ImageListSetStrip( reinterpret_cast<PLONG_PTR>(static_cast<HBITMAP>(bmp16x16)), reinterpret_cast<PLONG_PTR>(static_cast<HBITMAP>(bmp16x16)), 0, RGB(255, 0, 255));
lpScopeImage->Release();
return S_OK; }
STDMETHODIMP CComponentDataImpl::CreateComponent(LPCOMPONENT* ppComponent) { ASSERT(ppComponent != NULL);
CComObject<CSnapin>* pObject; CComObject<CSnapin>::CreateInstance(&pObject); ASSERT(pObject != NULL);
// Store IComponentData
pObject->SetIComponentData(this);
return pObject->QueryInterface(IID_IComponent, reinterpret_cast<void**>(ppComponent)); }
STDMETHODIMP CComponentDataImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { AFX_MANAGE_STATE (AfxGetStaticModuleState());
ASSERT(m_pScope != NULL); HRESULT hr;
// Since it's my folder it has an internal format.
// Design Note: for extension. I can use the fact, that the data object doesn't have
// my internal format and I should look at the node type and see how to extend it.
if (event == MMCN_PROPERTY_CHANGE) { hr = OnProperties(param); } else {
INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
if (pInternal == NULL) { return S_OK; }
MMC_COOKIE cookie = pInternal->m_cookie; ::GlobalFree(reinterpret_cast<HANDLE>(pInternal));
switch(event) { case MMCN_PASTE: AfxMessageBox(_T("CSnapin::MMCN_PASTE")); break;
case MMCN_DELETE: AfxMessageBox(_T("CD::MMCN_DELETE")); //hr = OnDelete(cookie);
break;
case MMCN_REMOVE_CHILDREN: hr = OnRemoveChildren(arg); break;
case MMCN_RENAME: hr = OnRename(cookie, arg, param); break;
case MMCN_EXPAND: hr = OnExpand(lpDataObject, arg, param); break;
default: break; }
}
return hr; }
STDMETHODIMP CComponentDataImpl::Destroy() { DBX_PRINT(_T(" ---------- CComponentDataImpl::Destroy<0x08x>\n"), this); ASSERT(m_bInitializedCD); m_bDestroyedCD = true;
// Delete enumerated scope items
DeleteList();
SAFE_RELEASE(m_pScope); SAFE_RELEASE(m_pConsole);
return S_OK; }
STDMETHODIMP CComponentDataImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { #ifdef _DEBUG
if (cookie == 0) { ASSERT(type != CCT_RESULT); } else { ASSERT(type == CCT_SCOPE);
DWORD dwItemType = GetItemType(cookie); ASSERT(dwItemType == SCOPE_ITEM); } #endif
return _QueryDataObject(cookie, type, this, ppDataObject); }
///////////////////////////////////////////////////////////////////////////////
//// IPersistStream interface members
STDMETHODIMP CComponentDataImpl::GetClassID(CLSID *pClassID) { ASSERT(pClassID != NULL);
// Copy the CLSID for this snapin
*pClassID = CLSID_Snapin;
return E_NOTIMPL; }
STDMETHODIMP CComponentDataImpl::IsDirty() { // Always save / Always dirty.
return ThisIsDirty() ? S_OK : S_FALSE; }
STDMETHODIMP CComponentDataImpl::Load(IStream *pStm) { DBX_PRINT(_T(" ---------- CComponentDataImpl::Load<0x08x>\n"), this);
ASSERT(pStm); ASSERT(m_bInitializedCD);
// Read the string
char psz[10]; ULONG nBytesRead; HRESULT hr = pStm->Read(psz, 10, &nBytesRead);
// Verify that the read succeeded
ASSERT(SUCCEEDED(hr) && nBytesRead == 10);
// check to see if the string is the correct string
ASSERT(strcmp("123456789", psz) == 0);
ClearDirty();
return SUCCEEDED(hr) ? S_OK : E_FAIL; }
STDMETHODIMP CComponentDataImpl::Save(IStream *pStm, BOOL fClearDirty) { DBX_PRINT(_T(" ---------- CComponentDataImpl::Save<0x08x>\n"), this);
ASSERT(pStm); ASSERT(m_bInitializedCD);
// Write the string
ULONG nBytesWritten; HRESULT hr = pStm->Write("123456789", 10, &nBytesWritten);
// Verify that the write operation succeeded
ASSERT(SUCCEEDED(hr) && nBytesWritten == 10); if (FAILED(hr)) return STG_E_CANTSAVE;
if (fClearDirty) ClearDirty(); return S_OK; }
STDMETHODIMP CComponentDataImpl::GetSizeMax(ULARGE_INTEGER *pcbSize) { ASSERT(pcbSize);
// Set the size of the string to be saved
ULISet32(*pcbSize, 10);
return S_OK; }
///////////////////////////////////////////////////////////////////////////////
//// Notify handlers for IComponentData
HRESULT CComponentDataImpl::OnDelete(MMC_COOKIE cookie) { return S_OK; }
HRESULT CComponentDataImpl::OnRemoveChildren(LPARAM arg) { return S_OK; }
HRESULT CComponentDataImpl::OnRename(MMC_COOKIE cookie, LPARAM arg, LPARAM param) { if (arg == 0) return S_OK;
LPOLESTR pszNewName = reinterpret_cast<LPOLESTR>(param); if (pszNewName == NULL) return E_INVALIDARG;
CFolder* pFolder = reinterpret_cast<CFolder*>(cookie); ASSERT(pFolder != NULL); if (pFolder == NULL) return E_INVALIDARG;
pFolder->SetName(pszNewName);
return S_OK; }
HRESULT CComponentDataImpl::OnExpand(LPDATAOBJECT lpDataObject, LPARAM arg, LPARAM param) { if (arg == TRUE) { // Did Initialize get called?
ASSERT(m_pScope != NULL); EnumerateScopePane(lpDataObject, param); }
return S_OK; }
HRESULT CComponentDataImpl::OnSelect(MMC_COOKIE cookie, LPARAM arg, LPARAM param) { return E_UNEXPECTED; }
HRESULT CComponentDataImpl::OnProperties(LPARAM param) { if (param == NULL) { return S_OK; }
ASSERT(param != NULL); CFolder* pFolder = new CFolder();
// Create a new folder object
pFolder->Create( reinterpret_cast<LPOLESTR>(param), 0, 0, STATIC, FALSE);
// The static folder in the last item in the list
POSITION pos = m_scopeItemList.GetTailPosition(); if (pos == 0) { // CreateFolderList();
pos = m_scopeItemList.GetTailPosition(); }
ASSERT(pos);
// Add it to the internal list
if (pos) { CFolder* pItem = m_scopeItemList.GetAt(pos); m_scopeItemList.InsertBefore(pos, pFolder);
pFolder->m_pScopeItem->relativeID = pItem->m_pScopeItem->relativeID;
// Set the folder as the cookie
pFolder->m_pScopeItem->mask |= SDI_PARAM; pFolder->m_pScopeItem->lParam = reinterpret_cast<LPARAM>(pFolder); pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder)); m_pScope->InsertItem(pFolder->m_pScopeItem); }
::GlobalFree(reinterpret_cast<void*>(param));
return S_OK; }
void CComponentDataImpl::CreateFolderList(LPDATAOBJECT lpDataObject) { CFolder* pFolder;
ASSERT(lpDataObject != NULL);
wchar_t* pWkStation = ExtractWorkstation(lpDataObject); ASSERT(pWkStation != NULL);
CLSID* pCoClassID = ExtractClassID(lpDataObject); ASSERT(pCoClassID != NULL);
// Determine which folder set to use based on context information
FOLDER_DATA* pFolderSet = FolderData; BOOL bExtend = FALSE;
if (!IsEqualCLSID(*pCoClassID, GetCoClassID())) { pFolderSet = ExtFolderData; bExtend = TRUE; // TRACE(_T("Using Extension Data\n"));
}
ASSERT(m_scopeItemList.GetCount() == 0); wchar_t buf[100];
for (int i=0; i < NUM_FOLDERS; i++) { pFolder = new CFolder(); buf[0] = NULL;
USES_CONVERSION;
wcscpy(buf, pFolderSet[i].szName);
// Add context info to the folder name
if (bExtend) wcscat(buf, pWkStation);
int nImage = 0; switch(pFolderSet[i].type) { case USER: case EXT_USER: nImage = USER_IMAGE; break;
case COMPANY: case EXT_COMPANY: nImage = COMPANY_IMAGE; break;
case VIRTUAL: nImage = VIRTUAL_IMAGE; break; }
// Create the folder objects with static data
pFolder->Create(buf, nImage/*FOLDER_IMAGE_IDX*/, OPEN_FOLDER_IMAGE_IDX, pFolderSet[i].type, FALSE);
m_scopeItemList.AddTail(pFolder); }
// mark cookie for last item
pFolder->SetCookie(NULL);
// Free memory from data object extraction
::GlobalFree(reinterpret_cast<HGLOBAL>(pWkStation)); ::GlobalFree(reinterpret_cast<HGLOBAL>(pCoClassID)); }
void CComponentDataImpl::EnumerateScopePane(LPDATAOBJECT lpDataObject, HSCOPEITEM pParent) { int i;
ASSERT(m_pScope != NULL); // make sure we QI'ed for the interface
ASSERT(lpDataObject != NULL);
INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
if (pInternal == NULL) return ;
MMC_COOKIE cookie = pInternal->m_cookie;
#ifndef RECURSIVE_NODE_EXPANSION
// Only the static node has enumerated children
if (cookie != NULL) return ; #endif
::GlobalFree(reinterpret_cast<HANDLE>(pInternal));
// Initialize folder list if empty
if (m_scopeItemList.GetCount() == 0) CreateFolderList(lpDataObject);
// Enumerate the scope pane
// return the folder object that represents the cookie
// Note - for large list, use dictionary
CFolder* pStatic = FindObject(cookie);
#ifndef RECURSIVE_NODE_EXPANSION
ASSERT(!pStatic->IsEnumerated()); // Note - Each cookie in the scope pane represents a folder.
// A released product may have more then one level of children.
// This sample assumes the parent node is one level deep.
#endif
ASSERT(pParent != NULL);
// Cache the HSCOPEITEM of the static root.
if (cookie == NULL) m_pStaticRoot = pParent;
POSITION pos = m_scopeItemList.GetHeadPosition(); CFolder* pFolder;
for (i=0; (i < (NUM_FOLDERS - 1)) && (pos != NULL); i++) { pFolder = m_scopeItemList.GetNext(pos); ASSERT(pFolder);
// Set the parent
pFolder->m_pScopeItem->relativeID = pParent;
// Set the folder as the cookie
pFolder->m_pScopeItem->mask |= SDI_PARAM; pFolder->m_pScopeItem->lParam = reinterpret_cast<LPARAM>(pFolder); pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder)); m_pScope->InsertItem(pFolder->m_pScopeItem);
// Note - On return, the ID member of 'm_pScopeItem'
// contains the handle to the newly inserted item!
ASSERT(pFolder->m_pScopeItem->ID != NULL); }
// Last folder added is the static folder
pStatic->Set(TRUE); // folder has been enumerated
pStatic->m_pScopeItem->relativeID = pParent; }
void CComponentDataImpl::DeleteAndReinsertAll() { ASSERT(m_pScope != NULL); // make sure we QI'ed for the interface
ASSERT (m_scopeItemList.GetCount() > 0);
//m_pStaticRoot
HRESULT hr = m_pScope->DeleteItem(m_pStaticRoot, FALSE); ASSERT(SUCCEEDED(hr));
POSITION pos = m_scopeItemList.GetHeadPosition(); CFolder* pFolder;
for (UINT i=0; (i < (NUM_FOLDERS - 1)) && (pos != NULL); i++) { pFolder = m_scopeItemList.GetNext(pos); ASSERT(pFolder);
// clear old ID
pFolder->m_pScopeItem->ID = NULL;
// Set the parent
pFolder->m_pScopeItem->relativeID = m_pStaticRoot;
// Set the folder as the cookie
pFolder->m_pScopeItem->mask |= SDI_PARAM; pFolder->m_pScopeItem->lParam = reinterpret_cast<LPARAM>(pFolder); pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder)); m_pScope->InsertItem(pFolder->m_pScopeItem);
// Note - On return, the ID member of 'm_pScopeItem'
// contains the handle to the newly inserted item!
ASSERT(pFolder->m_pScopeItem->ID != NULL); } }
void CComponentDataImpl::DeleteList() { POSITION pos = m_scopeItemList.GetHeadPosition();
while (pos) delete m_scopeItemList.GetNext(pos); }
CFolder* CComponentDataImpl::FindObject(MMC_COOKIE cookie) { POSITION pos = m_scopeItemList.GetHeadPosition(); CFolder* pFolder = NULL;
while(pos) { pFolder = m_scopeItemList.GetNext(pos);
if (*pFolder == cookie) return pFolder; }
return NULL; }
STDMETHODIMP CComponentDataImpl::GetDisplayInfo(SCOPEDATAITEM* pScopeDataItem) { ASSERT(pScopeDataItem != NULL); if (pScopeDataItem == NULL) return E_POINTER;
CFolder* pFolder = reinterpret_cast<CFolder*>(pScopeDataItem->lParam);
ASSERT(pScopeDataItem->mask & SDI_STR); pScopeDataItem->displayname = pFolder ? pFolder->m_pszName : L"Snapin Data";
//ASSERT(pScopeDataItem->displayname != NULL);
return S_OK; }
STDMETHODIMP CComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB) { if (lpDataObjectA == NULL || lpDataObjectB == NULL) return E_POINTER;
// Make sure both data object are mine
INTERNAL* pA; INTERNAL* pB; HRESULT hr = S_FALSE;
pA = ExtractInternalFormat(lpDataObjectA); pB = ExtractInternalFormat(lpDataObjectA);
if (pA != NULL && pB != NULL) hr = (*pA == *pB) ? S_OK : S_FALSE;
::GlobalFree(reinterpret_cast<HANDLE>(pA)); ::GlobalFree(reinterpret_cast<HANDLE>(pB));
return hr; }
/////////////////////////////////////////////////////////////////////////////
// IExtendPropertySheet2 Implementation
HRESULT CComponentDataImpl::DoInsertWizard(LPPROPERTYSHEETCALLBACK lpProvider) { CStartUpWizard* pWizard = new CStartUpWizard; CStartupWizard1* pWizard1 = new CStartupWizard1;
MMCPropPageCallback(&pWizard->m_psp97); MMCPropPageCallback(&pWizard1->m_psp97);
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pWizard->m_psp97);
if (hPage == NULL) return E_UNEXPECTED;
lpProvider->AddPage(hPage);
hPage = CreatePropertySheetPage(&pWizard1->m_psp97);
if (hPage == NULL) return E_UNEXPECTED;
lpProvider->AddPage(hPage);
return S_OK; }
STDMETHODIMP CComponentDataImpl::GetWatermarks( LPDATAOBJECT lpIDataObject, HBITMAP* lphWatermark, HBITMAP* lphHeader, HPALETTE* lphPalette, BOOL* pbStretch) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
*lphHeader = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BANNER)); *lphWatermark = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_WATERMARK)); *pbStretch = TRUE; // force the watermark bitmap to stretch
return S_OK; }
STDMETHODIMP CComponentDataImpl::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpIDataObject) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Look at the data object and determine if this an extension or a primary
ASSERT(lpIDataObject != NULL);
// Look at the data object and see if the snap-in manager is asking for pages
INTERNAL* pInternal= ExtractInternalFormat(lpIDataObject);
if (pInternal != NULL) { DATA_OBJECT_TYPES type = pInternal->m_type; FREE_DATA(pInternal);
if (type == CCT_SNAPIN_MANAGER) { HRESULT hr = DoInsertWizard(lpProvider); return hr; } }
CLSID* pCoClassID = ExtractClassID(lpIDataObject);
if(pCoClassID == NULL) { ASSERT(FALSE); return E_UNEXPECTED; }
CPropertyPage* pBasePage;
// Determine which
// Note: Should check the node type, but the sample only has 1
if (IsEqualCLSID(*pCoClassID, GetCoClassID())) { // Create the primary property page
CGeneralPage* pPage = new CGeneralPage(); pPage->m_hConsoleHandle = handle; pBasePage = pPage; } else {
// Create the extension property page
CExtensionPage* pPage = new CExtensionPage(); pBasePage = pPage;
wchar_t* pWkStation = ExtractWorkstation(lpIDataObject);
if (pWkStation == NULL) { ASSERT(FALSE); return E_FAIL; }
// Save the workstation name
pPage->m_szText = pWkStation; FREE_DATA(pWkStation);
}
FREE_DATA(pCoClassID);
// Object gets deleted when the page is destroyed
ASSERT(lpProvider != NULL);
HRESULT hr = MMCPropPageCallback(&pBasePage->m_psp);
if (SUCCEEDED(hr)) {
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
if (hPage == NULL) return E_UNEXPECTED;
lpProvider->AddPage(hPage); }
return hr; }
STDMETHODIMP CComponentDataImpl::QueryPagesFor(LPDATAOBJECT lpDataObject) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
// Get the node type and see if it's one of mine
// if (nodetype == one of mine)
// do this
// else
// see which node type it is and answer the question
return S_OK; }
BOOL CComponentDataImpl::IsScopePaneNode(LPDATAOBJECT lpDataObject) { BOOL bResult = FALSE; INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
if (pInternal->m_cookie == NULL && (pInternal->m_type == CCT_SCOPE || pInternal->m_type == CCT_RESULT)) bResult = TRUE;
FREE_DATA(pInternal);
return bResult; }
///////////////////////////////////////////////////////////////////////////////
// IExtendContextMenu implementation
//
STDMETHODIMP CComponentDataImpl::AddMenuItems(LPDATAOBJECT pDataObject, LPCONTEXTMENUCALLBACK pContextMenuCallback, long *pInsertionAllowed) { HRESULT hr = S_OK;
// Note - snap-ins need to look at the data object and determine
// in what context, menu items need to be added. They must also
// observe the insertion allowed flags to see what items can be
// added.
if (IsMMCMultiSelectDataObject(pDataObject) == TRUE) return S_FALSE;
INTERNAL* pInternal = ExtractInternalFormat(pDataObject); BOOL bCmd1IsDefault = (pInternal->m_type == CCT_RESULT);
if (bCmd1IsDefault) menuItems[0].fSpecialFlags = CCM_SPECIAL_DEFAULT_ITEM; else menuItems[0].fSpecialFlags = 0;
// Loop through and add each of the menu items
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP) { for (LPCONTEXTMENUITEM m = menuItems; m->strName; m++) { hr = pContextMenuCallback->AddItem(m);
if (FAILED(hr)) break; } }
// Loop through and add each of the view items
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW) { for (LPCONTEXTMENUITEM m = viewItems; m->strName; m++) { hr = pContextMenuCallback->AddItem(m);
if (FAILED(hr)) break; } }
return hr; }
STDMETHODIMP CComponentDataImpl::Command(long nCommandID, LPDATAOBJECT pDataObject) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
#ifdef DOBJ_NOCONSOLE
if (pDataObject == DOBJ_NOCONSOLE) { TCHAR szMsg[256];
wsprintf (szMsg, _T("CComponentDataImpl::Command invoked from outside the context of MMC (nCommandID = %d)."), nCommandID); AfxMessageBox (szMsg); return (S_OK); } #endif // DOBJ_NOCONSOLE
// Note - snap-ins need to look at the data object and determine
// in what context the command is being called.
// Handle each of the commands.
switch (nCommandID) { case IDM_COMMAND1: { ASSERT(m_pConsole); m_pConsole->MessageBox(L"Snapin Menu Comand Selected", menuItems[nCommandID].strName, MB_OK, NULL); if (1) { IConsole2* pc2 = NULL; m_pConsole->QueryInterface(IID_IConsole2, (void**)&pc2); ASSERT(pc2 != NULL); pc2->IsTaskpadViewPreferred(); pc2->Release(); break; }
INTERNAL* pi = ExtractInternalFormat(pDataObject); ASSERT(pi); ASSERT(pi->m_type != CCT_RESULT); CFolder* pFolder = reinterpret_cast<CFolder*>(pi->m_cookie); if (pFolder) { m_pConsole->SelectScopeItem(pFolder->m_pScopeItem->ID); } else { SCOPEDATAITEM si; ZeroMemory(&si, sizeof(si)); si.ID = m_pStaticRoot; si.mask = SDI_STR; si.displayname = MMC_TEXTCALLBACK; // _T("Sample snapin's static folder");
m_pScope->SetItem(&si); } break; } case IDM_COMMAND2: ASSERT(m_pConsole); m_pConsole->MessageBox(L"Snapin Menu Comand Selected", menuItems[nCommandID].strName, MB_OK, NULL); break;
default: ASSERT(FALSE); // Unknown command!
break; }
return S_OK; }
///////////////////////////////////////////////////////////////////////////////
// IExtendControlbar implementation
//
STDMETHODIMP CSnapin::SetControlbar(LPCONTROLBAR pControlbar) { // TRACE(_T("CSnapin::SetControlbar(%ld)\n"),pControlbar);
// Please don't delete this. Required to make sure we pick up the bitmap
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (pControlbar != NULL) {
// Hold on to the controlbar interface.
if (m_pControlbar) { m_pControlbar->Release(); }
m_pControlbar = pControlbar; m_pControlbar->AddRef();
HRESULT hr=S_FALSE;
if (!m_pMenuButton1) { hr = m_pControlbar->Create(MENUBUTTON, this, reinterpret_cast<LPUNKNOWN*>(&m_pMenuButton1)); ASSERT(SUCCEEDED(hr)); }
if (m_pMenuButton1) { // Unlike toolbar buttons, menu buttons need to be added every time.
hr = m_pMenuButton1->AddButton(FOLDEREX_MENU, L"FolderEx", L"Extended Folder Menu"); ASSERT(SUCCEEDED(hr)); hr = m_pMenuButton1->AddButton(FILEEX_MENU, L"FileEx", L"Extended File Menu"); ASSERT(SUCCEEDED(hr)); }
// Create the Toolbar 1
if (!m_pToolbar1) { hr = m_pControlbar->Create(TOOLBAR, this, reinterpret_cast<LPUNKNOWN*>(&m_pToolbar1)); ASSERT(SUCCEEDED(hr));
// Add the bitmap
m_pbmpToolbar1 = new ::CBitmap; m_pbmpToolbar1->LoadBitmap(IDB_TOOLBAR1); hr = m_pToolbar1->AddBitmap(11, *m_pbmpToolbar1, 16, 16, RGB(255, 0, 255)); ASSERT(SUCCEEDED(hr));
// Add the buttons to the toolbar
hr = m_pToolbar1->AddButtons(ARRAYLEN(SnapinButtons), SnapinButtons); ASSERT(SUCCEEDED(hr));
}
// TOOLBAR 2
// Create the Toolbar 2
if (!m_pToolbar2) { hr = m_pControlbar->Create(TOOLBAR, this, reinterpret_cast<LPUNKNOWN*>(&m_pToolbar2)); ASSERT(SUCCEEDED(hr));
// Add the bitmap
m_pbmpToolbar2 = new ::CBitmap; m_pbmpToolbar2->LoadBitmap(IDB_TOOLBAR2); hr = m_pToolbar2->AddBitmap(36, *m_pbmpToolbar2, 16, 16, RGB(192,192,192)); ASSERT(SUCCEEDED(hr));
// Add the buttons to the toolbar
hr = m_pToolbar2->AddButtons(ARRAYLEN(SnapinButtons2), SnapinButtons2); ASSERT(SUCCEEDED(hr));
}
} else { SAFE_RELEASE(m_pControlbar); }
return S_OK; }
void CSnapin::OnButtonClick(LPDATAOBJECT pdtobj, LONG_PTR idBtn) { TCHAR name[128]; GetItemName(pdtobj, name);
TCHAR buf[200]; wsprintf(buf, _T("Toolbar button<%d> was clicked. \nThe currently selected result item is <%s>"), idBtn, name); ::MessageBox(NULL, buf, _T("TRACE"), MB_OK); }
STDMETHODIMP CSnapin::ControlbarNotify(MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param) { HRESULT hr=S_FALSE;
AFX_MANAGE_STATE(AfxGetStaticModuleState());
switch (event) { case MMCN_BTN_CLICK: //TCHAR szMessage[MAX_PATH];
//wsprintf(szMessage, _T("CommandID %ld"),param);
//AfxMessageBox(szMessage);
OnButtonClick(reinterpret_cast<LPDATAOBJECT>(arg), param); break;
case MMCN_DESELECT_ALL: case MMCN_SELECT: HandleExtToolbars((event == MMCN_DESELECT_ALL), arg, param); break;
case MMCN_MENU_BTNCLICK: HandleExtMenus(arg, param); break;
default: break; }
return S_OK; }
// This compares two data objects to see if they are the same object.
// return
// S_OK if equal otherwise S_FALSE
//
// Note: check to make sure both objects belong to the snap-in.
//
STDMETHODIMP CSnapin::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB) { return S_FALSE; }
// This compare is used to sort the item's in the listview
//
// Parameters:
//
// lUserParam - user param passed in when IResultData::Sort() was called
// cookieA - first item to compare
// cookieB - second item to compare
// pnResult [in, out]- contains the col on entry,
// -1, 0, 1 based on comparison for return value.
//
// Note: Assum sort is ascending when comparing.
STDMETHODIMP CSnapin::Compare(LPARAM lUserParam, MMC_COOKIE cookieA, MMC_COOKIE cookieB, int* pnResult) { if (pnResult == NULL) { ASSERT(FALSE); return E_POINTER; }
// check col range
int nCol = *pnResult; ASSERT(nCol >=0 && nCol< 3);
*pnResult = 0;
USES_CONVERSION;
LPTSTR szStringA; LPTSTR szStringB;
RESULT_DATA* pDataA = reinterpret_cast<RESULT_DATA*>(cookieA); RESULT_DATA* pDataB = reinterpret_cast<RESULT_DATA*>(cookieB);
ASSERT(pDataA != NULL && pDataB != NULL);
if (nCol == 0) { szStringA = OLE2T(pDataA->szName); szStringB = OLE2T(pDataB->szName); } else if(nCol == 1) { szStringA = OLE2T(pDataA->szSize); szStringB = OLE2T(pDataB->szSize); } else { szStringA = OLE2T(pDataA->szType); szStringB = OLE2T(pDataB->szType) ; }
ASSERT(szStringA != NULL); ASSERT(szStringB != NULL);
*pnResult = _tcscmp(szStringA, szStringB);
return S_OK; }
///////////////////////////////////////////////////////////////////////////////
// IResultOwnerData implementation
//
STDMETHODIMP CSnapin::FindItem (LPRESULTFINDINFO pFindInfo, int* pnFoundIndex) { // find next item that matches the string (exact or partial)
// if matched found, set FoundIndex and return S_OK
// For the sample all items are named by their index number
// so we don't do a real string search. Also, to simplify the code
// the routine assumes a partial match search with wrap, which is what
// keyboard navigation calls use.
ASSERT((pFindInfo->dwOptions & (RFI_PARTIAL | RFI_WRAP)) == (RFI_PARTIAL | RFI_WRAP));
USES_CONVERSION;
TCHAR* lpszFind = OLE2T(pFindInfo->psz);
// TRACE(_T("CSnapin::FindItem(\"%s\")"), lpszFind);
// convert search string to number
int nMatchVal = 0; TCHAR* pch = lpszFind; while (*pch >= _T('0') && *pch <= _T('9') && nMatchVal < NUM_VIRTUAL_ITEMS) nMatchVal = nMatchVal * 10 + (*pch++ - _T('0'));
// if string has a non-decimal char or is too large, it won't match anything
if (*pch != 0 || nMatchVal >= NUM_VIRTUAL_ITEMS) return S_FALSE;
// if ascending sequence
if (!(m_dwVirtualSortOptions & RSI_DESCENDING)) { int nStartVal = pFindInfo->nStart;
// if match is less than start (but not zero), locate first value above start that matches
// otherwise the match number itself it the answer
if (nMatchVal < nStartVal && nMatchVal != 0) { // find scale factor to reach value >= start value
int nScale = 1; while (nMatchVal * nScale < nStartVal) nScale *= 10;
// check special case of start value beginning with the match digits
int nTestVal = (nStartVal * 10 - nMatchVal * nScale) < nScale ? nStartVal : nMatchVal * nScale;
// if not too big it's the match, else the match value is the match
if (nTestVal < NUM_VIRTUAL_ITEMS) nMatchVal = nTestVal; } } else // descending sequence
{ // convert start index to start value
int nStartVal = (NUM_VIRTUAL_ITEMS - 1) - pFindInfo->nStart;
if (nMatchVal != 0) { // if match number > start, we will have to wrap to find a match
// so use max index as our target
int nTargetVal = (nMatchVal > nStartVal) ? NUM_VIRTUAL_ITEMS - 1 : nStartVal;
// find scale factor that gets closest without going over target
int nScale = 1; while (nMatchVal * nScale * 10 < nTargetVal) nScale *= 10;
// check special case of target value beginning with the match digits
nMatchVal = (nTargetVal - nMatchVal * nScale) < nScale ? nTargetVal : (nMatchVal + 1) * nScale - 1; }
// convert match value back to an item index
nMatchVal = (NUM_VIRTUAL_ITEMS - 1) - nMatchVal; }
*pnFoundIndex = nMatchVal;
return S_OK;
}
STDMETHODIMP CSnapin::CacheHint (int nStartIndex, int nEndIndex) { // If advantageous, use this hint to pre-fetch the result item info that
// is about to be requested.
// TRACE(_T("CSnapin::CacheHint(%d,%d)\n"), nStartIndex, nEndIndex);
return S_OK;
}
STDMETHODIMP CSnapin::SortItems (int nColumn, DWORD dwSortOptions, LPARAM lUserParam) { // sort request for user owned result items
// if item order changed return S_OK, else S_FALSE
// Sample only sorts on the first column (item name)
if ((nColumn == 0) && (m_dwVirtualSortOptions != dwSortOptions)) { m_dwVirtualSortOptions = dwSortOptions; return S_OK; }
return S_FALSE;
}
void CSnapin::HandleStandardVerbs(bool bDeselectAll, LPARAM arg, LPDATAOBJECT lpDataObject) { WORD bScope = LOWORD(arg); WORD bSelect = HIWORD(arg);
#if 0
// trace
{ TCHAR buf[250]; static UINT s_count1 = 0; wsprintf(buf, _T("<%4d> %s - %s\n"), ++s_count1, bScope ? _T("Scope") : _T("Result"), bSelect ? _T("selected") : _T("de-selected")); OutputDebugString(buf); } #endif
if (!bScope) { if (m_CustomViewID == VIEW_MICROSOFT_URL) { m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
return; } else if (m_CustomViewID == VIEW_CALENDAR_OCX) { m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
return; } }
if (!bDeselectAll && lpDataObject == NULL) return;
// You should crack the data object and enable/disable/hide standard
// commands appropriately. The standard commands are reset everytime you get
// called. So you must reset them back.
#if 0
TCHAR buf[40]; wsprintf(buf, _T(" %4d - CSnapin::OnSelect<%d, %d>\n"), ++n_count, bScope, bSelect); ODS(buf); #else
DBX_PRINT(_T(" %4d - CSnapin::OnSelect<%d, %d>\n"), ++n_count, bScope, bSelect); #endif
if (!bDeselectAll && IsMyMultiSelectDataObject(lpDataObject) == TRUE) { m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE);
m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, ENABLED, TRUE);
m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
return; }
INTERNAL* pInternal = lpDataObject ? ExtractInternalFormat(lpDataObject) : NULL;
if (bSelect && (pInternal != NULL) && (pInternal->m_type == CCT_SCOPE)) { IConsole2* pConsole2; m_pConsole->QueryInterface (IID_IConsole2, (void**)&pConsole2);
CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie);
if (pFolder != NULL) { switch (pFolder->GetType()) { case USER: pConsole2->SetStatusText (L"User node selected||third pane"); break;
case COMPANY: pConsole2->SetStatusText (L"Company node selected|%25|third pane"); break;
case VIRTUAL: pConsole2->SetStatusText (L" Virtual node selected | %50 | third pane "); break; } } else pConsole2->SetStatusText (L"Static root node selected||third pane");
pConsole2->Release (); }
if (bDeselectAll || !bSelect) { if (bScope) { m_pConsoleVerb->SetVerbState(MMC_VERB_OPEN, ENABLED, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, ENABLED, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_PASTE, ENABLED, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_RENAME, ENABLED, FALSE); } else { // Result pane background
m_pConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_PASTE, ENABLED, TRUE);
if (pInternal && pInternal->m_cookie == 0) { m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE); }
m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE); }
return; }
if (m_pConsoleVerb && pInternal) { if (pInternal->m_type == CCT_SCOPE) { // Standard funcitonality support by scope items
m_pConsoleVerb->SetVerbState(MMC_VERB_OPEN, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_OPEN, ENABLED, TRUE);
m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
// Enable properties for static node only.
if (pInternal->m_cookie == 0) { m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE); //m_pConsoleVerb->SetDefaultVerb(MMC_VERB_PROPERTIES);
m_pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN); } else { m_pConsoleVerb->SetVerbState(MMC_VERB_PRINT, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_PRINT, ENABLED, TRUE);
m_pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN); }
// Standard funcitonality NOT support by scope items
m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, ENABLED, TRUE);
m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE);
m_pConsoleVerb->SetVerbState(MMC_VERB_CUT, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_CUT, ENABLED, FALSE); //m_pConsoleVerb->SetVerbState(MMC_VERB_CUT, ENABLED, TRUE);
} else { // Standard funcitonality support by result items
m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE); m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, FALSE); m_pConsoleVerb->SetVerbState(MMC_VERB_DELETE, ENABLED, TRUE); m_pConsoleVerb->SetDefaultVerb(MMC_VERB_NONE);
// Standard funcitonality NOT support by result items
}
m_pConsoleVerb->SetVerbState(MMC_VERB_RENAME, ENABLED, TRUE);
// Standard funcitonality NOT support by all items
//m_pConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, TRUE);
//m_pConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, TRUE);
} }
void EnableToolbar(LPTOOLBAR pToolbar, MMCBUTTON rgSnapinButtons[], int nRgSize, BOOL bEnable) { for (int i=0; i < nRgSize; ++i) { if (rgSnapinButtons[i].idCommand != 0) pToolbar->SetButtonState(rgSnapinButtons[i].idCommand, ENABLED, bEnable); } }
void EnableMenuBtns(LPMENUBUTTON pMenuBtn, MMCBUTTON rgSnapinButtons[], int nRgSize, BOOL bEnable) { for (int i=0; i < nRgSize; ++i) { if (rgSnapinButtons[i].idCommand != 0) pMenuBtn->SetButtonState(rgSnapinButtons[i].idCommand, ENABLED, bEnable); } }
void CSnapin::HandleExtToolbars(bool bDeselectAll, LPARAM arg, LPARAM param) { INTERNAL* pInternal = NULL; HRESULT hr;
BOOL bScope = (BOOL) LOWORD(arg); BOOL bSelect = (BOOL) HIWORD(arg);
#if 0
#if 1
{ if (param) { LPDATAOBJECT pDataObject = reinterpret_cast<LPDATAOBJECT>(param); pInternal = ExtractInternalFormat(pDataObject); }
TCHAR buf[200]; wsprintf(buf, _T(" %4d - CExtendControlbar::OnSelect<%d, %d> = %d\n"), ++n_count, bScope, bSelect, pInternal ? pInternal->m_cookie : 0); ODS(buf); } #else
DBX_PRINT(_T(" %4d - CExtendControlbar::OnSelect<%d, %d>\n"), ++n_count, bScope, bSelect); #endif
#endif
if (bDeselectAll || bSelect == FALSE) { ASSERT(m_pToolbar1); EnableToolbar(m_pToolbar1, SnapinButtons, ARRAYLEN(SnapinButtons), FALSE);
ASSERT(m_pToolbar2); EnableToolbar(m_pToolbar2, SnapinButtons2, ARRAYLEN(SnapinButtons2), FALSE);
ASSERT(m_pMenuButton1 != NULL); m_pMenuButton1->SetButtonState(FOLDEREX_MENU, ENABLED, FALSE); m_pMenuButton1->SetButtonState(FILEEX_MENU, ENABLED, FALSE);
return; }
ASSERT(bSelect == TRUE); bool bFileExBtn = false; if (bScope == TRUE) { LPDATAOBJECT pDataObject = reinterpret_cast<LPDATAOBJECT>(param);
pInternal = ExtractInternalFormat(pDataObject); if (pInternal == NULL) return;
CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie);
if (pInternal->m_cookie == 0) { if (IsPrimaryImpl() == TRUE) { // Attach the toolbars to the window
hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar1); ASSERT(SUCCEEDED(hr));
hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar2); ASSERT(SUCCEEDED(hr)); } } else if ((IsPrimaryImpl() == TRUE && pFolder->GetType() == COMPANY) || (IsPrimaryImpl() == FALSE && pFolder->GetType() == EXT_COMPANY)) { // Detach the toolbar2 from the window
hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar2); ASSERT(SUCCEEDED(hr));
// Attach the toolbar1 to the window
hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar1); ASSERT(SUCCEEDED(hr)); } else if ((IsPrimaryImpl() == TRUE && pFolder->GetType() == USER) || (IsPrimaryImpl() == FALSE && pFolder->GetType() == EXT_USER)) { // Detach the toolbar1 from the window
hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar1); ASSERT(SUCCEEDED(hr));
// Attach the toolbar2 to the window
hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar2); ASSERT(SUCCEEDED(hr)); } else { // Detach the toolbars from the window
hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar1); ASSERT(SUCCEEDED(hr));
hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar2); ASSERT(SUCCEEDED(hr)); }
FREE_DATA(pInternal);
EnableToolbar(m_pToolbar1, SnapinButtons, ARRAYLEN(SnapinButtons), FALSE);
EnableToolbar(m_pToolbar2, SnapinButtons2, ARRAYLEN(SnapinButtons2), FALSE); } else // result item selected.
{ LPDATAOBJECT pDataObject = reinterpret_cast<LPDATAOBJECT>(param);
if (pDataObject != NULL) pInternal = ExtractInternalFormat(pDataObject);
if (pInternal == NULL) return;
if (pInternal->m_type == CCT_RESULT) { bFileExBtn = true;
ASSERT(m_pToolbar1); EnableToolbar(m_pToolbar1, SnapinButtons, ARRAYLEN(SnapinButtons), TRUE);
m_pToolbar1->SetButtonState(1, ENABLED, FALSE); m_pToolbar1->SetButtonState(2, CHECKED, TRUE); m_pToolbar1->SetButtonState(3, HIDDEN, TRUE); m_pToolbar1->SetButtonState(4, INDETERMINATE, TRUE); m_pToolbar1->SetButtonState(5, BUTTONPRESSED, TRUE);
// Above is the correct way
ASSERT(m_pToolbar2); m_pToolbar2->SetButtonState(20, CHECKED, TRUE); m_pToolbar2->SetButtonState(30, HIDDEN, TRUE); m_pToolbar2->SetButtonState(40, INDETERMINATE, TRUE); m_pToolbar2->SetButtonState(50, BUTTONPRESSED, TRUE);
EnableToolbar(m_pToolbar2, SnapinButtons2, ARRAYLEN(SnapinButtons2), TRUE); } else // sub folder slected
{ CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie);
ASSERT(m_pControlbar);
if (pInternal->m_cookie == 0) { if (IsPrimaryImpl() == TRUE) { // Attach the toolbars to the window
hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar1); ASSERT(SUCCEEDED(hr));
hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar2); ASSERT(SUCCEEDED(hr)); } } else if ((IsPrimaryImpl() == TRUE && pFolder->GetType() == COMPANY) || (IsPrimaryImpl() == FALSE && pFolder->GetType() == EXT_COMPANY)) { // Detach the toolbar2 from the window
hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar2); ASSERT(SUCCEEDED(hr));
// Attach the toolbar1 to the window
hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar1); ASSERT(SUCCEEDED(hr)); } else if ((IsPrimaryImpl() == TRUE && pFolder->GetType() == USER) || (IsPrimaryImpl() == FALSE && pFolder->GetType() == EXT_USER)) { // Detach the toolbar1 from the window
hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar1); ASSERT(SUCCEEDED(hr));
// Attach the toolbar2 to the window
hr = m_pControlbar->Attach(TOOLBAR, (LPUNKNOWN) m_pToolbar2); ASSERT(SUCCEEDED(hr)); } else { // Detach the toolbars from the window
hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar1); ASSERT(SUCCEEDED(hr));
hr = m_pControlbar->Detach((LPUNKNOWN)m_pToolbar2); ASSERT(SUCCEEDED(hr)); }
ASSERT(m_pToolbar1); EnableToolbar(m_pToolbar1, SnapinButtons, ARRAYLEN(SnapinButtons), TRUE);
m_pToolbar1->SetButtonState(1, ENABLED, FALSE); m_pToolbar1->SetButtonState(2, CHECKED, TRUE); m_pToolbar1->SetButtonState(3, ENABLED, TRUE); m_pToolbar1->SetButtonState(4, INDETERMINATE, TRUE); m_pToolbar1->SetButtonState(5, BUTTONPRESSED, TRUE);
ASSERT(m_pToolbar2); EnableToolbar(m_pToolbar2, SnapinButtons2, ARRAYLEN(SnapinButtons2), TRUE);
// Above is the correct way
m_pToolbar2->SetButtonState(20, CHECKED, FALSE); m_pToolbar2->SetButtonState(30, ENABLED, TRUE); m_pToolbar2->SetButtonState(40, INDETERMINATE, FALSE); m_pToolbar2->SetButtonState(50, BUTTONPRESSED, TRUE); } }
if (m_pMenuButton1) { // Always make sure the menuButton is attached
m_pControlbar->Attach(MENUBUTTON, m_pMenuButton1);
if (bFileExBtn) { m_pMenuButton1->SetButtonState(FILEEX_MENU, HIDDEN, FALSE); m_pMenuButton1->SetButtonState(FOLDEREX_MENU, HIDDEN, TRUE); m_pMenuButton1->SetButtonState(FILEEX_MENU, ENABLED, TRUE); } else { m_pMenuButton1->SetButtonState(FOLDEREX_MENU, HIDDEN, FALSE); m_pMenuButton1->SetButtonState(FILEEX_MENU, HIDDEN, TRUE); m_pMenuButton1->SetButtonState(FOLDEREX_MENU, ENABLED, TRUE); } } }
void CSnapin::HandleExtMenus(LPARAM arg, LPARAM param) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
LPDATAOBJECT* ppDataObject = reinterpret_cast<LPDATAOBJECT*>(arg); LPMENUBUTTONDATA pMenuData = reinterpret_cast<LPMENUBUTTONDATA>(param);
if (ppDataObject == NULL || pMenuData == NULL) { ASSERT(FALSE); return; }
::CMenu menu; ::CMenu* pMenu = NULL;
switch (pMenuData->idCommand) { case FOLDEREX_MENU: menu.LoadMenu(FOLDEREX_MENU); pMenu = menu.GetSubMenu(0); break;
case FILEEX_MENU: menu.LoadMenu(FILEEX_MENU); pMenu = menu.GetSubMenu(0); break;
default: ASSERT(FALSE); }
if (pMenu == NULL) return;
pMenu->TrackPopupMenu(TPM_RETURNCMD | TPM_NONOTIFY, pMenuData->x, pMenuData->y, AfxGetMainWnd());
}
void CSnapin::GetItemName(LPDATAOBJECT pdtobj, LPTSTR pszName) { ASSERT(pszName != NULL); pszName[0] = 0;
INTERNAL* pInternal = ExtractInternalFormat(pdtobj); ASSERT(pInternal != NULL); if (pInternal == NULL) return;
OLECHAR *pszTemp;
USES_CONVERSION;
if (pInternal->m_type == CCT_RESULT) { RESULT_DATA* pData; // if virtual, derive result item from index
// else cookie is the item pointer
if (m_bVirtualView) pData = GetVirtualResultItem(pInternal->m_cookie); else pData = reinterpret_cast<RESULT_DATA*>(pInternal->m_cookie);
ASSERT(pData != NULL); pszTemp = pData->szName; } else { CFolder* pFolder = reinterpret_cast<CFolder*>(pInternal->m_cookie); if (pFolder == 0) pszTemp = L"Static folder"; else pszTemp = pFolder->m_pszName; }
lstrcpy(pszName, OLE2T(pszTemp)); }
/* end of file */
|