BSTRs

2011-12-19 20 views
8

के एक सुरक्षितता के साथ एक वैरिएंट से मूल्यों को प्रदर्शित करने के लिए कैसे करें मैं एक COM ऑब्जेक्ट लाइब्रेरी पर फ़ंक्शन के साथ काम कर रहा हूं जो VARIANTBSTR एस के साथ देता है। मैं इस VARIANT इंस्टेंस से मान कैसे प्रदर्शित कर सकता हूं और इसे TStringList के अंदर सहेज सकता हूं? मैंने नेट को बिना किसी स्पष्ट उत्तर के खोजने की कोशिश की।BSTRs

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); 

उत्तर

4

आप TWideStringDynArray का उपयोग करें और डेल्फी रूपांतरण करते हैं कर सकते हैं::

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; 

जब आप BSTRs के अपने संस्करण SAFEARRAY के साथ इस फोन में यह हो जाएगा

मुझे कोई सफलता के साथ पालन करने का प्रयास स्वचालित रूप से TWideStringDynArray में परिवर्तित हो गया। एक असंगत संस्करण रनटाइम त्रुटि EVariantInvalidArgError का कारण बन जाएगा।

यह जांचने के लिए एक संस्करण BSTR का एक सुरक्षित सरणी आप ऐसा कर सकते हैं रखती है:

IsOK := VarIsArray(V) and (VarArrayDimCount(V) = 1) and (VarType(V) and varTypeMask = varOleStr); 
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 

अगर आप लेट बाइंडिंग (CreateOleObject) के माध्यम से ComFunction पैदा कर रहे आप का उपयोग करना चाहिए:

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

मैं इस वैरिएंट उदाहरण से मूल्य कैसे प्रदर्शित कर सकता हूं और उसे TStringLi के अंदर सहेज सकता हूं सेंट?

कॉम VARIANT struct parray और pparray डेटा सदस्यों को बताया कि एक SAFEARRAY के संकेत दिए गए हैं, जैसे हैं:

VARIANT V; 
LPSAFEARRAY sa = V_ISBYREF(&V) ? V_ARRAYREF(&V) : V_ARRAY(&V); 

VCL Variant वर्ग, दूसरे हाथ पर, एक LPSAFEARRAY रूपांतरण ऑपरेटर है परिभाषित किया गया है, इसलिए आप इसे सीधे असाइन कर सकते हैं (लेकिन केवल Variant.VType फ़ील्ड जिसमें varByRef ध्वज मौजूद नहीं है, उदाहरण के लिए:

Variant V; 
LPSAFEARRAY sa = V; 

किसी भी तरह से, एक बार आप SAFEARRAY सूचक है, BSTR मूल्यों का उपयोग करने की SAFEARRAY एपीआई का उपयोग, जैसे:

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; 
} 

VarClear (वी); टीवीरडाटा (वी) .VType = varOleStr;

आपको उन सभी की आवश्यकता नहीं है। वीसीएल Variant कक्षा स्वयं को रिक्त स्थिति में शुरू कर देती है, और VType असाइन करने की आवश्यकता नहीं है क्योंकि आप तुरंत बाद में Variant पर नया मान निर्दिष्ट कर रहे हैं।

वी = कॉमफंक्शन-> GetValues ​​(); // < < < < ----- वी खाली

है वी खाली है, तो GetValues() एक खाली Variant लौटने के साथ शुरू।

mystr = (wchar_t *) (टीवीरडाटा (वी) .VString);

TVarData::VString एक AnsiString& संदर्भ है, न कि wchar_t* सूचक है। एक String करने के लिए एक VCL Variant (नहीं एक COM VARIANT) में परिवर्तित करने के लिए, बस इसे के रूप में है आवंटित दो और RTL आप के लिए विस्तार बाहर काम करता है:

String mystr = V;