| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 | 
							- ///////////////////////////////////////////////////////////////////////////////
 
- // Name:        msw/ole/safearray.h
 
- // Purpose:     Helpers for working with OLE SAFEARRAYs.
 
- // Author:      PB
 
- // Created:     2012-09-23
 
- // Copyright:   (c) 2012 wxWidgets development team
 
- // Licence:     wxWindows licence
 
- ///////////////////////////////////////////////////////////////////////////////
 
- #ifndef _MSW_OLE_SAFEARRAY_H_
 
- #define _MSW_OLE_SAFEARRAY_H_
 
- #include "wx/msw/ole/oleutils.h"
 
- #if wxUSE_OLE && wxUSE_VARIANT
 
- /*
 
-     wxSafeArray is wxWidgets wrapper for working with MS Windows SAFEARRAYs.
 
-     It also has convenience functions for converting between SAFEARRAY
 
-     and wxVariant with list type or wxArrayString.
 
- */
 
- // The base class with type-independent methods. It exists solely in order to
 
- // reduce the template bloat.
 
- class WXDLLIMPEXP_CORE wxSafeArrayBase
 
- {
 
- public:
 
-     // If owns a SAFEARRAY, it's unlocked and destroyed.
 
-     virtual ~wxSafeArrayBase() { Destroy(); }
 
-     // Unlocks and destroys the owned SAFEARRAY.
 
-     void Destroy();
 
-     // Unlocks the owned SAFEARRAY, returns it and gives up its ownership.
 
-     SAFEARRAY* Detach();
 
-     // Returns true if has a valid SAFEARRAY.
 
-     bool HasArray() const { return m_array != NULL; }
 
-     // Returns the number of dimensions.
 
-     size_t GetDim() const;
 
-     // Returns lower bound for dimension dim in bound. Dimensions start at 1.
 
-     bool GetLBound(size_t dim, long& bound) const;
 
-     // Returns upper bound for dimension dim in bound. Dimensions start at 1.
 
-     bool GetUBound(size_t dim, long& bound) const;
 
-     // Returns element count for dimension dim. Dimensions start at 1.
 
-     size_t GetCount(size_t dim) const;
 
- protected:
 
-     // Default constructor, protected so the class can't be used on its own,
 
-     // it's only used as a base class of wxSafeArray<>.
 
-     wxSafeArrayBase()
 
-     {
 
-         m_array = NULL;
 
-     }
 
-     bool Lock();
 
-     bool Unlock();
 
-     SAFEARRAY* m_array;
 
- };
 
- // wxSafeArrayConvertor<> must be specialized for the type in order to allow
 
- // using it with wxSafeArray<>.
 
- //
 
- // We specialize it below for the standard types.
 
- template <VARTYPE varType>
 
- struct wxSafeArrayConvertor {};
 
- /**
 
-     Macro for specializing wxSafeArrayConvertor for simple types.
 
-     The template parameters are:
 
-         - externType: basic C data type, e.g. wxFloat64 or wxInt32
 
-         - varType: corresponding VARIANT type constant, e.g. VT_R8 or VT_I4.
 
- */
 
- #define wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(externType, varType) \
 
- template <>                                                 \
 
- struct wxSafeArrayConvertor<varType>                        \
 
- {                                                           \
 
-     typedef externType externT;                             \
 
-     typedef externT    internT;                             \
 
-     static bool ToArray(const externT& from, internT& to)   \
 
-     {                                                       \
 
-         to = from;                                          \
 
-         return true;                                        \
 
-     }                                                       \
 
-     static bool FromArray(const internT& from, externT& to) \
 
-     {                                                       \
 
-         to = from;                                          \
 
-         return true;                                        \
 
-     }                                                       \
 
- }
 
- wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxInt16, VT_I2);
 
- wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxInt32, VT_I4);
 
- wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxFloat32, VT_R4);
 
- wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxFloat64, VT_R8);
 
- // Specialization for VT_BSTR using wxString.
 
- template <>
 
- struct wxSafeArrayConvertor<VT_BSTR>
 
- {
 
-     typedef wxString externT;
 
-     typedef BSTR internT;
 
-     static bool ToArray(const wxString& from, BSTR& to)
 
-     {
 
-         BSTR bstr = wxConvertStringToOle(from);
 
-         if ( !bstr && !from.empty() )
 
-         {
 
-             // BSTR can be NULL for empty strings but if the string was
 
-             // not empty, it means we failed to allocate memory for it.
 
-             return false;
 
-         }
 
-         to = bstr;
 
-         return true;
 
-     }
 
-     static bool FromArray(const BSTR from, wxString& to)
 
-     {
 
-         to = wxConvertStringFromOle(from);
 
-         return true;
 
-     }
 
- };
 
