我正在使用一个COM对象库,其函数返回VARIANT
SAFEARRAY
个BSTR
s。如何显示此VARIANT
实例中的值并将其保存在TStringList
内?我试着在网上搜索没有明确的答案。
我尝试了以下但没有成功:
Variant V;
String mystr;
VarClear(V);
TVarData(V).VType = varOleStr;
V = ComFunction->GetValues(); //<<<<----- V is empty
mystr = (wchar_t *)(TVarData(V).VString);
Memo1->Lines->Add(mystr);
VarClear(V);
答案 0 :(得分:4)
您可以使用TWideStringDynArray
让Delphi进行转换:
procedure LoadStringsFromVariant(const Values: TWideStringDynArray; Strings: TStrings);
var
I: Integer;
begin
Strings.BeginUpdate;
try
for I := Low(Values) to High(Values) do
Strings.Add(Values[I]);
finally
Strings.EndUpdate;
end;
end;
当您使用BSTR的Variant safearray调用它时,它将自动转换为TWideStringDynArray
。不兼容的Variant将导致运行时错误EVariantInvalidArgError
。
要检查Variant是否包含BSTR的安全数组,您可以执行以下操作:
IsOK := VarIsArray(V) and (VarArrayDimCount(V) = 1) and (VarType(V) and varTypeMask = varOleStr);
答案 1 :(得分:4)
uses ActiveX;
var
VSafeArray: PSafeArray;
LBound, UBound, I: LongInt;
W: WideString;
begin
VSafeArray := ComFunction.GetValues();
SafeArrayGetLBound(VSafeArray, 1, LBound);
SafeArrayGetUBound(VSafeArray, 1, UBound);
for I := LBound to UBound do
begin
SafeArrayGetElement(VSafeArray, I, W);
Memo1.Lines.Add(W);
end;
SafeArrayDestroy(VSafeArray); // cleanup PSafeArray
如果您通过后期绑定(ComFunction
)创建CreateOleObject
,则应使用:
var
v: Variant;
v := ComFunction.GetValues;
for i := VarArrayLowBound(v, 1) to VarArrayHighBound(v, 1) do
begin
W := VarArrayGet(v, [i]);
Memo1.Lines.Add (W);
end;
答案 2 :(得分:2)
如何显示此VARIANT实例的值并将其保存在TStringList中?
COM VARIANT
结构包含指向parray
的{{1}}和pparray
数据成员,例如:
SAFEARRAY
另一方面,VCL VARIANT V;
LPSAFEARRAY sa = V_ISBYREF(&V) ? V_ARRAYREF(&V) : V_ARRAY(&V);
类定义了Variant
转换运算符,因此您可以直接指定它(但仅限于LPSAFEARRAY
字段没有{ {1}}标志存在,即),例如:
Variant.VType
无论哪种方式,只要您拥有varByRef
指针,请使用SafeArray API访问Variant V;
LPSAFEARRAY sa = V;
值,例如:
SAFEARRAY
<强> VarClear(V); TVarData(V).VType = varOleStr;
你根本不需要那些。 VCL BSTR
类将自身初始化为空白状态,并且无需分配bool __fastcall VariantToStrings(const Variant &V, TStrings *List)
{
// make sure the Variant is holding an array
if (!V_ISARRAY(&V)) return false;
// get the array pointer
LPSAFEARRAY sa = V_ISBYREF(&V) ? V_ARRAYREF(&V) : V_ARRAY(&V);
// make sure the array is holding BSTR values
VARTYPE vt;
if (FAILED(SafeArrayGetVartype(sa, &vt))) return false;
if (vt != VT_BSTR) return false;
// make sure the array has only 1 dimension
if (SafeArrayGetDim(sa) != 1) return false;
// get the bounds of the array's sole dimension
LONG lBound = -1, uBound = -1;
if (FAILED(SafeArrayGetLBound(sa, 0, &lBound))) return false;
if (FAILED(SafeArrayGetUBound(sa, 0, &uBound))) return false;
if ((lBound > -1) && (uBound > -1))
{
// access the raw data of the array
BSTR *values = NULL;
if (FAILED(SafeArrayAccessData(sa, (void**)&values))) return false;
try
{
List->BeginUpdate();
try
{
// loop through the array adding the elements to the list
for (LONG idx = lBound; l <= uBound; ++idx)
{
String s;
if (values[idx] != NULL)
s = String(values[idx], SysStringLen(values[idx]));
List->Add(s);
}
}
__finally
{
List->EndUpdate();
}
}
__finally
{
// unaccess the raw data of the array
SafeArrayUnaccessData(sa);
}
}
return true;
}
,因为您之后会立即为整个Variant
分配新值。
V = ComFunction-&gt; GetValues(); //&lt;&lt;&lt;&lt; ----- V为空
如果V为空,则VType
将返回空的Variant
以开始。
mystr =(wchar_t *)(TVarData(V).VString);
GetValues()
是Variant
引用,而不是TVarData::VString
指针。要将VCL AnsiString&
(不是COM wchar_t*
)转换为Variant
,只需按原样分配它,让RTL为您解决详细信息:
VARIANT