学会使用SafeArray 之 Delphi 篇Word文件下载.docx
《学会使用SafeArray 之 Delphi 篇Word文件下载.docx》由会员分享,可在线阅读,更多相关《学会使用SafeArray 之 Delphi 篇Word文件下载.docx(8页珍藏版)》请在冰点文库上搜索。
SAFEARRAY的主要目的是用于automation中的数组型参数的传递。
因为在网络环境中,数组是不能直接传递的,而必须将其包装成SafeArray。
实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元素类型等信息。
SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。
在VARIANT的vt成员的值如果包含VT_ARRAY|...,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。
SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。
Delphi中com组件或外部调用需要传递一个对象或者数组,这个时候可以考虑使用SafeArray。
比如三层架构中通常需要将使用的ClientDataSet数据集传出,那么就可以将DataSet转换为SafeArray,再由其他模块转换接收。
代码块:
pSafeArray是一个结构体,其定义在ActiveX单元中,相关定义如下:
PSafeArray=^TSafeArray;
{$EXTERNALSYMtagSAFEARRAY}
tagSAFEARRAY=record
cDims:
Word;
//数组的维数
fFeatures:
//用来描述数组如何分配和如何被释放的标志
cbElements:
Longint;
//数组元素的大小
cLocks:
//一个计数器,用来跟踪该数组被锁定的次数
pvData:
Pointer;
//指向数据缓冲的指针
rgsabound:
array[0..0]ofTSafeArrayBound;
//描述数组每维的数组结构,该数组的大小是可变的
end;
TSafeArray=tagSAFEARRAY;
{$EXTERNALSYMSAFEARRAY}
SAFEARRAY=TSafeArray;
一维数组的传递:
//一维数组传递
procedureTForm1.ArrayToSafeArray(DataArray:
arrayofstring);
var
VarBound:
TVarArrayBound;
psa:
PSafeArray;
i:
Integer;
AV1:
OleVariant;
begin
//初始化OleValue
VariantInit(OleValue);
VarBound.LowBound:
=0;
VarBound.ElementCount:
=High(DataArray)+1;
psa:
=SafeArrayCreate(VT_BSTR,1,VarBound);
//创建SafeArray对象
//将数组元素放到SafeArray中
fori:
=Low(DataArray)toHigh(DataArray)do
begin
AV1:
=DataArray[i];
SafeArrayPutElement(psa,i,TVarData(AV1).VPointer^);
//封装到Varaint变量中
TVarData(OleValue).VType:
=VT_ARRAYorVT_BSTR;
TVarData(OleValue).VArray:
=pVarArray(psa);
end;
读取一维safeArray的步骤:
//使用SafeArrayGetLBound、SafeArrayGetUBound方法获取safeArray数组上下限
functionTForm1.SafeArrayToText(OleValue:
OleVariant):
string;
RVarData:
TVarData;
RBound:
j,UCount:
aValue:
WideString;
Result:
='
'
;
//获取OleVaraint对象指针
RVarData:
=FindVarData(OleValue)^;
ifRVarData.VArray=nilthen
Exit;
VarResultCheck((SafeArrayGetLBound(pSafeArray(RVarData.VArray),1,RBound.LowBound)));
VarResultCheck(SafeArrayGetUBound(pSafearray(RVarData.VArray),1,UCount));
RBound.ElementCount:
=UCount-RBound.LowBound;
forj:
=RBound.LowBoundtoRBound.ElementCountdo
VarResultCheck(SafeArrayGetElement(PSafeArray(RVarData.VArray),j,aValue));
ifResult='
then
=Result+aValue
else
=Result+'
'
+aValue;
//另外附上将DataSet通过SafeArray传递的方法,其实为多维数组的传递:
procedureTForm1.DataSetToSafeArray(ClientData:
TClientDataSet);
DataArray:
TDoubleArray;
array[0..1]ofTVarArrayBound;
Demen:
array[0..1]ofDWORD;
i,j,k,Count:
SetLength(DataArray,ClientData.FieldCount+1,ClientData.RecordCount+1);
Count:
ClientData.First;
whilenotClientData.Eofdo
=0toClientData.FieldCount-1do
ifCount=0then
DataArray[i][Count]:
=ClientData.Fields[i].FieldName
=ClientData.Fields[i].Value;
ifCount&
gt;
0then
ClientData.Next;
inc(Count);
//--------开始转换为SafeArray-----------
VarBound[0].LowBound:
VarBound[0].ElementCount:
=ClientData.FieldCount+1;
VarBound[1].LowBound:
VarBound[1].ElementCount:
=ClientData.RecordCount+1;
=SafeArrayCreate(VT_BSTR,2,VarBound);
Demen[0]:
=i;
=Low(DataArray[i])toHigh(DataArray[i])do
Demen[1]:
=j;
=DataArray[i][j];
SafeArrayPutElement(psa,Demen,TVarData(AV1).VPointer^);
//读多维数组,读出后再转换为想要的格式:
functionTForm1.SafeArrayToDataSet(oleValue:
i,j,DCount,UCount,iCount:
DCount:
=RVarData.Varray^.DimCount;
//取维数
=0toDCount-1do
VarResultCheck((SafeArrayGetLBound(pSafeArray(RVarData.VArray),i+1,RBound[i].LowBound)));
VarResultCheck(SafeArrayGetUBound(pSafearray(RVarData.VArray),i+1,UCount));
RBound[i].ElementCount:
=UCount-RBound[i].LowBound;
=RBound[1].LowBoundtoRBound[1].ElementCountdo
foriCount:
=RBound[0].LowBoundtoRBound[0].ElementCountdo
=iCount;
VarResultCheck(SafeArrayGetElement(PSafeArray(RVarData.VArray),demen,aValue));