Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
So, this code should eventually make it to the VistaBridge Windows SDK code sample (" no official support" ) . It's in C++/CLI as it uses macros and templates quite a lot...
It is really a beta version as I’d love to have other people use it and tell me what’s wrong or missing.
I’m including here the code without most property macro (they are 800+ !) but you can download the zip file and examine it.
As you can see below, you can access the properties by name or by PropertyKey (in case its’a custom one):
PropertyKey pk = new PropertyKey(new Guid("F29F85E0-4FF9-1068-AB91-08002B27B3D9"), 6);
using (ItemPropertySet ips = new ItemPropertySet(textboxPath.Text, GetPropertyStoreFlag.ReadWrite)) {
object o = ips.GetValue(pk);
string comment = o as string;
System.Diagnostics.Debug.Assert(comment == ips.Comment);
ips.Comment = "A first comment to test the writing of property";
System.Diagnostics.Debug.Assert(ips.Comment == (string) ips.GetValue(pk));
}
using (ItemPropertySet ips = new ItemPropertySet(textboxPath.Text, GetPropertyStoreFlag.ReadWrite)) {
ips.SetValue(pk, "A second comment to test the writing of property");
}
The C++/CLI code:
#include "stdafx.h"
using namespace System::Runtime::InteropServices;
using namespace System;
// ********************************************************************************
// *
// * The VariantType template class helps mapping the VARTYPE (e.g. VT_LPWSTR) to a
// * CLR type (e.g. String ^).
// *
// ********************************************************************************
template <typename T>
class VariantType {
public:
const static VARTYPE vartype;
};
template <typename T>
const VARTYPE VariantType<T>::vartype = VT_ILLEGAL;
const VARTYPE VariantType<Int16>::vartype = VT_I2;
const VARTYPE VariantType<Int32>::vartype = VT_I4;
const VARTYPE VariantType<Byte>::vartype = VT_UI1;
const VARTYPE VariantType<UInt16>::vartype = VT_UI2;
const VARTYPE VariantType<UInt32>::vartype = VT_UI4;
const VARTYPE VariantType<UInt64>::vartype = VT_UI8;
const VARTYPE VariantType<Double>::vartype = VT_R8;
const VARTYPE VariantType<bool>::vartype = VT_BOOL;
const VARTYPE VariantType<ComTypes::FILETIME>::vartype = VT_FILETIME;
const VARTYPE VariantType<Guid>::vartype = VT_CLSID;
const VARTYPE VariantType<String ^>::vartype = VT_LPWSTR;
// ********************************************************************************
// *
// * Overloaded GetValueFromPropertyVariant functions to help with the mapping from PROPVARIANT.
// *
// ********************************************************************************
static HRESULT GetValue(const PROPVARIANT & propertyVariant, Byte % value) {
if (propertyVariant.vt == VT_UI1) {
value = propertyVariant.bVal;
return S_OK;
}
return E_INVALIDARG;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, Int16 % value) {
SHORT i16;
HRESULT hr = PropVariantGetInt16Elem(propertyVariant, 0, & i16);
if SUCCEEDED(hr)
value = i16;
return hr;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, Int32 % value) {
LONG i32;
HRESULT hr = PropVariantGetInt32Elem(propertyVariant, 0, & i32);
if SUCCEEDED(hr)
value = i32;
return hr;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, UInt16 % value) {
USHORT ui16;
HRESULT hr = PropVariantGetUInt16Elem(propertyVariant, 0, & ui16);
if SUCCEEDED(hr)
value = ui16;
return hr;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, UInt32 % value) {
ULONG ui32;
HRESULT hr = PropVariantGetUInt32Elem(propertyVariant, 0, & ui32);
if SUCCEEDED(hr)
value = ui32;
return hr;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, UInt64 % value) {
ULONGLONG ui64;
HRESULT hr = PropVariantGetUInt64Elem(propertyVariant, 0, & ui64);
if SUCCEEDED(hr)
value = ui64;
return hr;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, Double % value) {
Double d;
HRESULT hr = PropVariantGetDoubleElem(propertyVariant, 0, & d);
if SUCCEEDED(hr)
value = d;
return hr;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, bool % value) {
BOOL b;
HRESULT hr = PropVariantGetBooleanElem(propertyVariant, 0, & b);
if SUCCEEDED(hr)
value = (b != FALSE);
return hr;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, ComTypes::FILETIME % value) {
::FILETIME filetime;
HRESULT hr = PropVariantGetFileTimeElem(propertyVariant, 0, & filetime);
if SUCCEEDED(hr) {
value.dwHighDateTime = filetime.dwHighDateTime;
value.dwLowDateTime = filetime.dwLowDateTime;
}
return hr;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, System::Guid % value) {
CLSID clsid;
HRESULT hr = PropVariantToCLSID(propertyVariant, & clsid);
if SUCCEEDED(hr) {
value = Guid( clsid.Data1, clsid.Data2, clsid.Data3, clsid.Data4[0], clsid.Data4[1], clsid.Data4[2], clsid.Data4[3], clsid.Data4[4], clsid.Data4[5], clsid.Data4[6], clsid.Data4[7]);
}
return hr;
}
static HRESULT GetValue(const PROPVARIANT & propertyVariant, String ^ % value) {
BSTR bstr;
HRESULT hr = PropVariantToBSTR(propertyVariant,& bstr);
if SUCCEEDED(hr) {
try {
value = System::Runtime::InteropServices::Marshal::PtrToStringBSTR( (IntPtr) bstr);
} finally {
SysFreeString(bstr);
}
}
return hr;
}
// ********************************************************************************
// *
// * GetValueFromPropertyVariant template functions
// *
// ********************************************************************************
template <typename T>
static void GetValueFromPropertyVariant(const PROPVARIANT & propertyVariant, T % element) {
if (propertyVariant.vt != VariantType<T>::vartype)
throw gcnew Exception(String::Format("Wrong property VARTYPE (expected {0}, actual {1})", VariantType<T>::vartype, propertyVariant.vt));
Tif(GetValue(propertyVariant, element));
}
template <typename T>
static void GetValueFromPropertyVariant(const PROPVARIANT & propertyVariant, array<T> ^ % elements) {
ULONG count = PropVariantGetElementCount(propertyVariant);
if (count) {
elements = gcnew array<T>(count);
for(ULONG i = 0; i < count; i++) {
PROPVARIANT propertyVariantElement;
try {
Tif(PropVariantGetElem(propertyVariant, i, & propertyVariantElement));
Tif(GetValue(propertyVariantElement, elements[i]));
} finally {
PropVariantClear(& propertyVariantElement);
}
}
} else {
elements = nullptr;
}
}
// ********************************************************************************
// *
// * SetPropertyVariant functions
// *
// ********************************************************************************
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, Double % value) {
return InitPropVariantFromDouble(value,propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, const Double * valueArray, ULONG elementCount) {
return InitPropVariantFromDoubleVector(valueArray, elementCount, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, Byte % value) {
propertyVariant->vt = VT_UI1;
propertyVariant->bVal = value;
return S_OK;
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, bool % value) {
return InitPropVariantFromBoolean(value,propertyVariant); // the bool will be converted to a BOOL when pushing the value on the stack
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, const bool * valueArray, ULONG elementCount) {
// Double marshalling from Boolean on the managed heap before entering here, then from
// bool on the native heap to BOOL on the native heap!
BOOL * p = new BOOL[elementCount];
BOOL * to = p;
const bool * from = valueArray;
try {
for(ULONG l = 0; l < elementCount; l++) {
*to++ = *from++;
}
return InitPropVariantFromBooleanVector(p, elementCount, propertyVariant);
} finally {
delete [] p;
}
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, Int16 % value) {
return InitPropVariantFromInt16(value, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, const Int16 * valueArray, ULONG elementCount) {
return InitPropVariantFromInt16Vector(valueArray, elementCount, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, Int32 % value) {
return InitPropVariantFromInt32(value, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, const Int32 * valueArray, ULONG elementCount) {
return InitPropVariantFromInt32Vector(reinterpret_cast<LONG *>(const_cast<Int32 *>(valueArray)), elementCount, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, UInt16 % value) {
return InitPropVariantFromUInt16(value, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, const UInt16 * valueArray, ULONG elementCount) {
return InitPropVariantFromUInt16Vector(valueArray, elementCount, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, UInt32 % value) {
return InitPropVariantFromUInt32(value, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, const UInt32 * valueArray, ULONG elementCount) {
return InitPropVariantFromUInt32Vector(reinterpret_cast<ULONG *>(const_cast<UInt32 *>(valueArray)), elementCount, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, UInt64 % value) {
return InitPropVariantFromUInt64(value, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, const UInt64 * valueArray, ULONG elementCount) {
return InitPropVariantFromUInt64Vector(valueArray, elementCount, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, ComTypes::FILETIME % value) {
pin_ptr<ComTypes::FILETIME> filetime = & value;
return InitPropVariantFromFileTime(reinterpret_cast<::FILETIME *>(filetime),propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, const ::FILETIME * valueArray, ULONG elementCount) {
return InitPropVariantFromFileTimeVector(valueArray, elementCount, propertyVariant);
}
static HRESULT SetPropertyVariant(PROPVARIANT * propertyVariant, Guid % value) {
// How to: Convert Between System::Guid and _GUID
// https://msdn2.microsoft.com/en-us/library/wb8scw8f(VS.80).aspx
pin_ptr<Byte> p = & value.ToByteArray()[0]; // pin_ptr<Guid> p = & value;
CLSID & clsid = *reinterpret_cast<CLSID *>(p);
p = nullptr;
return InitPropVariantFromCLSID(clsid, propertyVariant);
}
// ********************************************************************************
// *
// * SetPropertyVariantFromValue [template] functions
// *
// ********************************************************************************
static void SetPropertyVariantFromValue(PROPVARIANT * propertyVariant, String ^ % value) {
pin_ptr<const wchar_t> p = PtrToStringChars(value);
Tif(InitPropVariantFromString(p,propertyVariant));
p = nullptr;
if (propertyVariant->vt != VT_EMPTY && !(propertyVariant->vt & VariantType<String ^>::vartype))
throw gcnew Exception(String::Format("Wrong property VARTYPE (expected {0}, actual {1})", VariantType<String ^>::vartype, propertyVariant->vt));
}
template <typename T>
static void SetPropertyVariantFromValue(PROPVARIANT * propertyVariant, Nullable<T> % value) {
Tif(SetPropertyVariant(propertyVariant, value.Value));
if (propertyVariant->vt != VariantType<T>::vartype)
throw gcnew Exception(String::Format("Wrong property VARTYPE (expected {0}, actual {1})", VariantType<T>::vartype, propertyVariant->vt));
}
static void SetPropertyVariantFromValue(PROPVARIANT * propertyVariant, array<String ^> ^ % arrayValue) {
Text::StringBuilder sb;
for each( String ^ s in arrayValue) {
sb.Append(s);
sb.Append(';');
}
String ^ s = sb.ToString();
pin_ptr<const wchar_t> p = PtrToStringChars(s);
Tif(InitPropVariantFromStringAsVector(p,propertyVariant));
}
static void SetPropertyVariantFromValue(PROPVARIANT * /*propertyVariant*/, array<Byte> ^ % /*arrayValue*/) {
throw gcnew InvalidOperationException(); // TODO: implement
}
static void SetPropertyVariantFromValue(PROPVARIANT * propertyVariant, array<ComTypes::FILETIME> ^ % arrayValue) {
::FILETIME * p = new ::FILETIME[arrayValue->Length];
try {
unsigned int u = 0;
for each(ComTypes::FILETIME value in arrayValue) {
// Doing that way, we don't have to pin the whole array
p[u].dwHighDateTime = value.dwHighDateTime;
p[u++].dwLowDateTime = value.dwLowDateTime;
}
Tif(SetPropertyVariant(propertyVariant, p, arrayValue->Length));
} finally {
delete [] p;
}
}
template <typename T>
static void SetPropertyVariantFromValue(PROPVARIANT * propertyVariant, array<T> ^ % arrayValue) {
T * p = new T[arrayValue->Length];
try {
unsigned int u = 0;
for each(T value in arrayValue) {
p[u++] = value;
}
Tif(SetPropertyVariant(propertyVariant, p, arrayValue->Length));
} finally {
delete [] p;
}
}
// ********************************************************************************
// * PropertyTypeHolder template is a trick to help with the writing of
// * one and only one ItemPropertySet::[Get|Set]Value() template.
// * It works with value type and reference type (including array).
// ********************************************************************************
template <typename PVT, bool IS_REFERENCE_TYPE = __is_ref_array(PVT) || cliext::is_handle<PVT>::value>
ref class PropertyTypeHolder;
template <typename PVT>
ref class PropertyTypeHolder<PVT, true> {
public:
typedef PVT type;
static PVT null = nullptr;
static bool IsNull(type o) {return o == null;}
};
template <typename PVT>
ref class PropertyTypeHolder<PVT, false> {
public:
typedef Nullable<PVT> type;
static Nullable<PVT> null;
static bool IsNull(type % o) {return ! o.HasValue;}
};
namespace Microsoft { namespace SDK { namespace Samples { namespace VistaBridge { namespace Library { namespace Shell {
// ********************************************************************************
// *
// * PropertyKey managed value class
// *
// ********************************************************************************
public value class PropertyKey {
internal:
PROPERTYKEY Native() {
pin_ptr<Byte> p = & PropertyGuid.ToByteArray()[0];
PROPERTYKEY propertyKey = {*reinterpret_cast<CLSID *>(p), PropertyIdentifier};
return propertyKey;
}
public:
PropertyKey(Guid propertyGuid) : PropertyGuid(propertyGuid), PropertyIdentifier(PID_FIRST_USABLE) {
}
PropertyKey(Guid propertyGuid, UInt32 propertyIdentifier) : PropertyGuid(propertyGuid), PropertyIdentifier(propertyIdentifier) {
}
Guid PropertyGuid;
UInt32 PropertyIdentifier;
};
// ********************************************************************************
// *
// * ItemPropertySet managed reference class
// *
// ********************************************************************************
public ref class ItemPropertySet {
private:
IPropertyStore * _propertyStore;
bool _needCommit;
protected:
void Init(String ^ path, GetPropertyStoreFlag flag) {
IShellItem2Ptr shellItem;
HRESULT hr;
pin_ptr<const wchar_t> f = PtrToStringChars(path);
hr = SHCreateItemFromParsingName(f, NULL, IID_PPV_ARGS(& shellItem));
f = nullptr;
if FAILED(hr)
throw gcnew Exception( String::Format("Error creating the Shell Item for \"{0}\".", path));
void * v;
Tif(shellItem->GetPropertyStore(reinterpret_cast<GETPROPERTYSTOREFLAGS &>(flag), IID_IPropertyStore, & v));
_propertyStore = static_cast<IPropertyStore *>(v);
}
template <typename T>
void SetValue(const PROPERTYKEY & propertyKey, typename PropertyTypeHolder<T>::type % value) {
if(IsNotWritable(propertyKey))
throw gcnew InvalidOperationException("This property is not writable");
PROPVARIANT propertyVariant;
try {
if (PropertyTypeHolder<T>::IsNull(value))
propertyVariant.vt = VT_EMPTY;
else {
SetPropertyVariantFromValue(& propertyVariant, value);
}
Tif(_propertyStore->SetValue(propertyKey, propertyVariant));
_needCommit = true;
} finally {
PropVariantClear(& propertyVariant);
}
}
template <typename T>
typename PropertyTypeHolder<T>::type GetValue(const PROPERTYKEY & propertyKey) {
PROPVARIANT propertyVariant;
Tif(_propertyStore->GetValue(propertyKey, & propertyVariant));
try {
if (propertyVariant.vt == VT_EMPTY)
return PropertyTypeHolder<T>::null;
typename T propertyValue;
GetValueFromPropertyVariant(propertyVariant, propertyValue);
return propertyValue;
} finally {
PropVariantClear(& propertyVariant);
}
}
bool IsNotWritable(const PROPERTYKEY & propertyKey) {
IPropertyStoreCapabilitiesPtr propertyStoreCapabilities;
return SUCCEEDED(_propertyStore->QueryInterface(IID_PPV_ARGS(& propertyStoreCapabilities)))
&& S_FALSE == propertyStoreCapabilities->IsPropertyWritable(propertyKey);
}
public:
ItemPropertySet(String ^ path, GetPropertyStoreFlag flag) {
Init(path, flag);
}
ItemPropertySet(String ^ path) {
Init(path, GetPropertyStoreFlag::Default);
}
~ItemPropertySet() {
ItemPropertySet::!ItemPropertySet();
}
!ItemPropertySet() {
if (_needCommit) {
System::Diagnostics::Debug::WriteLine("ItemPropertySet instance did not call Commit() although it might have needed to.");
_needCommit = false;
}
if (_propertyStore)
_propertyStore->Release();
}
bool IsNotWritable(PropertyKey propertyKey) {
return IsNotWritable(propertyKey.Native());
}
Object ^ GetValue(PropertyKey managedPropertyKey) {
PROPVARIANT propertyVariant;
Tif(_propertyStore->GetValue(managedPropertyKey.Native(), & propertyVariant));
if (propertyVariant.vt == VT_EMPTY)
return nullptr;
try {
if (propertyVariant.vt & VT_VECTOR) {
#pragma push_macro("HANDLE_CASE")
#define HANDLE_CASE(T) case VariantType<T>::vartype: {array<T> ^ t; ::GetValueFromPropertyVariant(propertyVariant, t); return t;}
switch (propertyVariant.vt & ~VT_VECTOR) {
HANDLE_CASE(Byte)
HANDLE_CASE(UInt16)
HANDLE_CASE(UInt32)
HANDLE_CASE(UInt64)
HANDLE_CASE(Int16)
HANDLE_CASE(Int32)
HANDLE_CASE(Double)
HANDLE_CASE(bool)
HANDLE_CASE(ComTypes::FILETIME)
HANDLE_CASE(Guid)
HANDLE_CASE(String ^)
}
#undef HANDLE_CASE
} else {
#define HANDLE_CASE(T) case VariantType<T>::vartype: {T t; Tif(::GetValue(propertyVariant, t)); return t;}
switch (propertyVariant.vt) {
HANDLE_CASE(Byte)
HANDLE_CASE(UInt16)
HANDLE_CASE(UInt32)
HANDLE_CASE(UInt64)
HANDLE_CASE(Int16)
HANDLE_CASE(Int32)
HANDLE_CASE(Double)
HANDLE_CASE(bool)
HANDLE_CASE(ComTypes::FILETIME)
HANDLE_CASE(Guid)
HANDLE_CASE(String ^)
}
#undef HANDLE_CASE
#pragma pop_macro("HANDLE_CASE")
}
} finally {
PropVariantClear(& propertyVariant);
}
throw gcnew InvalidOperationException(String::Format("Unsupported type ({0})", propertyVariant.vt));
}
Object ^ GetValue(Guid propertyGuid, UInt32 propertyIdentifier) {
return GetValue(PropertyKey(propertyGuid,propertyIdentifier));
}
void Commit() {
if (_needCommit) {
Tif(_propertyStore->Commit());
_needCommit = false;
} else {
System::Diagnostics::Debug::WriteLine("ItemPropertySet.Commit() was called although it was not need");
}
}
void SetValue(PropertyKey pk, String ^ value) {SetValue<String ^>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<Boolean> value) {SetValue<Boolean>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<Byte> value) {SetValue<Byte>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<Int16> value) {SetValue<Int16>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<Int32> value) {SetValue<Int32>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<UInt16> value) {SetValue<UInt16>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<UInt32> value) {SetValue<UInt32>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<UInt64> value) {SetValue<UInt64>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<Double> value) {SetValue<Double>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<ComTypes::FILETIME> value) {SetValue<ComTypes::FILETIME>(pk.Native(), value);}
void SetValue(PropertyKey pk, Nullable<Guid> value) {SetValue<Guid>(pk.Native(), value);}
void SetValue(PropertyKey pk, array<String ^> ^ value) {SetValue<array<String ^> ^>(pk.Native(), value);}
void SetValue(PropertyKey pk, array<Boolean> ^value) {SetValue<array<Boolean> ^>(pk.Native(), value);}
void SetValue(PropertyKey pk, array<Byte> ^ value) {SetValue<array<Byte> ^>(pk.Native(), value);}
void SetValue(PropertyKey pk, array<Int16> ^ value) {SetValue<array<Int16> ^>(pk.Native(), value);}
void SetValue(PropertyKey pk, array<Int32> ^ value) {SetValue<array<Int32> ^>(pk.Native(), value);}
void SetValue(PropertyKey pk, array<UInt16> ^ value) {SetValue<array<UInt16> ^>(pk.Native(), value);}
void SetValue(PropertyKey pk, array<UInt32> ^ value) {SetValue<array<UInt32> ^>(pk.Native(), value);}
void SetValue(PropertyKey pk, array<UInt64> ^ value) {SetValue<array<UInt64> ^> (pk.Native(), value);}
void SetValue(PropertyKey pk, array<Double> ^ value) {SetValue<array<Double> ^>(pk.Native(), value);}
void SetValue(PropertyKey pk, array<ComTypes::FILETIME> ^ value) {SetValue<array<ComTypes::FILETIME> ^>(pk.Native(), value);}
//void SetValue(PropertyKey pk, array<Guid> ^ value) {SetValue<array<Guid> ^>(pk.Native(), value);}
// And now for the properties:
#define PROPERTY_GETTER(PK, T) PropertyTypeHolder<T>::type get() {return GetValue<T>(PK);}
#define PROPERTY_SETTER(PK, T) void set(PropertyTypeHolder<T>::type value) {SetValue<T>(PK, value);}
#define PROPERTY(PK, T, N) property PropertyTypeHolder<T>::type N {PROPERTY_GETTER(PK, T) PROPERTY_SETTER(PK, T)}
#define PROPERTY_R(PK, T, N) property PropertyTypeHolder<T>::type N {PROPERTY_GETTER(PK, T)}
// #define PROPERTY_W(PK, T, N) property PropertyTypeHolder<T>::type N {PROPERTY_SETTER(PK, T)}
// I use the full namespace so that I can have a property of the same type as its name (e.g. NoteColor of type NoteColor)
#define PROPERTY_WRAPPER_GETTER(FROM_TYPE, TO_TYPE, NAME)\
Nullable<::Microsoft::SDK::Samples::VistaBridge::Library::Shell::TO_TYPE> get() {\
Nullable<FROM_TYPE> u = NAME;\
return u.HasValue ? static_cast<::Microsoft::SDK::Samples::VistaBridge::Library::Shell::TO_TYPE>(u.Value) : Nullable<::Microsoft::SDK::Samples::VistaBridge::Library::Shell::TO_TYPE>();\
}
#define PROPERTY_WRAPPER_SETTER(FROM_TYPE, TO_TYPE, NAME)\
void set(Nullable<::Microsoft::SDK::Samples::VistaBridge::Library::Shell::TO_TYPE> value) {\
NAME = value.HasValue ? static_cast<FROM_TYPE>(value.Value) : Nullable<FROM_TYPE>();\
}
#define PROPERTY_WRAPPER_R(FROM_TYPE, TO_TYPE, NAME) property Nullable<TO_TYPE> NAME {PROPERTY_WRAPPER_GETTER(FROM_TYPE, TO_TYPE, NAME##Raw)}
//#define PROPERTY_WRAPPER_W(FROM_TYPE, TO_TYPE, NAME) property Nullable<TO_TYPE> NAME {PROPERTY_WRAPPER_SETTER(FROM_TYPE, TO_TYPE, NAME##Raw)}
#define PROPERTY_WRAPPER(FROM_TYPE, TO_TYPE, NAME) property Nullable<TO_TYPE> NAME {PROPERTY_WRAPPER_GETTER(FROM_TYPE, TO_TYPE, NAME##Raw) PROPERTY_WRAPPER_SETTER(FROM_TYPE, TO_TYPE, NAME##Raw)}
#pragma region Audio properties
PROPERTY_R(PKEY_Audio_ChannelCount, UInt32, AudioChannelCountRaw)
PROPERTY_WRAPPER_R(UInt32, ChannelCount, AudioChannelCount)
PROPERTY_R(PKEY_Audio_Compression, String ^, AudioCompression)
PROPERTY_R(PKEY_Audio_EncodingBitrate, UInt32, AudioEncodingBitrate)
PROPERTY_R(PKEY_Audio_Format, String ^, AudioFormat)
PROPERTY_R(PKEY_Audio_IsVariableBitRate, bool, AudioIsVariableBitRate)
PROPERTY_R(PKEY_Audio_PeakValue, UInt32, AudioPeakValue)
PROPERTY_R(PKEY_Audio_SampleRate, UInt32, AudioSampleRate)
PROPERTY_R(PKEY_Audio_SampleSize, UInt32, AudioSampleSize)
PROPERTY_R(PKEY_Audio_StreamName, String ^, AudioStreamName)
PROPERTY_R(PKEY_Audio_StreamNumber, UInt16, AudioStreamNumber)
#pragma endregion
#pragma region Calendar properties
...
Comments
- Anonymous
February 25, 2007
PingBack from http://cheatcodedirect.com/itempropertyset-accessing-the-property-system-from-managed-code/