📄 0,1410,22016,00.html
字号:
<br><tt>\{</tt>
<br><tt> // Method 1</tt>
<br><tt> TArrayDimT<2> Dim_1(20, 10);</tt>
<br><tt> TSafeArrayT<<b>long</b>, VT_I4, 2> Array2D_1(Dim_1);</tt>
<p><tt> // Method 2</tt>
<br><tt> TSafeArrayDim2 Dim_2(20, 10);</tt>
<br><tt> TSafeArrayLong2 Array2D_2(Dim_2);</tt>
<p><tt> // Method 3</tt>
<br><tt> SAFEARRAYBOUND sabdBounds[2] = \{ \{10, 0\}, \{20, 0\}
\};</tt>
<br><tt> LPSAFEARRAY lpsaArray = SafeArrayCreate(VT_I4, 2,
sabdBounds);</tt>
<br><tt> TSafeArrayLong2 Array2D_3(lpsaArray);</tt>
<p><tt> <b>return</b> 0;</tt>
<br><tt>\}</tt>
<br><tt>//---------------------------------------------------------------------------</tt>
<p>The first method provides all the template arguments for TArrayDimT
and TSafeArrayT. The second method uses typedefs for commonly used arrays.
See the bottom of safearry.h for these typedefs among others. The third
method first constructs a SAFEARRAY using Win32 and then attaches
the SAFEARRAY to a TSafeArrayLong2. Each of the three SafeArrays are destroyed
in the destructor of TSafeArrayT when they go out of scope, which leads
us to the next topic.
<p><font size=+2>Accessing TSafeArrayT Elements</font>
<br>Modifying the elements of the array is very simple. The index of operator
(<b>[]</b>) has been overloaded for this purpose. This operator returns
a reference to a TSAAccessorT object that can also has the index of operator
overloaded so that multidimensional arrays can be accessed by a series
of index of operations. However, there is a small but significant bug in
the destructor of TSAAccessorT that makes it unusable for multidimensional
arrays. In safearry.h starting on line 220 is the following:
<p><tt>~TSAAccessorT()</tt>
<br><tt> \{</tt>
<br><tt> <b>if</b> (m_Alloc) \{</tt>
<br><tt> <b>delete</b>[] m_Indices;</tt>
<br><tt> \}</tt>
<br><tt> \}</tt>
<p>This should read:
<p><tt>~TSAAccessorT()</tt>
<br><tt> \{</tt>
<br><tt> <b>if</b> (m_Alloc) \{</tt>
<br><tt> m_Indices--;</tt>
<br><tt> <b>delete</b>[] m_Indices;</tt>
<br><tt> \}</tt>
<br><tt> \}</tt>
<p>Now, the following program will not give an access violation.
<p><tt>//---------------------------------------------------------------------------</tt>
<p><tt><font color="#009900">#include <vcl.h></font></tt>
<br><tt><font color="#009900">#include <windows.h></font></tt>
<br><tt><font color="#009900">#include <safearry.h></font></tt>
<br><tt><font color="#009900">#pragma hdrstop</font></tt>
<p><tt>//---------------------------------------------------------------------------</tt>
<p><tt><font color="#009900">#pragma argsused</font></tt>
<br><tt>WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, <b>int</b> nCmdShow)</tt>
<br><tt>\{</tt>
<br><tt> TSafeArrayDim3 dim(100, 10, 20);</tt>
<br><tt> TSafeArrayLong3 array(dim);</tt>
<br><tt> <b>for</b>(<b>int</b> i = 0; i < 100; i++)</tt>
<br><tt> <b>for</b>(<b>int</b> j = 0; j <
10; j++)</tt>
<br><tt> <b>for</b>(<b>int</b>
k = 0; k < 20; k++)</tt>
<br><tt>
array[i][j][k] = 5;</tt>
<p><tt> <b>return</b> 0;</tt>
<br><tt>\}</tt>
<br><tt>//---------------------------------------------------------------------------</tt>
<p><font size=+2>Automatic Destruction of SafeArrays</font>
<br>Another benefit to using a statically instantiated object to manage
SafeArrays is for automatic destruction of the internal SAFEARRAY when
the object goes out of scope. For example, the following code instantiates
a SafeArray in a <b>try</b>...<b>catch</b> and a SafeArray in a function
called within the <b>try</b>...<b>catch</b> block. Both SafeArrays are
automatically destroyed when they go out of scope, whether or not an exception
occurs. This example also demonstrates passing TSafeArrayT objects by reference
and by value and manipulating the data contained in the array.
<p><tt>//---------------------------------------------------------------------------</tt>
<p><tt><font color="#009900">#include <vcl.h></font></tt>
<br><tt><font color="#009900">#include <windows.h></font></tt>
<br><tt><font color="#009900">#include <safearry.h></font></tt>
<br><tt><font color="#009900">#pragma hdrstop</font></tt>
<p><tt>//---------------------------------------------------------------------------</tt>
<br><tt>TSafeArrayBSTR1 CreateBSTRArray(TSafeArrayT<wchar_t, VT_I2,
2>& SafeArray) \{</tt>
<br><tt> TSafeArrayDim1 Dim(SafeArray.BoundsLength[0]);</tt>
<br><tt> TSafeArrayBSTR1 BSTRArray(Dim);</tt>
<p><tt> WideString wstr;</tt>
<br><tt> <b>for</b>(<b>int</b> i = 0; i < SafeArray.BoundsLength[0];
i++) \{</tt>
<br><tt> wstr.Empty();</tt>
<br><tt> <b>for</b>(<b>int</b> j = 0; j <
SafeArray.BoundsLength[1]; j++) \{</tt>
<br><tt> wstr.Insert(WideString(SafeArray[j][i]),
wstr.Length()+1);</tt>
<br><tt> \}</tt>
<br><tt> BSTRArray[i] = wstr.Detach();</tt>
<br><tt> \}</tt>
<p><tt> <b>return</b> BSTRArray;</tt>
<br><tt>\}</tt>
<p><tt><font color="#009900">#pragma argsused</font></tt>
<br><tt>WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, <b>int</b> nCmdShow)</tt>
<br><tt>\{</tt>
<br><tt> <b>try</b> \{</tt>
<br><tt> // Fill a 10x10 array of chars with
where each row consists of</tt>
<br><tt> // chars '0', '1', '2',...,'9'</tt>
<br><tt> TSafeArrayDim2 Dim(10, 10);</tt>
<br><tt> TSafeArrayT<<b>wchar_t</b>, VT_I2,
2> Array(Dim);</tt>
<br><tt> <b>char</b> temp[2];</tt>
<br><tt> <b>for</b>(<b>int</b> i = 0; i <
10; i++)</tt>
<br><tt> <b>for</b>(<b>int</b>
j = 0; j < 10; j++)</tt>
<br><tt>
Array[j][i] = WideChar((itoa(j, temp, 10))[0]);</tt>
<p><tt> // Create an array of 10 BSTRS, where
each BSTR consists</tt>
<br><tt> // of the string, "0123456789".
Each row in the 10x10 array</tt>
<br><tt> // of chars is converted to the
equivalent BSTR.</tt>
<br><tt> TSafeArrayBSTR1 BSTRArray = CreateBSTRArray(Array);</tt>
<p><tt> // Display the BSTRs.</tt>
<br><tt> WideString msg;</tt>
<br><tt> <b>for</b>(<b>int</b> i = 0; i <
10; i++)</tt>
<br><tt> msg = msg + WideString(BSTRArray[i])
+ WideString("n");</tt>
<br><tt> ShowMessage(msg);</tt>
<br><tt> \} <b>catch</b>(Exception& E) \{</tt>
<br><tt> ShowMessage(E.Message);</tt>
<br><tt> \}</tt>
<p><tt><b>return</b> 0;</tt>
<br><tt>\}</tt>
<br><tt>//---------------------------------------------------------------------------</tt>
<p>This program demonstrates the numerous ways TSafeArrayT can be used
to create, modify, and convert data, while letting the exception handling
mechanism automatically clean up resources if an error occurs.
<p><font size=+2>SAFEARRAY Ownership</font>
<br>Care must be taken when accessing the SAFEARRAY structure stored by
a TSafeArrayT directly in order to avoid the destruction of the SAFEARRAY
in more than one place or not at all. Often, when using straight Win32
functions or those of another API that work directly with the SAFEARRAY
structure, you still want to use TSafeArrayT to manage the data. The following
code demonstrates three cases: one, a newly created SAFEARRAY is returned
from a function; two, a newly created SAFEARRAY is returned in an out parameter;
three, where a preexisting SAFEARRAY is to be passed to a function.
<p><tt><font color="#009900">#include <vcl.h></font></tt>
<br><tt><font color="#009900">#include <windows.h></font></tt>
<br><tt><font color="#009900">#include <safearry.h></font></tt>
<br><tt><font color="#009900">#pragma hdrstop</font></tt>
<p><tt>//---------------------------------------------------------------------------</tt>
<p><tt><font color="#009900">#pragma argsused</font></tt>
<br><tt>WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, <b>int</b> nCmdShow)</tt>
<br><tt>\{</tt>
<br><tt> SAFEARRAYBOUND sabdBounds[2] = \{ \{10, 0\}, \{20, 0\}
\};</tt>
<br><tt> TSafeArrayLong2 Array1(SafeArrayCreate(VT_I4, 2, sabdBounds));</tt>
<p><tt> TSafeArrayLong2 Array2;</tt>
<br><tt> SAFEARRAY* sa = Array1.Detach();</tt>
<br><tt> SafeArrayCopy(sa, &Array2);</tt>
<br><tt> SafeArrayDestroy(sa);</tt>
<p><tt> <b>return</b> 0;</tt>
<br><tt>\}</tt>
<br><tt>//---------------------------------------------------------------------------</tt>
<p>The first two lines of WinMain initiliaze <i>Array1</i> with the return
value of <i>SafeArrayCreate</i>. At this point, ownership of the SAFEARRAY
is in the hands of Array1. The only method provided to access the internal
SAFEARRAY is by detaching it with <i>TSafeArrayT::Detach()</i>. Once this
method is called, the SAFEARRAY is no longer associated with Array1 and
must be destroyed explicitly, as demonstrated the example. Not doing so
will cause a resource leak. <i>Array2</i> is constructed with no data or
dimension sizes. Its internal SAFEARRAY is accessed and initialized by
the Win32 <i>SafeArrayCopy</i> function. The & operator was overloaded
for initializing TSafeArrayT objects by using them as an out parameter.
This will only work if the TSafeArrayT object has not yet been initialized.
If it has already, an exception is thrown. SAFEARRAY objects can be detached
and reattached to TSafeArrayT objects as many times as desired. However,
attempting to attach a SAFEARRAY that does not match the type and dimensions
of the TSafeArrayT object will result in an exception.
<p><tt><font color="#009900">#include <vcl.h></font></tt>
<br><tt><font color="#009900">#include <windows.h></font></tt>
<br><tt><font color="#009900">#include <safearry.h></font></tt>
<br><tt><font color="#009900">#pragma hdrstop</font></tt>
<p><tt>//---------------------------------------------------------------------------</tt>
<p><tt><font color="#009900">#pragma argsused</font></tt>
<br><tt>WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, <b>int</b> nCmdShow)</tt>
<br><tt>\{</tt>
<br><tt> SAFEARRAYBOUND sabdBounds[2] = \{ \{10, 0\}, \{20, 0\}
\};</tt>
<br><tt> TSafeArrayLong2 Array1(SafeArrayCreate(VT_I4, 2, sabdBounds));</tt>
<p><tt> TSafeArrayLong2 Array2;</tt>
<br><tt> SAFEARRAY* sa = Array1.Detach();</tt>
<br><tt> SafeArrayCopy(sa, &Array2);</tt>
<br><tt> Array1.Attach(sa);</tt>
<p><tt> <b>return</b> 0;</tt>
<br><tt>\}</tt>
<br><tt>//---------------------------------------------------------------------------</tt>
<p>This last example is identical to the one before, except that, instead
of explicitly destroying the SAFEARRAY <i>sa</i>, it is reattached to Array1
which destroys it when Array1 goes out of scope.
</table>
</BODY>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -