xpmgr/BuildTools/Include/UIRibbonPropertyHelpers.h

227 lines
8.2 KiB
C++

//****************************************************************************
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: UIRibbonPropertyHelpers.h
//
// Contents: Property helper functions for the Windows Ribbon Framework
//
//****************************************************************************
#pragma once
#include <propvarutil.h>
interface IUIImage;
#ifndef TUIPROPERTYKEYDEFINED
// A version of PROPERTYKEY whose VARTYPE can be tested at compile time.
#include <pshpack8.h>
template<VARTYPE T>
struct TUIPROPERTYKEY
{
GUID fmtid;
DWORD pid;
inline operator const PROPERTYKEY&() const { return reinterpret_cast<const PROPERTYKEY&>(*this); }
inline const PROPERTYKEY* operator&() const { return reinterpret_cast<const PROPERTYKEY*>(this); }
};
#include <poppack.h>
C_ASSERT(sizeof(TUIPROPERTYKEY<VT_BOOL>) == sizeof(PROPERTYKEY));
#define TUIPROPERTYKEYDEFINED
#endif // TUIPROPERTYKEYDEFINED
// UIBreakCheckType is being used to do both Compilation and Runtime checking of types on PROPVARIANTs
struct UIWrongType {};
template<class A, VARTYPE B>
struct UIBreakCheckType
{
// If a PROPERTYKEY/type combination is invalid, compilation will break (it will try to cast a bool to UIWrongType)
typedef UIWrongType _Type;
static bool Validate(REFPROPERTYKEY key) { UNREFERENCED_PARAMETER(key); return false; }
};
#define UI_REGISTER_TYPE( type ) \
template<> struct UIBreakCheckType< TUIPROPERTYKEY<type>, type > \
{ \
typedef bool _Type; \
static bool Validate(REFPROPERTYKEY key) { UNREFERENCED_PARAMETER(key); return true; } \
}; \
template<> struct UIBreakCheckType< PROPERTYKEY, type > \
{ \
typedef bool _Type; \
/* we cannot catch at compilation time when PROPERTYKEYs are by reference, so check at runtime */ \
static bool Validate(REFPROPERTYKEY key) { return (type) == key.pid; }\
};
// Register known types
UI_REGISTER_TYPE( VT_BOOL )
UI_REGISTER_TYPE( VT_UI4 )
UI_REGISTER_TYPE( VT_LPWSTR )
UI_REGISTER_TYPE( VT_DECIMAL )
UI_REGISTER_TYPE( VT_UNKNOWN )
UI_REGISTER_TYPE( VT_ARRAY|VT_UNKNOWN )
//======================================================================================
// PROPVARIANT initializer helpers
template<class T>
HRESULT UIInitPropertyFromBoolean(const T& propertyKey, BOOL fVal, __out PROPVARIANT* pPropVar)
{
// If this fails to compile, it means this property is not of type VT_BOOL
UIBreakCheckType<T, VT_BOOL>::_Type valid = UIBreakCheckType<T, VT_BOOL>::Validate(propertyKey);
return valid ? InitPropVariantFromBoolean(fVal, pPropVar) : E_INVALIDARG;
}
template<class T>
HRESULT UIInitPropertyFromUInt32(const T& propertyKey, UINT ulVal, __out PROPVARIANT* pPropVar)
{
// If this fails to compile, it means this property is not of type VT_UI4
UIBreakCheckType<T, VT_UI4>::_Type valid = UIBreakCheckType<T, VT_UI4>::Validate(propertyKey);
return valid ? InitPropVariantFromUInt32(ulVal, pPropVar) : E_INVALIDARG;
}
template<class T>
HRESULT UIInitPropertyFromString(const T& propertyKey, __in PCWSTR psz, __out PROPVARIANT* pPropVar)
{
// If this fails to compile, it means this property is not of type VT_LPWSTR
UIBreakCheckType<T, VT_LPWSTR>::_Type valid = UIBreakCheckType<T, VT_LPWSTR>::Validate(propertyKey);
return valid ? InitPropVariantFromString(psz, pPropVar) : E_INVALIDARG;
}
template<class T>
HRESULT UIInitPropertyFromDecimal(const T& propertyKey, const DECIMAL& decValue, __out PROPVARIANT* pPropVar)
{
// If this fails to compile, it means this property is not of type VT_DECIMAL
UIBreakCheckType<T, VT_DECIMAL>::_Type valid = UIBreakCheckType<T, VT_DECIMAL>::Validate(propertyKey);
if (valid)
{
// Must set decVal before vt because the two overlap.
pPropVar->decVal = decValue;
pPropVar->vt = VT_DECIMAL;
return S_OK;
}
return E_INVALIDARG;
}
template<class T>
HRESULT UIInitPropertyFromInterface(const T& propertyKey, __in IUnknown* pUnk, __out PROPVARIANT* pPropVar)
{
// If this fails to compile, it means this property is not of type VT_UNKNOWN
UIBreakCheckType<T, VT_UNKNOWN>::_Type valid = UIBreakCheckType<T, VT_UNKNOWN>::Validate(propertyKey);
if (valid)
{
pPropVar->vt = VT_UNKNOWN;
pPropVar->punkVal = pUnk;
if (pUnk)
{
pUnk->AddRef();
}
return S_OK;
}
return E_INVALIDARG;
}
template<class T>
HRESULT UIInitPropertyFromImage(const T& propertyKey, __in IUIImage* pImage, __out PROPVARIANT* pPropVar)
{
return UIInitPropertyFromInterface(propertyKey, pImage, pPropVar);
}
template<class T>
HRESULT UIInitPropertyFromIUnknownArray(const T& propertyKey, __in SAFEARRAY* psa, __out PROPVARIANT* pPropVar)
{
// If this fails to compile, it means this property is not of type VT_ARRAY
UIBreakCheckType<T, VT_ARRAY|VT_UNKNOWN>::_Type valid = UIBreakCheckType<T, VT_ARRAY|VT_UNKNOWN>::Validate(propertyKey);
if (valid && (psa->fFeatures & FADF_UNKNOWN) )
{
HRESULT hr = ::SafeArrayCopy(psa, &pPropVar->parray);
if (SUCCEEDED(hr))
{
pPropVar->vt = VT_ARRAY|VT_UNKNOWN;
}
return hr;
}
return E_INVALIDARG;
}
//======================================================================================
// Extract value from PROPVARIANT
template<class T>
HRESULT UIPropertyToBoolean(const T& propertyKey, REFPROPVARIANT propvarIn, __out BOOL *pfRet)
{
// If this fails to compile, it means this property is not of type VT_BOOL
UIBreakCheckType<T, VT_BOOL>::_Type valid = UIBreakCheckType<T, VT_BOOL>::Validate(propertyKey);
return valid ? PropVariantToBoolean(propvarIn, pfRet) : E_INVALIDARG;
}
template<class T>
HRESULT UIPropertyToUInt32(const T& propertyKey, REFPROPVARIANT propvarIn, __out UINT *pulVal)
{
// If this fails to compile, it means this property is not of type VT_UI4
UIBreakCheckType<T, VT_UI4>::_Type valid = UIBreakCheckType<T, VT_UI4>::Validate(propertyKey);
return valid ? PropVariantToUInt32(propvarIn, pulVal) : E_INVALIDARG;
}
// Allocate a new string and return it in ppszOut
template<class T>
HRESULT UIPropertyToStringAlloc(const T& propertyKey, REFPROPVARIANT propvarIn, __deref_out PWSTR *ppszOut)
{
// If this fails to compile, it means this property is not of type VT_LPWSTR
UIBreakCheckType<T, VT_LPWSTR>::_Type valid = UIBreakCheckType<T, VT_LPWSTR>::Validate(propertyKey);
return valid ? PropVariantToStringAlloc(propvarIn, ppszOut) : E_INVALIDARG;
}
template<class T>
HRESULT UIPropertyToDecimal(const T& propertyKey, REFPROPVARIANT propvarIn, __out DECIMAL *pDecValue)
{
// If this fails to compile, it means this property is not of type VT_DECIMAL
UIBreakCheckType<T, VT_DECIMAL>::_Type valid = UIBreakCheckType<T, VT_DECIMAL>::Validate(propertyKey);
if (valid && propvarIn.vt == VT_DECIMAL)
{
*pDecValue = propvarIn.decVal;
return S_OK;
}
return E_INVALIDARG;
}
template<class T, class TInterface>
HRESULT UIPropertyToInterface(const T& propertyKey, REFPROPVARIANT propvarIn, __deref_out TInterface** ppObj)
{
*ppObj = NULL;
// If this fails to compile, it means this property is not of type VT_UNKNOWN
UIBreakCheckType<T, VT_UNKNOWN>::_Type valid = UIBreakCheckType<T, VT_UNKNOWN>::Validate(propertyKey);
if (valid && propvarIn.vt == VT_UNKNOWN)
{
if (propvarIn.punkVal)
{
return propvarIn.punkVal->QueryInterface(__uuidof(TInterface), (void**)ppObj);
}
return S_OK;
}
return E_INVALIDARG;
}
template<class T>
HRESULT UIPropertyToImage(const T& propertyKey, REFPROPVARIANT propvarIn, __deref_out IUIImage** ppImage)
{
return UIPropertyToInterface(propertyKey, propvarIn, ppImage);
}
template<class T>
HRESULT UIPropertyToIUnknownArrayAlloc(const T& propertyKey, REFPROPVARIANT propvarIn, __deref_out SAFEARRAY** ppsa)
{
// If this fails to compile, it means this property is not of type VT_ARRAY
UIBreakCheckType<T, VT_ARRAY|VT_UNKNOWN>::_Type valid = UIBreakCheckType<T, VT_ARRAY|VT_UNKNOWN>::Validate(propertyKey);
if (valid && propvarIn.vt == (VT_ARRAY|VT_UNKNOWN) )
{
return ::SafeArrayCopy(propvarIn.parray, ppsa);
}
return E_INVALIDARG;
}