Improve wxVariantDataSafeArray documentation
Improve the class description. Mention that one needs to call wxAutomationObject::SetConvertVariantFlags() with wxOleConvertVariant_ReturnSafeArrays to actually receive a wxVariant with SAFEARRAY (if possible). Make better use of now-documented wxSafeArray in the code examples. Closes https://github.com/wxWidgets/wxWidgets/pull/1611
This commit is contained in:
@@ -245,71 +245,115 @@ public:
|
|||||||
/**
|
/**
|
||||||
@class wxVariantDataSafeArray
|
@class wxVariantDataSafeArray
|
||||||
|
|
||||||
This class represents a thin wrapper for Microsoft Windows @c SAFEARRAY type.
|
This class stores @c SAFEARRAY in a wxVariant. It can be used
|
||||||
|
to pass arrays having more than one dimension with wxAutomationObject methods.
|
||||||
|
|
||||||
It is used for converting between wxVariant and OLE @c VARIANT
|
|
||||||
with type set to @c VT_ARRAY, which has more than one dimension.
|
|
||||||
When wxVariant stores wxVariantDataSafeArray, it returns "safearray" as its type.
|
When wxVariant stores wxVariantDataSafeArray, it returns "safearray" as its type.
|
||||||
|
|
||||||
wxVariantDataSafeArray does NOT manage the @c SAFEARRAY it points to.
|
wxVariantDataSafeArray does NOT manage the @c SAFEARRAY it points to.
|
||||||
If you want to pass it to a wxAutomationObject as a parameter:
|
If you want to pass it to a wxAutomationObject as a parameter:
|
||||||
-# Assign a @c SAFEARRAY pointer to it and store it in a wxVariant.
|
-# Create and fill a @c SAFEARRAY.
|
||||||
-# Call the wxAutomationObject method (CallMethod(), SetProperty() or Invoke())
|
-# Assign the @c SAFEARRAY pointer to it and store it in a wxVariant.
|
||||||
-# wxAutomationObject will destroy the array after the approapriate automation call.
|
-# Call a wxAutomationObject method (such as CallMethod() or PutProperty()) with the wxVariant as a parameter.
|
||||||
|
-# wxAutomationObject will destroy the array after the automation call.
|
||||||
|
|
||||||
An example of creating a 2-dimensional @c SAFEARRAY containing VARIANTs
|
An example of creating a two-dimensional @c SAFEARRAY containing <tt>VARIANT</tt>s
|
||||||
and storing it in a wxVariant
|
and storing it in a wxVariant, using a utility class wxSafeArray<varType>.
|
||||||
@code
|
@code
|
||||||
SAFEARRAYBOUND bounds[2]; // 2 dimensions
|
const size_t dimensions = 2;
|
||||||
|
const long rowCount = 1000;
|
||||||
|
const long columnCount = 20;
|
||||||
|
|
||||||
|
SAFEARRAYBOUND bounds[dimensions];
|
||||||
wxSafeArray<VT_VARIANT> safeArray;
|
wxSafeArray<VT_VARIANT> safeArray;
|
||||||
unsigned rowCount = 1000;
|
|
||||||
unsigned colCount = 20;
|
|
||||||
|
|
||||||
bounds[0].lLbound = 0; // elements start at 0
|
bounds[0].lLbound = 0; // elements start at 0
|
||||||
bounds[0].cElements = rowCount;
|
bounds[0].cElements = rowCount;
|
||||||
bounds[1].lLbound = 0; // elements start at 0
|
bounds[1].lLbound = 0; // elements start at 0
|
||||||
bounds[1].cElements = colCount;
|
bounds[1].cElements = columnCount;
|
||||||
|
|
||||||
if ( !safeArray.Create(bounds, 2) )
|
if ( !safeArray.Create(bounds, dimensions) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
long indices[2];
|
long indices[dimensions];
|
||||||
|
|
||||||
for ( unsigned row = 0; row < rowCount; row++ )
|
for ( long row = 0; row < rowCount; ++row )
|
||||||
{
|
{
|
||||||
indices[0] = row;
|
indices[0] = row;
|
||||||
for ( unsigned col = 0; col < colCount; col++ )
|
|
||||||
|
for ( long column = 0; column < columnCount; ++column )
|
||||||
{
|
{
|
||||||
indices[1] = col;
|
indices[1] = column;
|
||||||
if ( !safeArray.SetElement(indices, wxString::Format("R%u C%u", row+1, col+1)) )
|
if ( !safeArray.SetElement(indices, wxString::Format("R%u C%u", row, column)) )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
range.PutProperty("Value", wxVariant(new wxVariantDataSafeArray(safeArray.Detach())));
|
range.PutProperty("Value", wxVariant(new wxVariantDataSafeArray(safeArray.Detach())));
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
If you you received wxVariantDataSafeArray as a result of wxAutomationObject method call:
|
If you want to receive a @c SAFEARRAY in a wxVariant as a result of an wxAutomationObject
|
||||||
(1) Get the data out of the array.
|
call:
|
||||||
(2) Destroy the array.
|
-# Call wxAutomationObject::SetConvertVariantFlags() with parameter
|
||||||
|
::wxOleConvertVariant_ReturnSafeArrays (otherwise the data would be
|
||||||
|
sent as a flattened one-dimensional list).
|
||||||
|
-# Call a wxAutomationObject method (such as CallMethod() or GetProperty()).
|
||||||
|
-# Retrieve the @c SAFEARRAY from the returned wxVariant.
|
||||||
|
-# Process the data in the @c SAFEARRAY.
|
||||||
|
-# Destroy the @c SAFEARRAY when you no longer need it.
|
||||||
|
|
||||||
|
The following example shows how to process a two-dimensional @c SAFEARRAY
|
||||||
|
with @c VT_VARIANT type received from a wxAutomationObject call,
|
||||||
|
using a utility class wxSafeArray<varType>.
|
||||||
@code
|
@code
|
||||||
|
const size_t dimensions = 2;
|
||||||
|
|
||||||
wxVariant result;
|
wxVariant result;
|
||||||
|
|
||||||
|
range.SetConvertVariantFlags(wxOleConvertVariant_ReturnSafeArrays);
|
||||||
result = range.GetProperty("Value");
|
result = range.GetProperty("Value");
|
||||||
if ( result.GetType() == "safearray" )
|
|
||||||
|
if ( !result.IsType("safearray") )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxSafeArray<VT_VARIANT> safeArray;
|
||||||
|
wxVariantDataSafeArray* const
|
||||||
|
sa = wxStaticCastVariantData(result.GetData(), wxVariantDataSafeArray);
|
||||||
|
|
||||||
|
if ( !safeArray.Attach(sa->GetValue()) )
|
||||||
{
|
{
|
||||||
wxSafeArray<VT_VARIANT> safeArray;
|
if ( !safeArray.HasArray() )
|
||||||
wxVariantDataSafeArray* const
|
::SafeArrayDestroy(sa->GetValue()); // we have to dispose the SAFEARRAY ourselves
|
||||||
sa = wxStaticCastVariantData(variant.GetData(), wxVariantDataSafeArray);
|
return false;
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( safeArray.GetDim() != dimensions ) // we are expecting 2 dimensions
|
||||||
|
return false; // SAFEARRAY will be disposed by safeArray's dtor
|
||||||
|
|
||||||
|
long rowStart, columnStart;
|
||||||
|
long rowCount, columnCount;
|
||||||
|
long indices[dimensions];
|
||||||
|
wxVariant value;
|
||||||
|
|
||||||
|
// get start indices and item counts for rows and columns
|
||||||
|
safeArray.GetLBound(1, rowStart);
|
||||||
|
safeArray.GetLBound(2, columnStart);
|
||||||
|
safeArray.GetUBound(1, rowCount);
|
||||||
|
safeArray.GetUBound(2, columnCount);
|
||||||
|
|
||||||
|
for ( long row = rowStart; row <= rowCount; ++row )
|
||||||
|
{
|
||||||
|
indices[0] = row;
|
||||||
|
|
||||||
|
for ( long column = columnStart; column <= columnCount; ++column )
|
||||||
|
{
|
||||||
|
indices[1] = column;
|
||||||
|
if ( !safeArray.GetElement(indices, value) )
|
||||||
|
return false;
|
||||||
|
// do something with value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SAFEARRAY will be disposed by safeArray's dtor
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@onlyfor{wxmsw}
|
@onlyfor{wxmsw}
|
||||||
@@ -318,7 +362,7 @@ public:
|
|||||||
@library{wxcore}
|
@library{wxcore}
|
||||||
@category{data}
|
@category{data}
|
||||||
|
|
||||||
@see wxAutomationObject, wxVariant, wxVariantData, wxVariantDataErrorCode
|
@see wxAutomationObject, wxSafeArray<varType>, wxVariant, wxVariantData
|
||||||
|
|
||||||
@header{wx/msw/ole/oleutils.h}
|
@header{wx/msw/ole/oleutils.h}
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user