|
|
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) Microsoft Corp. All rights reserved.
//
// FILE
//
// snapwork.cpp
//
// SYNOPSIS
//
// Defines classes for implementing an MMC Snap-In.
//
// MODIFICATION HISTORY
//
// 02/19/2000 Original version.
//
///////////////////////////////////////////////////////////////////////////////
#include <proxypch.h>
#include <snapwork.h>
namespace SnapIn { void AfxThrowLastError() { DWORD error = GetLastError(); AfxThrowOleException(HRESULT_FROM_WIN32(error)); }
//////////
// Clipboard formats we support.
//////////
const CLIPFORMAT CCF_ID_NODETYPE = (CLIPFORMAT) RegisterClipboardFormatW(CCF_NODETYPE);
const CLIPFORMAT CCF_ID_SZNODETYPE = (CLIPFORMAT) RegisterClipboardFormatW(CCF_SZNODETYPE);
const CLIPFORMAT CCF_ID_DISPLAY_NAME = (CLIPFORMAT) RegisterClipboardFormatW(CCF_DISPLAY_NAME);
const CLIPFORMAT CCF_ID_SNAPIN_CLASSID = (CLIPFORMAT) RegisterClipboardFormatW(CCF_SNAPIN_CLASSID);
//////////
// Helper function that returns the length of a string in bytes.
//////////
inline ULONG wcsbytelen(PCWSTR sz) throw () { return (wcslen(sz) + 1) * sizeof(WCHAR); }
//////////
// Helper functions that writes data to an HGLOBAL
//////////
HRESULT WriteDataToHGlobal( HGLOBAL& dst, const VOID* data, ULONG dataLen ) throw () { if (GlobalSize(dst) < dataLen) { HGLOBAL newGlobal = GlobalReAlloc(dst, dataLen, 0); if (!newGlobal) { return E_OUTOFMEMORY; } dst = newGlobal; }
memcpy(dst, data, dataLen);
return S_OK; }
//////////
// Helper function that loads a string resource.
//////////
ULONG LoadString( HMODULE module, UINT id, PCWSTR* string ) throw () { HRSRC resInfo = FindResourceW( module, MAKEINTRESOURCEW((id >> 4) + 1), RT_STRING ); if (resInfo) { HGLOBAL resData = LoadResource( module, resInfo ); if (resData) { PCWSTR sz = (PCWSTR)LockResource(resData); if (sz) { // Skip forward to our string.
for (id &= 0xf; id > 0; --id) { sz += *sz + 1; }
*string = sz + 1; return *sz; } } }
*string = NULL; return 0; } }
// Static member of ResourceString
WCHAR ResourceString::empty;
ResourceString::ResourceString(UINT id) throw () { PCWSTR string; ULONG length = LoadString( _Module.GetResourceInstance(), id, &string ); sz = new (std::nothrow) WCHAR[length + 1]; if (sz) { memcpy(sz, string, length * sizeof(WCHAR)); sz[length] = L'\0'; } else { sz = ∅ } }
///////////////////////////////////////////////////////////////////////////////
//
// Methods for manipulating a generic IDataObject (i.e., not necessarily one of
// ours).
//
///////////////////////////////////////////////////////////////////////////////
VOID WINAPI ExtractData( IDataObject* dataObject, CLIPFORMAT format, PVOID data, DWORD dataLen ) { HGLOBAL global; ExtractData( dataObject, format, dataLen, &global ); memcpy(data, global, dataLen); GlobalFree(global); }
VOID WINAPI ExtractData( IDataObject* dataObject, CLIPFORMAT format, DWORD maxDataLen, HGLOBAL* data ) { if (!dataObject) { AfxThrowOleException(E_POINTER); }
FORMATETC formatetc = { format, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
stgmedium.hGlobal = GlobalAlloc(GPTR, maxDataLen); if (!stgmedium.hGlobal) { AfxThrowOleException(E_OUTOFMEMORY); }
HRESULT hr = dataObject->GetDataHere(&formatetc, &stgmedium); if (SUCCEEDED(hr)) { *data = stgmedium.hGlobal; } else { GlobalFree(stgmedium.hGlobal); AfxThrowOleException(hr); } }
VOID WINAPI ExtractNodeType( IDataObject* dataObject, GUID* nodeType ) { ExtractData( dataObject, CCF_ID_NODETYPE, nodeType, sizeof(GUID) ); }
// Convert an IDataObject to its corresponding SnapInDataItem.
SnapInDataItem* SnapInDataItem::narrow(IDataObject* dataObject) throw () { if (!dataObject) { return NULL; }
SnapInDataItem* object; HRESULT hr = dataObject->QueryInterface( __uuidof(SnapInDataItem), (PVOID*)&object ); if (FAILED(hr)) { return NULL; }
object->Release();
return object; }
// Default implementations of various functions used by GetDataHere. This way
// derived classes don't have to implement these if they're sure MMC will never
// ask for them.
const GUID* SnapInDataItem::getNodeType() const throw () { return &GUID_NULL; } const GUID* SnapInDataItem::getSnapInCLSID() const throw () { return &GUID_NULL; } PCWSTR SnapInDataItem::getSZNodeType() const throw () { return L"{00000000-0000-0000-0000-000000000000}"; }
// By default we compare column items as case sensitive strings.
int SnapInDataItem::compare( SnapInDataItem& item, int column ) throw () { return wcscmp(getDisplayName(column), item.getDisplayName(column)); }
//////////
// Do nothing implementations of all the notifications, etc.
//////////
HRESULT SnapInDataItem::addMenuItems( SnapInView& view, LPCONTEXTMENUCALLBACK callback, long insertionAllowed ) { return S_FALSE; }
HRESULT SnapInDataItem::createPropertyPages( SnapInView& view, LPPROPERTYSHEETCALLBACK provider, LONG_PTR handle ) { return S_FALSE; }
HRESULT SnapInDataItem::queryPagesFor() throw () { return S_FALSE; }
HRESULT SnapInDataItem::getResultViewType( LPOLESTR* ppViewType, long* pViewOptions ) throw () { return S_FALSE; }
HRESULT SnapInDataItem::onButtonClick( SnapInView& view, MMC_CONSOLE_VERB verb ) { return S_FALSE; }
HRESULT SnapInDataItem::onContextHelp( SnapInView& view ) { return S_FALSE; }
HRESULT SnapInDataItem::onDelete( SnapInView& view ) { return S_FALSE; }
HRESULT SnapInDataItem::onDoubleClick( SnapInView& view ) { return S_FALSE; }
HRESULT SnapInDataItem::onExpand( SnapInView& view, HSCOPEITEM itemId, BOOL expanded ) { return S_FALSE; }
HRESULT SnapInDataItem::onMenuCommand( SnapInView& view, long commandId ) { return S_FALSE; }
HRESULT SnapInDataItem::onPropertyChange( SnapInView& view, BOOL scopeItem ) { return S_FALSE; }
HRESULT SnapInDataItem::onRefresh(SnapInView& view) { return S_FALSE; }
HRESULT SnapInDataItem::onRename( SnapInView& view, LPCOLESTR newName ) { return S_FALSE; }
HRESULT SnapInDataItem::onSelect( SnapInView& view, BOOL scopeItem, BOOL selected ) { return S_FALSE; }
HRESULT SnapInDataItem::onShow( SnapInView& view, HSCOPEITEM itemId, BOOL selected ) { return S_FALSE; }
HRESULT SnapInDataItem::onToolbarButtonClick( SnapInView& view, int buttonId ) { return S_FALSE; }
HRESULT SnapInDataItem::onToolbarSelect( SnapInView& view, BOOL scopeItem, BOOL selected ) { return S_FALSE; }
HRESULT SnapInDataItem::onViewChange( SnapInView& view, LPARAM data, LPARAM hint ) { return S_FALSE; }
//////////
// IUnknown
//////////
STDMETHODIMP_(ULONG) SnapInDataItem::AddRef() { return InterlockedIncrement(&refCount); }
STDMETHODIMP_(ULONG) SnapInDataItem::Release() { LONG l = InterlockedDecrement(&refCount);
if (l == 0) { delete this; }
return l; }
STDMETHODIMP SnapInDataItem::QueryInterface(REFIID iid, void ** ppvObject) { if (ppvObject == NULL) { return E_POINTER; } else if (iid == __uuidof(SnapInDataItem) || iid == __uuidof(IUnknown) || iid == __uuidof(IDataObject)) { *ppvObject = this; } else { *ppvObject = NULL; return E_NOINTERFACE; }
AddRef(); return S_OK; }
//////////
// IDataObject
//////////
STDMETHODIMP SnapInDataItem::GetData( FORMATETC *pformatetcIn, STGMEDIUM *pmedium ) { return E_NOTIMPL; }
STDMETHODIMP SnapInDataItem::GetDataHere( FORMATETC *pformatetc, STGMEDIUM *pmedium ) {
if (pmedium == NULL) { return E_POINTER; } if (pmedium->tymed != TYMED_HGLOBAL) { return DV_E_TYMED; }
ULONG dataLen; const VOID* data;
if (pformatetc->cfFormat == CCF_ID_NODETYPE) { dataLen = sizeof(GUID); data = getNodeType(); } else if (pformatetc->cfFormat == CCF_ID_DISPLAY_NAME) { dataLen = wcsbytelen(getDisplayName()); data = getDisplayName(); } else if (pformatetc->cfFormat == CCF_ID_SZNODETYPE) { dataLen = wcsbytelen(getSZNodeType()); data = getSZNodeType(); } else if (pformatetc->cfFormat == CCF_ID_SNAPIN_CLASSID) { dataLen = sizeof(GUID); data = getSnapInCLSID(); } else { return DV_E_CLIPFORMAT; }
return WriteDataToHGlobal(pmedium->hGlobal, data, dataLen); }
STDMETHODIMP SnapInDataItem::QueryGetData( FORMATETC *pformatetc ) { return E_NOTIMPL; }
STDMETHODIMP SnapInDataItem::GetCanonicalFormatEtc( FORMATETC *pformatectIn, FORMATETC *pformatetcOut ) { return E_NOTIMPL; }
STDMETHODIMP SnapInDataItem::SetData( FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease ) { return E_NOTIMPL; }
STDMETHODIMP SnapInDataItem::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc ) { return E_NOTIMPL; }
STDMETHODIMP SnapInDataItem::DAdvise( FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection ) { return E_NOTIMPL; }
STDMETHODIMP SnapInDataItem::DUnadvise( DWORD dwConnection ) { return E_NOTIMPL; }
STDMETHODIMP SnapInDataItem::EnumDAdvise( IEnumSTATDATA **ppenumAdvise ) { return E_NOTIMPL; }
SnapInDataItem::~SnapInDataItem() throw () { }
PCWSTR SnapInPreNamedItem::getDisplayName(int column) const throw () { return name; }
HRESULT SnapInView::displayHelp(PCWSTR contextHelpPath) { CComPtr<IDisplayHelp> displayHelp;
HRESULT hr = console->QueryInterface( __uuidof(IDisplayHelp), (PVOID*)&displayHelp ); if (FAILED(hr)) { return hr; }
return displayHelp->ShowTopic(const_cast<LPWSTR>(contextHelpPath)); }
void SnapInView::updateAllViews( SnapInDataItem& item, LPARAM data, INT_PTR hint ) const { CheckError(master->getConsole()->UpdateAllViews(&item, data, hint)); }
void SnapInView::deleteResultItem(const SnapInDataItem& item) const { HRESULTITEM itemId; CheckError(resultData->FindItemByLParam((LPARAM)&item, &itemId)); CheckError(resultData->DeleteItem(itemId, 0)); }
void SnapInView::updateResultItem(const SnapInDataItem& item) const { if (resultData != NULL) { HRESULTITEM itemId; CheckError(resultData->FindItemByLParam((LPARAM)&item, &itemId)); CheckError(resultData->UpdateItem(itemId)); } }
bool SnapInView::isPropertySheetOpen(const SnapInDataItem& item) const { HRESULT hr = sheetProvider->FindPropertySheet( (MMC_COOKIE)&item, const_cast<SnapInView*>(this), const_cast<SnapInDataItem*>(&item) ); CheckError(hr); return hr == S_OK; }
IToolbar* SnapInView::attachToolbar(size_t index) { // Make sure we have a controlbar.
if (!controlbar) { AfxThrowOleException(E_POINTER); }
// Get the entry for this index.
ToolbarEntry& entry = toolbars[index];
// Create the toolbar if necessary.
if (!entry.toolbar) { // Create the toolbar.
CComPtr<IUnknown> unk; CheckError(controlbar->Create(TOOLBAR, this, &unk));
CComPtr<IToolbar> newToolbar; CheckError(unk->QueryInterface(__uuidof(IToolbar), (PVOID*)&newToolbar));
const SnapInToolbarDef& def = *(entry.def);
// Add the bitmaps.
CheckError(newToolbar->AddBitmap( def.nImages, def.hbmp, 16, 16, def.crMask ));
// Add the buttons.
CheckError(newToolbar->AddButtons( def.nButtons, def.lpButtons));
// All went well, so save it away.
entry.toolbar = newToolbar; }
// Attach the toolbar to the controlbar ...
CheckError(controlbar->Attach(TOOLBAR, entry.toolbar));
return entry.toolbar; }
void SnapInView::detachToolbar(size_t index) throw () { if (toolbars[index].toolbar) { // We don't care if this fails, because there's nothing we can do about
// it anyway.
controlbar->Detach(toolbars[index].toolbar); } }
void SnapInView::reSort() const { CheckError(resultData->Sort(sortColumn, sortOption, 0)); }
void SnapInView::formatMessageBox( UINT titleId, UINT formatId, BOOL ignoreInserts, UINT style, int* retval, ... ) { ResourceString title(titleId); ResourceString format(formatId);
HRESULT hr;
if (ignoreInserts) { hr = console->MessageBox( format, title, style, retval ); } else { va_list marker; va_start(marker, retval); PWSTR text; DWORD nchar = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, format, 0, 0, (PWSTR)&text, 4096, &marker ); va_end(marker);
if (!nchar) { AfxThrowLastError(); }
hr = console->MessageBox( text, title, style, retval ); LocalFree(text); }
CheckError(hr); }
void SnapInView::setImageStrip( UINT smallStripId, UINT largeStripId, BOOL scopePane ) { //////////
// Load the bitmaps.
//////////
HBITMAP smallStrip, largeStrip;
smallStrip = LoadBitmap( _Module.GetModuleInstance(), MAKEINTRESOURCE(smallStripId) ); if (smallStrip) { largeStrip = LoadBitmap( _Module.GetModuleInstance(), MAKEINTRESOURCE(largeStripId) ); }
if (!smallStrip || !largeStrip) { AfxThrowLastError(); }
//////////
// Set the image strip.
//////////
HRESULT hr; IImageList* imageList; if (scopePane) { hr = console->QueryScopeImageList(&imageList); } else { hr = console->QueryResultImageList(&imageList); }
if (SUCCEEDED(hr)) { hr = imageList->ImageListSetStrip( (LONG_PTR*)smallStrip, (LONG_PTR*)largeStrip, 0, RGB(255, 0, 255) ); imageList->Release(); }
DeleteObject(smallStrip); DeleteObject(largeStrip);
CheckError(hr); }
STDMETHODIMP_(ULONG) SnapInView::AddRef() { return InternalAddRef(); }
STDMETHODIMP_(ULONG) SnapInView::Release() { ULONG l = InternalRelease(); if (l == 0) { delete this; } return l; }
STDMETHODIMP SnapInView::Initialize(LPCONSOLE lpConsole) { HRESULT hr;
hr = lpConsole->QueryInterface( __uuidof(IConsole2), (PVOID*)&console ); if (FAILED(hr)) { return hr; }
hr = lpConsole->QueryInterface( __uuidof(IHeaderCtrl2), (PVOID*)&headerCtrl ); if (FAILED(hr)) { return hr; }
hr = lpConsole->QueryInterface( __uuidof(sheetProvider), (PVOID*)&sheetProvider ); if (FAILED(hr)) { return hr; }
hr = lpConsole->QueryInterface( __uuidof(IResultData), (PVOID*)&resultData ); if (FAILED(hr)) { return hr; }
return S_OK; }
STDMETHODIMP SnapInView::Destroy(MMC_COOKIE cookie) { resultData.Release(); sheetProvider.Release(); headerCtrl.Release(); console.Release(); nameSpace.Release(); return S_OK; }
STDMETHODIMP SnapInView::GetResultViewType( MMC_COOKIE cookie, LPOLESTR* ppViewType, long* pViewOptions ) { return ((SnapInDataItem*)cookie)->getResultViewType( ppViewType, pViewOptions ); }
STDMETHODIMP SnapInView::GetDisplayInfo( RESULTDATAITEM* pResultDataItem ) {
if (pResultDataItem->mask & RDI_STR) { SnapInDataItem* item = (SnapInDataItem*)(pResultDataItem->lParam); pResultDataItem->str = const_cast<PWSTR>(item->getDisplayName(pResultDataItem->nCol)); } return S_OK; }
STDMETHODIMP SnapInView::Initialize(LPUNKNOWN pUnknown) { HRESULT hr;
CComPtr<IConsoleNameSpace2> initNameSpace; hr = pUnknown->QueryInterface( __uuidof(IConsoleNameSpace2), (PVOID*)&initNameSpace ); if (FAILED(hr)) { return hr; }
CComPtr<IConsole> initConsole; hr = pUnknown->QueryInterface( __uuidof(IConsole), (PVOID*)&initConsole ); if (FAILED(hr)) { return hr; }
hr = internalInitialize(initNameSpace, this); if (FAILED(hr)) { return hr; }
return Initialize(initConsole); }
STDMETHODIMP SnapInView::CreateComponent(LPCOMPONENT* ppComponent) { HRESULT hr;
CComObject<SnapInView>* newComponent; hr = CComObject<SnapInView>::CreateInstance(&newComponent); if (FAILED(hr)) { return hr; }
CComPtr<SnapInView> newView(newComponent);
hr = newView.p->internalInitialize(nameSpace, this); if (FAILED(hr)) { return hr; }
(*ppComponent = newView)->AddRef();
return S_OK; }
STDMETHODIMP SnapInView::Destroy() { return Destroy((MMC_COOKIE)0); }
STDMETHODIMP SnapInView::GetDisplayInfo(SCOPEDATAITEM* pScopeDataItem) { if (pScopeDataItem->mask & SDI_STR) { SnapInDataItem* item = (SnapInDataItem*)(pScopeDataItem->lParam); pScopeDataItem->displayname = const_cast<PWSTR>(item->getDisplayName()); } return S_OK; }
STDMETHODIMP SnapInView::QueryDataObject( MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject ) { if (!IS_SPECIAL_COOKIE(cookie)) { (*ppDataObject = (SnapInDataItem*)cookie)->AddRef(); return S_OK; } else { return S_FALSE; } }
STDMETHODIMP SnapInView::Notify( LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param ) { // Extract the SnapInDataItem.
SnapInDataItem* item; if (IS_SPECIAL_DATAOBJECT(lpDataObject)) { item = NULL; } else { item = SnapInDataItem::narrow(lpDataObject); }
HRESULT hr = S_FALSE; try { if (item) { // If we have a SnapInDataItem, dispatch the notification ...
switch (event) { case MMCN_BTN_CLICK: hr = item->onButtonClick(*this, (MMC_CONSOLE_VERB)param); break; case MMCN_CONTEXTHELP: hr = item->onContextHelp(*this); break; case MMCN_DELETE: hr = item->onDelete(*this); break; case MMCN_DBLCLICK: hr = item->onDoubleClick(*this); break; case MMCN_EXPAND: hr = item->onExpand(*this, (HSCOPEITEM)param, (BOOL)arg); break; case MMCN_REFRESH: hr = item->onRefresh(*this); break; case MMCN_RENAME: hr = item->onRename(*this, (LPOLESTR)param); break; case MMCN_SELECT: hr = item->onSelect(*this, LOWORD(arg), HIWORD(arg)); break; case MMCN_SHOW: hr = item->onShow(*this, (HSCOPEITEM)param, (BOOL)arg); break; case MMCN_VIEW_CHANGE: hr = item->onViewChange(*this, arg, param); break; } } else { // ... otherwise, handle it ourselves.
switch (event) { case MMCN_COLUMN_CLICK: sortColumn = (int)arg; sortOption = (int)param; break;
case MMCN_PROPERTY_CHANGE: { hr = ((SnapInDataItem*)param)->onPropertyChange(*this, arg); break; } } } } CATCH_AND_SAVE(hr);
return hr; }
STDMETHODIMP SnapInView::CompareObjects( LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB ) { return SnapInDataItem::narrow(lpDataObjectA) == SnapInDataItem::narrow(lpDataObjectB) ? S_OK : S_FALSE; }
STDMETHODIMP SnapInView::AddMenuItems( LPDATAOBJECT lpDataObject, LPCONTEXTMENUCALLBACK piCallback, long *pInsertionAllowed ) {
SnapInDataItem* item = SnapInDataItem::narrow(lpDataObject); if (!item) { return S_FALSE; }
HRESULT hr; try { hr = item->addMenuItems(*this, piCallback, *pInsertionAllowed); } CATCH_AND_SAVE(hr);
return hr; }
STDMETHODIMP SnapInView::Command( long lCommandID, LPDATAOBJECT lpDataObject ) {
SnapInDataItem* item = SnapInDataItem::narrow(lpDataObject); if (!item) { return S_FALSE; }
HRESULT hr; try { hr = item->onMenuCommand(*this, lCommandID); } CATCH_AND_SAVE(hr);
return hr; }
STDMETHODIMP SnapInView::ControlbarNotify( MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param ) { // If we don't have a controlbar, there's nothing we can do.
if (!controlbar) { return S_FALSE; }
// Get the IDataObject.
IDataObject* lpDataObject; switch (event) { case MMCN_BTN_CLICK: lpDataObject = (IDataObject*)arg; break; case MMCN_SELECT: lpDataObject = (IDataObject*)param; break; default: lpDataObject = NULL; }
// Convert to a SnapInDataItem.
if (IS_SPECIAL_DATAOBJECT(lpDataObject)) { return S_FALSE; } SnapInDataItem* item = SnapInDataItem::narrow(lpDataObject); if (!item) { return S_FALSE; }
// Dispatch the notification.
HRESULT hr = S_FALSE; try { switch (event) { case MMCN_BTN_CLICK: hr = item->onToolbarButtonClick(*this, param); break; case MMCN_SELECT: hr = item->onToolbarSelect(*this, LOWORD(arg), HIWORD(arg)); break; } } CATCH_AND_SAVE(hr);
return hr; }
STDMETHODIMP SnapInView::SetControlbar( LPCONTROLBAR pControlbar ) { releaseToolbars(); controlbar = pControlbar; return S_OK; }
STDMETHODIMP SnapInView::CreatePropertyPages( LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, LPDATAOBJECT lpDataObject ) {
SnapInDataItem* item = SnapInDataItem::narrow(lpDataObject); if (!item) { return S_FALSE; }
HRESULT hr; try { hr = item->createPropertyPages(*this, lpProvider, handle); } CATCH_AND_SAVE(hr);
return hr; }
STDMETHODIMP SnapInView::QueryPagesFor( LPDATAOBJECT lpDataObject ) {
SnapInDataItem* item = SnapInDataItem::narrow(lpDataObject); return item ? item->queryPagesFor() : S_FALSE; }
STDMETHODIMP SnapInView::GetWatermarks( LPDATAOBJECT lpIDataObject, HBITMAP *lphWatermark, HBITMAP *lphHeader, HPALETTE *lphPalette, BOOL *bStretch ) { return E_NOTIMPL; }
HRESULT SnapInView::Compare( LPARAM lUserParam, MMC_COOKIE cookieA, MMC_COOKIE cookieB, int* pnResult ) { *pnResult = ((SnapInDataItem*)cookieA)->compare( *(SnapInDataItem*)cookieB, *pnResult ); return S_OK; }
const SnapInToolbarDef* SnapInView::getToolbars() const throw () { static SnapInToolbarDef none; return &none; }
SnapInView::SnapInView() throw () : master(NULL), toolbars(NULL), numToolbars(0), sortColumn(0), sortOption(RSI_NOSORTICON) { }
SnapInView::~SnapInView() throw () { releaseToolbars(); delete[] toolbars;
if (master && master != this) { master->Release(); } }
HRESULT SnapInView::internalInitialize( IConsoleNameSpace2* consoleNameSpace, SnapInView* masterView ) throw () { nameSpace = consoleNameSpace;
master = masterView; if (master != this) { master->AddRef(); }
const SnapInToolbarDef* defs = master->getToolbars();
// How many new toolbars are there?
size_t count = 0; while (defs[count].nImages) { ++count; }
if (count) { // Allocate memory ...
toolbars = new (std::nothrow) ToolbarEntry[count]; if (!toolbars) { return E_OUTOFMEMORY; }
// ... and save the definitions. We don't actually create the toolbars
// now. We do this as we need them.
for (size_t i = 0; i < count; ++i) { toolbars[i].def = defs + i; } }
numToolbars = count;
return S_OK; }
void SnapInView::releaseToolbars() throw () { if (controlbar) { for (size_t i = 0; i < numToolbars; ++i) { if (toolbars[i].toolbar) { controlbar->Detach(toolbars[i].toolbar); toolbars[i].toolbar.Release(); } } } }
SnapInPropertyPage::SnapInPropertyPage( UINT nIDTemplate, UINT nIDHeaderTitle, UINT nIDHeaderSubTitle, bool EnableHelp ) : CHelpPageEx(nIDTemplate, 0, nIDHeaderTitle, nIDHeaderSubTitle, EnableHelp), notify(0), param(0), owner(false), applied(false), modified(FALSE) { if (!nIDHeaderTitle) { m_psp.dwFlags |= PSP_HIDEHEADER; } }
SnapInPropertyPage::SnapInPropertyPage( LONG_PTR notifyHandle, LPARAM notifyParam, bool deleteHandle, UINT nIDTemplate, UINT nIDCaption, bool EnableHelp ) : CHelpPageEx(nIDTemplate, nIDCaption, EnableHelp), notify(notifyHandle), param(notifyParam), owner(deleteHandle), applied(false), modified(FALSE) { }
SnapInPropertyPage::~SnapInPropertyPage() throw () { if (owner && notify) { MMCFreeNotifyHandle(notify); } }
void SnapInPropertyPage::addToMMCSheet(IPropertySheetCallback* cback) { // Swap our callback for the MFC supplied one.
mfcCallback = m_psp.pfnCallback; m_psp.pfnCallback = propSheetPageProc; m_psp.lParam = (LPARAM)this;
HRESULT hr = MMCPropPageCallback(&m_psp); if (SUCCEEDED(hr)) { HPROPSHEETPAGE page = CreatePropertySheetPage(&m_psp); if (page) { hr = cback->AddPage(page); if (FAILED(hr)) { DestroyPropertySheetPage(page); } } else { // GetLastError() doesn't work with CreatePropertySheetPage.
hr = E_UNEXPECTED; } }
if (FAILED(hr)) { delete this; }
CheckError(hr); }
void SnapInPropertyPage::DoDataExchange(CDataExchange* pDX) { pDX->m_bSaveAndValidate ? getData() : setData(); }
BOOL SnapInPropertyPage::OnApply() { // If we've been modified, ...
if (modified) { try { // Save the changes.
saveChanges(); } catch (CException* e) { // Bring up a message box.
reportException(e);
// We're in an indeterminate state, so we can't cancel.
CancelToClose();
// Block the apply.
return FALSE; }
// Notify MMC if necessary.
if (notify) { MMCPropertyChangeNotify(notify, param); }
// Set our flags.
applied = true; modified = FALSE; } return TRUE; }
BOOL SnapInPropertyPage::OnWizardFinish() { try { saveChanges(); } catch (CException* e) { // Bring up a message box.
reportException(e);
// Disable all the buttons. Something's wrong, so we'll only let the user
// cancel.
::PostMessageW( ::GetParent(m_hWnd), PSM_SETWIZBUTTONS, 0, (LPARAM)(DWORD)PSWIZB_DISABLEDFINISH );
return FALSE; }
return TRUE; }
void SnapInPropertyPage::OnReset() { // If we've been modified, ...
if (modified) { // ... discard the changes.
discardChanges(); modified = FALSE; } }
void SnapInPropertyPage::SetModified(BOOL bChanged) { modified = bChanged; CHelpPageEx::SetModified(bChanged); }
void SnapInPropertyPage::getData() { }
void SnapInPropertyPage::setData() { }
void SnapInPropertyPage::saveChanges() { }
void SnapInPropertyPage::discardChanges() { }
void SnapInPropertyPage::enableControl(int controlId, bool enable) { ::EnableWindow(::GetDlgItem(m_hWnd, controlId), (enable ? TRUE : FALSE)); }
void SnapInPropertyPage::fail(int controlId, UINT errorText, bool isEdit) { failNoThrow(controlId, errorText, isEdit);
AfxThrowUserException(); }
void SnapInPropertyPage::failNoThrow(int controlId, UINT errorText, bool isEdit) { // Give the offending control the focus.
HWND ctrl = ::GetDlgItem(m_hWnd, controlId); ::SetFocus(ctrl); if (isEdit) { ::SendMessage(ctrl, EM_SETSEL, 0, -1); }
// Bring up a message box.
reportError(errorText); }
void SnapInPropertyPage::initControl(int controlId, CWnd& control) { if (control.m_hWnd == NULL) { if (!control.SubclassWindow(::GetDlgItem(m_hWnd, controlId))) { AfxThrowNotSupportedException(); } } }
void SnapInPropertyPage::onChange() { SetModified(); }
void SnapInPropertyPage::reportError(UINT errorText) { // Bring up a message box.
MessageBox( ResourceString(errorText), ResourceString(getErrorCaption()), MB_ICONWARNING ); }
void SnapInPropertyPage::reportException(CException* e) { // Get the error message.
WCHAR errorText[256]; e->GetErrorMessage(errorText, sizeof(errorText)/sizeof(errorText[0])); e->Delete();
// Bring up a message box.
MessageBox( errorText, ResourceString(getErrorCaption()), MB_ICONERROR ); }
void SnapInPropertyPage::setLargeFont(int controlId) { static CFont largeFont;
CWnd* ctrl = GetDlgItem(controlId); if (ctrl) { // If we don't have the large font yet, ...
if (!(HFONT)largeFont) { // ... create it.
largeFont.CreatePointFont( 10 * _wtoi(ResourceString(IDS_LARGE_FONT_SIZE)), ResourceString(IDS_LARGE_FONT_NAME) ); }
ctrl->SetFont(&largeFont); } }
void SnapInPropertyPage::showControl(int controlId, bool show) { CWnd* ctrl = GetDlgItem(controlId); if (ctrl) { show ? ctrl->ModifyStyle(0, WS_VISIBLE) : ctrl->ModifyStyle(WS_VISIBLE, 0); } }
void SnapInPropertyPage::getValue( int controlId, LONG& value, UINT errorText ) { WCHAR buffer[32]; int len = GetDlgItemText(controlId, buffer, 32);
// We'll fail anything that's longer than 30 characters. This is an
// arbitrary bound. We just need to make sure that buffer is long enough to
// hold any valid integer plus a little whitespace.
if (len == 0 || len > 30) { fail(controlId, errorText); }
// Skip any leading whitespace.
PWSTR sz = buffer; while (*sz == L' ' || *sz == L'\t') { ++sz; }
// Save the first non-whitespace character.
WCHAR first = *sz;
// Convert the integer.
value = wcstol(sz, &sz, 10);
// Skip any trailing whitespace.
while (*sz == L' ' || *sz == L'\t') { ++sz; }
// Make sure all went well.
if ((value == 0 && first != L'0') || *sz != L'\0' || value == LONG_MIN || value == LONG_MAX) { fail(controlId, errorText); } }
void SnapInPropertyPage::setValue( int controlId, LONG value ) { WCHAR buffer[12]; SetDlgItemText(controlId, _ltow(value, buffer, 10)); }
void SnapInPropertyPage::getValue( int controlId, bool& value ) { value = IsDlgButtonChecked(controlId) != 0; }
void SnapInPropertyPage::setValue( int controlId, bool value ) { CheckDlgButton(controlId, (value ? BST_CHECKED : BST_UNCHECKED)); }
void SnapInPropertyPage::getValue( int controlId, CComBSTR& value, bool trim ) { HWND hwnd = ::GetDlgItem(m_hWnd, controlId);
int len = ::GetWindowTextLength(hwnd); SysFreeString(value.m_str); value.m_str = SysAllocStringLen(NULL, len); if (!value) { AfxThrowMemoryException(); }
::GetWindowTextW(hwnd, value, len + 1);
if (trim) { SdoTrimBSTR(value); } }
void SnapInPropertyPage::setValue( int controlId, PCWSTR value ) { SetDlgItemText(controlId, value); }
void SnapInPropertyPage::getRadio( int firstId, int lastId, LONG& value ) { value = GetCheckedRadioButton(firstId, lastId); value = value ? value - firstId : -1; }
void SnapInPropertyPage::setRadio( int firstId, int lastId, LONG value ) { CheckRadioButton(firstId, lastId, firstId + value); }
UINT CALLBACK SnapInPropertyPage::propSheetPageProc( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp ) throw () { SnapInPropertyPage* page = (SnapInPropertyPage*)(ppsp->lParam);
UINT retval = page->mfcCallback(hwnd, uMsg, ppsp);
if (uMsg == PSPCB_RELEASE) { delete page; }
return retval; }
|