Reply

C++, IDispatch how to get Item(x) ?

[ Edited ]

 

HI,

I'm trying to get Item (1) of a SolidEdgePart Models.

As a result I always get "Member not found".

Please can you help me with an example of how to get an item from a "collection"

Thanks in advace,

best regards

Massimo

-------------------------------------------

VARIANT result;

VariantInit(&result);

VARIANT x;

x.vt = VT_BSTR ;

x.bstrVal = L"1" ;

 

hr = AutoWrap(DISPATCH_PROPERTYGET, &result, pModels, L"Item", 1, x);

if (hr == S_OK)

{

    return result ;

} ;

 

//------------------------------

 

//

// AutoWrap() - Automation helper function...

//

HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,

      LPOLESTR ptName, int cArgs...)

{

      // Begin variable-argument list...

      va_list marker;

      va_start(marker, cArgs);

 

      if(!pDisp) {

//            MessageBox(NULL, "NULL IDispatch passed to AutoWrap()",

//                       "Error", 0x10010);

            _exit(0);

      }

 

      // Variables used...

      DISPPARAMS dp = { NULL, NULL, 0, 0 };

      DISPID dispidNamed = DISPID_PROPERTYPUT;

      DISPID dispID;

      HRESULT hr;

      char buf[200];

      char szName[200];

 

      // Convert down to ANSI

      WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);

 

      // Get DISPID for name passed...

      hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT,

                                &dispID);

      if(FAILED(hr)) {

            sprintf(buf,

                    "IDispatch::GetIDsOfNames(\"%s\") failed w/err0x%08lx",

                    szName, hr);

//            MessageBox(NULL, buf, "AutoWrap()", 0x10010);

            _exit(0);

            return hr;

      }

 

      // Allocate memory for arguments...

      VARIANT *pArgs = new VARIANT[cArgs+1];

 

      // Extract arguments...

      for(int i=0; i

            pArgs = va_arg(marker, VARIANT);

      }

 

      // Build DISPPARAMS

      dp.cArgs = cArgs;

      dp.rgvarg = pArgs;

 

      // Handle special-case for property-puts!

      if(autoType & DISPATCH_PROPERTYPUT) {

            dp.cNamedArgs = 1;

            dp.rgdispidNamedArgs = &dispidNamed;

      }

 

      // Make the call!

      hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType,

                         &dp, pvResult, NULL, NULL);

      if(FAILED(hr)) {

            sprintf(buf,

                    "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx",

                    szName, dispID, hr);

//            MessageBox(NULL, buf, "AutoWrap()", 0x10010);

            _exit(0);

            return hr;

      }

      // End variable-argument section...

      va_end(marker);

 

      delete [] pArgs;

 

      return hr;

 

}

 

 

Posted by: Massimo Magris
Post date: 3/1/2009 10:21:06 AM

5 REPLIES

RE: C++, IDispatch how to get Item(x) ?

[ Edited ]

Massimo,

 

Dispatch::Invoke can be tricky. I'll need a little time to work up an example if you really need it. I'm curious as to why you're not using the SolidEdgePart::Models interface. I'm guessing because you're trying to make it work for traditional and synchronous environments.

 

Posted by: Jason Newell
Post date: 3/3/2009 6:38:53 AM

RE: C++, IDispatch how to get Item(x) ?

[ Edited ]

 

Hi Massimo,

here's some code I use for getting the unit type of a variable. The biggest difference to your code is that you are using  DISPATCH_PROPERTYPUT instead of  DISPATCH_PROPERTYGET. You should be able to change this to get the item if you use DISPATCH_METHOD (Item is a method, not a property) - you will also have to set the parameter for the index (a variant containing 1L)IDispatchPtr var = results->Item(1L);DISPID dispid;LPOLESTR memberName(L"UnitsType");DISPPARAMS dispparams = { NULL, NULL, 0, 0 };HRESULT hr = var->GetIDsOfNames(IID_NULL, &memberName, 1, LOCALE_SYSTEM_DEFAULT, &dispid);if (SUCCEEDED(hr)){ _variant_t utResult; hr = var->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispparams, &utResult, NULL, NULL); if (FAILED(hr)) _com_issue_error(hr);}

Hope this helps - let me know if you still have problems and I can try and get a working example. I'll also try and get something working with templates - these would be a much nicer solution. All I need to do is install ST first!

Cheers

Calum

 

Posted by: Calum McLellan
Post date: 3/3/2009 7:52:36 PM

RE: C++, IDispatch how to get Item(x) ?

[ Edited ]

 

HI Callum

now I understand what "Programming Guru" is for !! Smiley Happy

 

Thanks for the infos.

The info about template will be great.

Regards

Massimo

 

Posted by: Massimo Magris
Post date: 3/3/2009 8:53:00 PM

RE: C++, IDispatch how to get Item(x) ?

[ Edited ]

Posted By Massimo Magris on 03/04/2009 2:53 AM

 

now I understand what "Programming Guru" is for !! Smiley Happy

No doubt.  That's why I gave him that title.  He easily picked up C++ in 1/2 the time that it took me.  He's scary smart and I appreciate it when he answers questions.

 

Posted by: Jason Newell
Post date: 3/4/2009 11:11:46 AM

RE: C++, IDispatch how to get Item(x) ?

[ Edited ]

 

Hi guys,

watch out - I might get a big head if you keep going like that . Seriously though, thanks for the compliments . 

I have been playing around with template functions (I installed ST yesterday...) and haven't been having much luck. I have attached my test project (VS2008). This is a simple dialog that calls a template function (CloseDocument) passing either a part document or a sync part and calls Close() on the document interface. I can't get rid of the LNK2019 when compiling (LNK2001 on a release build). Interestingly, the template specialisation for SolidEdgeDocumentPtr works.

I'll keep trying to figure this out as it would be nice to get it working. One problem we will face is that as soon as a Solid Edge interface does not return a strongly typed interface, we cannot use the template function approach. For example, PartDocument::Models returns a ModelsPtr so we can do this in the template function: partDoc->Models->Item(1L) to get a model pointer, however Models::Item returns IDispatch so we have to query the result like this:ModelPtr model = NULL; HRESULT hr = partDoc->Models->Item(1L)->QueryInterface(&model);

This means that we need to know if we are dealing with a SolidEdgePart::Model or a SolidEdgePartSync::Model, meaning that the template function will no longer help us as we cannot know which variable type to declare.

This basically means that we are stuck with either using IDispatch or overloading functions. IDispatch means less maintainence as the code is only in one place, but it will be slower than overloaded functions.

Template functions (once we get them working) will be perfect for simple scenarios and for cases where we can't use a completely generic method (as in the case above) I will probably use a template specialisation or overloaded methods. I will certainly be moving all this into a seperate class to improve the maintainability of the code.

Hope this helps

Calum

 

Posted by: Calum McLellan
Post date: 3/4/2009 10:51:49 PM