Improve SAFEARRAY support in wxMSW OLE Automation code.

Add a new wxSafeArray<> class wrapping SAFEARRAY.

Also add support for converting VARIANTs containing other, previously
unsupported, standard types.

Closes #14637.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72543 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2012-09-23 22:49:50 +00:00
parent 2abce4af22
commit 226fa6db3d
18 changed files with 989 additions and 159 deletions

View File

@@ -215,6 +215,133 @@ public:
virtual bool GetAsAny(wxAny* any) const;
};
/**
@class wxVariantDataSafeArray
This class represents a thin wrapper for Microsoft Windows SAFEARRAY type.
It is used for converting between wxVariant and OLE VARIANT
with type set to VT_ARRAY, which has more than one dimension.
When wxVariant stores wxVariantDataSafeArray, it returns "safearray" as its type.
wxVariantDataSafeArray does NOT manage the SAFEARRAY it points to.
If you want to pass it to a wxAutomationObject as a parameter:
-# Assign a SAFEARRAY pointer to it and store it in a wxVariant.
-# Call the wxAutomationObject method (CallMethod(), SetProperty() or Invoke())
-# wxAutomationObject will destroy the array after the approapriate automation call.
An example of creating a 2-dimensional SAFEARRAY containing VARIANTs
and storing it in a wxVariant
@code
SAFEARRAYBOUND bounds[2]; // 2 dimensions
wxSafeArray<VT_VARIANT> safeArray;
unsigned rowCount = 1000;
unsigned colCount = 20;
bounds[0].lLbound = 0; // elements start at 0
bounds[0].cElements = rowCount;
bounds[1].lLbound = 0; // elements start at 0
bounds[1].cElements = colCount;
if ( !safeArray.Create(bounds, 2) )
return false;
long indices[2];
for ( unsigned row = 0; row < rowCount; row++ )
{
indices[0] = row;
for ( unsigned col = 0; col < colCount; col++ )
{
indices[1] = col;
if ( !safeArray.SetElement(indices, wxString::Format("R%ud C%ud", i+1, j+1)) )(
return false;
}
}
range.PutProperty("Value", wxVariant(new wxVariantDataSafeArray(sa.Detach())));
@endcode
If you you received wxVariantDataSafeArray as a result of wxAutomationObject method call:
(1) Get the data out of the array.
(2) Destroy the array.
@code
wxVariant result;
result = range.GetProperty("Value");
if ( result.GetType() == "safearray" )
{
wxSafeArray<VT_VARIANT> safeArray;
wxVariantDataSafeArray* const
sa = wxStaticCastVariantData(variant.GetData(), wxVariantDataSafeArray);
if ( !safeArray.Attach(sa.GetValue() )
{
if ( !safeArray.HasArray() )
SafeArrayDestroy(sa.GetValue()); // we have to dispose the SAFEARRAY ourselves
return false;
}
// get the data from the SAFEARRAY using wxSafeArray::GetElement()
// SAFEARRAY will be disposed by safeArray's dtor
}
@endcode
@onlyfor{wxmsw}
@since 2.9.5
@library{wxcore}
@category{data}
@see wxAutomationObject, wxVariant, wxVariantData, wxVariantDataErrorCode
@header{wx/msw/ole/oleutils.h}
*/
class wxVariantDataSafeArray : public wxVariantData
{
public:
/**
Constructor initializes the object to @a value.
*/
explicit wxVariantDataSafeArray(SAFEARRAY* value = NULL);
/**
Returns the stored array.
*/
SAFEARRAY* GetValue() const;
/**
Set the stored array.
*/
void SetValue(SAFEARRAY* value);
/**
Returns true if @a data is of wxVariantDataErrorCode type
and contains the same SCODE value.
*/
virtual bool Eq(wxVariantData& data) const;
/**
Fills the provided string with the textual representation of this
object.
The error code is just a number, so it's output as such.
*/
virtual bool Write(wxString& str) const;
/**
Returns a copy of itself.
*/
wxVariantData* Clone() const;
/**
Returns "safearray".
*/
virtual wxString GetType() const;
/**
Converts the value of this object to wxAny.
*/
virtual bool GetAsAny(wxAny* any) const;
};
/**
@class wxAutomationObject
@@ -245,7 +372,7 @@ public:
@library{wxcore}
@category{data}
@see wxVariant, wxVariantDataCurrency, wxVariantDataErrorCode
@see wxVariant, wxVariantDataCurrency, wxVariantDataErrorCode, wxVariantDataSafeArray
*/
class wxAutomationObject : public wxObject
{

View File

@@ -26,9 +26,9 @@
the wxVariantData object, unlike the case for basic data types where
convenience functions such as GetLong() can be used.
Under Microsoft Windows, two additional wxVariantData-derived classes --
wxVariantDataCurrency and wxVariantDataErrorCode -- are available for
interoperation with OLE VARIANT when using wxAutomationObject.
Under Microsoft Windows, three additional wxVariantData-derived classes --
wxVariantDataCurrency, wxVariantDataErrorCode and wxVariantDataSafeArray --
are available for interoperation with OLE VARIANT when using wxAutomationObject.
Pointers to any wxObject derived class can also easily be stored in a
wxVariant. wxVariant will then use wxWidgets' built-in RTTI system to set