- // Specialization for VT_VARIANT using wxVariant.
 
- template <>
 
- struct wxSafeArrayConvertor<VT_VARIANT>
 
- {
 
-     typedef wxVariant externT;
 
-     typedef VARIANT internT;
 
-     static bool ToArray(const wxVariant& from, VARIANT& to)
 
-     {
 
-         return wxConvertVariantToOle(from, to);
 
-     }
 
-     static bool FromArray(const VARIANT& from, wxVariant& to)
 
-     {
 
-         return wxConvertOleToVariant(from, to);
 
-     }
 
- };
 
- template <VARTYPE varType>
 
- class wxSafeArray : public wxSafeArrayBase
 
- {
 
- public:
 
-     typedef wxSafeArrayConvertor<varType> Convertor;
 
-     typedef typename Convertor::internT internT;
 
-     typedef typename Convertor::externT externT;
 
-     // Default constructor.
 
-     wxSafeArray()
 
-     {
 
-         m_array = NULL;
 
-     }
 
-     // Creates and locks a zero-based one-dimensional SAFEARRAY with the given
 
-     // number of elements.
 
-     bool Create(size_t count)
 
-     {
 
-         SAFEARRAYBOUND bound;
 
-         bound.lLbound = 0;
 
-         bound.cElements = count;
 
-         return Create(&bound, 1);
 
-     }
 
-     // Creates and locks a SAFEARRAY. See SafeArrayCreate() in MSDN
 
-     // documentation for more information.
 
-     bool Create(SAFEARRAYBOUND* bound, size_t dimensions)
 
-     {
 
-         wxCHECK_MSG( !m_array, false, wxS("Can't be created twice") );
 
-         m_array = SafeArrayCreate(varType, dimensions, bound);
 
-         if ( !m_array )
 
-             return false;
 
-         return Lock();
 
-     }
 
-     /**
 
-         Creates a 0-based one-dimensional SAFEARRAY from wxVariant with the
 
-         list type.
 
-         Can be called only for wxSafeArray<VT_VARIANT>.
 
-     */
 
-     bool CreateFromListVariant(const wxVariant& variant)
 
-     {
 
-         wxCHECK(varType == VT_VARIANT, false);
 
-         wxCHECK(variant.GetType() == wxS("list"), false);
 
-         if ( !Create(variant.GetCount()) )
 
-             return false;
 
-         VARIANT* data = static_cast<VARIANT*>(m_array->pvData);
 
-         for ( size_t i = 0; i < variant.GetCount(); i++)
 
-         {
 
-             if ( !Convertor::ToArray(variant[i], data[i]) )
 
-                 return false;
 
-         }
 
-         return true;
 
-     }
 
-     /**
 
-         Creates a 0-based one-dimensional SAFEARRAY from wxArrayString.
 
-         Can be called only for wxSafeArray<VT_BSTR>.
 
-     */
 
-     bool CreateFromArrayString(const wxArrayString& strings)
 
-     {
 
-         wxCHECK(varType == VT_BSTR, false);
 
-         if ( !Create(strings.size()) )
 
-             return false;
 
-         BSTR* data = static_cast<BSTR*>(m_array->pvData);
 
-         for ( size_t i = 0; i < strings.size(); i++ )
 
-         {
 
-             if ( !Convertor::ToArray(strings[i], data[i]) )
 
-                 return false;
 
-         }
 
-         return true;
 
-     }
 
-     /**
 
-         Attaches and locks an existing SAFEARRAY.
 
-         The array must have the same VARTYPE as this wxSafeArray was
 
-         instantiated with.
 
-     */
 
-     bool Attach(SAFEARRAY* array)
 
-     {
 
-         wxCHECK_MSG(!m_array && array, false,
 
-                     wxS("Can only attach a valid array to an uninitialized one") );
 
-         VARTYPE vt;
 
-         HRESULT hr = SafeArrayGetVartype(array, &vt);
 
-         if ( FAILED(hr) )
 
-         {
 
-             wxLogApiError(wxS("SafeArrayGetVarType()"), hr);
 
-             return false;
 
-         }
 
-         wxCHECK_MSG(vt == varType, false,
 
-                     wxS("Attaching array of invalid type"));
 
-         m_array = array;
 
-         return Lock();
 
-     }
 
-     /**
 
-         Indices have the same row-column order as rgIndices in
 
-         SafeArrayPutElement(), i.e. they follow BASIC rules, NOT C ones.
 
-     */
 
-     bool SetElement(long* indices, const externT& element)
 
-     {
 
-         wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
 
-         wxCHECK_MSG( indices, false, wxS("Invalid index") );
 
-         internT* data;
 
-         if ( FAILED( SafeArrayPtrOfIndex(m_array, (LONG *)indices, (void**)&data) ) )
 
-             return false;
 
-         return Convertor::ToArray(element, *data);
 
-     }
 
-     /**
 
-         Indices have the same row-column order as rgIndices in
 
-         SafeArrayPutElement(), i.e. they follow BASIC rules, NOT C ones.
 
-     */
 
-     bool GetElement(long* indices, externT& element) const
 
-     {
 
-         wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
 
-         wxCHECK_MSG( indices, false, wxS("Invalid index") );
 
-         internT* data;
 
-         if ( FAILED( SafeArrayPtrOfIndex(m_array, (LONG *)indices, (void**)&data) ) )
 
-             return false;
 
-         return Convertor::FromArray(*data, element);
 
-     }
 
-     /**
 
-         Converts the array to a wxVariant with the list type, regardless of the
 
-         underlying SAFEARRAY type.
 
-         If the array is multidimensional, it is flattened using the alghoritm
 
-         originally employed in wxConvertOleToVariant().
 
-     */
 
-     bool ConvertToVariant(wxVariant& variant) const
 
-     {
 
-         wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
 
-         size_t dims = m_array->cDims;
 
-         size_t count = 1;
 
-         for ( size_t i = 0; i < dims; i++ )
 
-             count *= m_array->rgsabound[i].cElements;
 
-         const internT* data = static_cast<const internT*>(m_array->pvData);
 
-         externT element;
 
-         variant.ClearList();
 
-         for ( size_t i1 = 0; i1 < count; i1++ )
 
-         {
 
-             if ( !Convertor::FromArray(data[i1], element) )
 
-             {
 
-                 variant.ClearList();
 
-                 return false;
 
-             }
 
-             variant.Append(element);
 
-         }
 
-         return true;
 
-     }
 
-     /**
 
-         Converts an array to an ArrayString.
 
-         Can be called only for wxSafeArray<VT_BSTR>. If the array is
 
-         multidimensional, it is flattened using the alghoritm originally
 
-         employed in wxConvertOleToVariant().
 
-     */
 
-     bool ConvertToArrayString(wxArrayString& strings) const
 
-     {
 
-         wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
 
-         wxCHECK(varType == VT_BSTR, false);
 
-         size_t dims = m_array->cDims;
 
-         size_t count = 1;
 
-         for ( size_t i = 0; i < dims; i++ )
 
-             count *= m_array->rgsabound[i].cElements;
 
-         const BSTR* data = static_cast<const BSTR*>(m_array->pvData);
 
-         wxString element;
 
-         strings.clear();
 
-         strings.reserve(count);
 
-         for ( size_t i1 = 0; i1 < count; i1++ )
 
-         {
 
-             if ( !Convertor::FromArray(data[i1], element) )
 
-             {
 
-                 strings.clear();
 
-                 return false;
 
-             }
 
-             strings.push_back(element);
 
-         }
 
-         return true;
 
-     }
 
-     static bool ConvertToVariant(SAFEARRAY* psa, wxVariant& variant)
 
-     {
 
-         wxSafeArray<varType> sa;
 
-         bool result = false;
 
-         if ( sa.Attach(psa) )
 
-             result = sa.ConvertToVariant(variant);
 
-         if ( sa.HasArray() )
 
-             sa.Detach();
 
-         return result;
 
-     }
 
-     static bool ConvertToArrayString(SAFEARRAY* psa, wxArrayString& strings)
 
-     {
 
-         wxSafeArray<varType> sa;
 
-         bool result = false;
 
-         if ( sa.Attach(psa) )
 
-             result = sa.ConvertToArrayString(strings);
 
-         if ( sa.HasArray() )
 
-             sa.Detach();
 
-         return result;
 
-     }
 
-     wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxSafeArray, varType);
 
- };
 
- #endif // wxUSE_OLE && wxUSE_VARIANT
 
- #endif // _MSW_OLE_SAFEARRAY_H_
 
 
  |