SAFEARRAY

I am using C++...so far I am able to create profile on one of reference plane

and added 2d relation ships on those entities(4 lines shapes of square, but I have difficulties to protrude those entities to cebic shape using "SAFEARRAY" see below for code I am using but I am not sure about how to use "LPSAFEARRAY" please help

 

Thank you

 

 

MdlPtr=MdlsPtr->AddFiniteExtrudedProtrusion(1,LPSAFEARRAY* PofileArray, Solidedgepart_tlb::igRight, 1.0*0.0254);

 

Posted by: Terry Goto
Post date: 3/30/2007 6:09:10 AM

13 REPLIES

RE: SAFEARRAY

Terry,

 

My VS.NET 2005 addin wizard generates code that uses SAFEARRAY's. See the following example. I'll be out of town this weekend so I can't work up a better example for you. Reply back and let me know how it goes.

 

 

STDMETHODIMP CConnect::raw_OnConnectToEnvironment( BSTR EnvironmentCatid, LPDISPATCH pEnvironment, VARIANT_BOOL bFirstTime )

{

HRESULT hr = S_OK;

 

CComBSTR bstrCommands[NUMBER_OF_COMMANDS];

CComBSTR bstrCategory;

SAFEARRAY *pCmdStrings = NULL;

SAFEARRAY *pCmdIDs = NULL;

CLSID clsid;

 

try

{

/* Populate command string array */

for (int i = 0; i

{

bstrCommands.LoadString(IDS_COMMAND_1 + i);

}

 

bstrCategory.LoadString(IDS_CATEGORY);

 

/* Allocate Safe Arrays */

pCmdStrings = SafeArrayCreateVector(VT_BSTR, 0, NUMBER_OF_COMMANDS );

pCmdIDs = SafeArrayCreateVector(VT_I4, 0, NUMBER_OF_COMMANDS );

 

/* Ensure Safe Array Allocation */

if (pCmdStrings && pCmdIDs)

{

/* Populate Safe Arrays */

for (long index = 0; index

{

hr = SafeArrayPutElement(pCmdStrings, &index, bstrCommands[index].Detach());

hr = SafeArrayPutElement(pCmdIDs, &index, &index);

}

 

/* Configure AddIn */

hr = m_pAddin->SetAddInInfo(HandleToLong( _AtlModule.GetResourceInstance()),

EnvironmentCatid, bstrCategory.m_str,

IDB_TOOLBAR_SMALL, IDB_TOOLBAR_LARGE,

IDB_TOOLBAR_SMALL, IDB_TOOLBAR_LARGE,

NUMBER_OF_COMMANDS,

&pCmdStrings, &pCmdIDs);

 

 

/* Convert BSTR -> CSLID */

CLSIDFromString(EnvironmentCatid, &clsid);

 

/* Store the runtime command ids for later use */

m_pEventManager->SetEnvironmentCommandIds(clsid, NUMBER_OF_COMMANDS, pCmdIDs);

 

/* Deallocate Safe Array */

hr = SafeArrayDestroy(pCmdStrings);

hr = SafeArrayDestroy(pCmdIDs);

}

 

#ifdef SE_ADDIN_TOOLBAR

if (bFirstTime == VARIANT_TRUE)

{

for (long index = 0; index

{

 

CommandBarButtonPtr pButton = m_pAddin->AddCommandBarButton( EnvironmentCatid, bstrCategory.m_str, index);

}

}

#endif

 

}

catch(_com_error &e)

{

hr = e.Error();

}

 

return hr;

}

 

 

Posted by: Jason Newell
Post date: 3/30/2007 8:05:10 AM

RE: SAFEARRAY

Hi Terry,

 

LPSAFEARRAY is a "Long Pointer" to a SAFEARRAY. Meaning that LPSAFEARRAY* is a pointer to a pointer to a SAFEARRAY (or a SAFEARRAY pointer passed by reference)

 

Check out the CComSAFEARRAY ATL class. It's a bit easier to use than the SAFEARRAY macros.

 

Here's the code that Jason posted using CComSAFEARRAY (the CComSAFEARRAY::GetSafeArrayPtr() method returns a LPSAFEARRAY*):

 

/* Set up the SAFEARRAYS for the call to

SetAddInInfo */

CComBSTR temp;

CComSafeArray cmdIDs(NUMBER_OF_COMMANDS);

CComSafeArray cmdNames(NUMBER_OF_COMMANDS);

 

HRESULT hr;

for (long i = 0; i

{

cmdIDs.SetAt(i, i);

 

temp.LoadString(IDS_COMMAND_1 + i);

hr = cmdNames.SetAt(i, temp.Detach(), false);

if (FAILED(hr)) return hr;

}

 

temp.LoadString(IDS_CATEGORY);

 

// TODO: Store the runtime command ids for each environment

hr = m_seAddIn->raw_SetAddInInfo(

HandleToLong(_AtlBaseModule.GetResourceInstance()),

EnvCatID, temp, IDB_TOOLBAR_SMALL, IDB_TOOLBAR_LARGE,

IDB_TOOLBAR_SMALL, IDB_TOOLBAR_LARGE, NUMBER_OF_COMMANDS,

cmdNames.GetSafeArrayPtr(), cmdIDs.GetSafeArrayPtr());

 

Cheers

Calum

 

 

Posted by: Calum McLellan
Post date: 4/2/2007 1:59:26 AM

RE: SAFEARRAY

I am not sure what kind of VT_**** uses for Profile array??

Is it VT_BSTR? VT_DISPATCH?

I tried below but did not work

 

pls help

 

Thank you

 

Terry

 

long indices=0;

VARIANT Vsfarry03;

LPSAFEARRAY prfarray;

LPDISPATCH Etp;

 

Etp = PfPtr->ProjectEdge(Etp); // PfPtr is a pointer to the profile I have 4 lines

 

Vsfarry03.vt=VT_DISPATCH;

 

Vsfarry03.pdispVal=Etp;

 

prfarray = SafeArrayCreateVector(VT_DISPATCH, 0, 1);

 

SafeArrayPutElement(prfarray, &indices, &Vsfarry03);

 

 

 

 

 

 

 

Posted by: Terry Goto
Post date: 4/2/2007 8:04:28 AM

RE: SAFEARRAY

Terry,

 

Take a closer look at Calum's use of CComSafeArray. I think you'll find his way much easier to use. There I go again doing things the hard way

 

Posted by: Jason Newell
Post date: 4/2/2007 2:45:39 PM

RE: SAFEARRAY

Hi Terry,

 

Here's an example I wrote a while back (sorry, I forgot I had this )

 

PartDocumentPtr partDoc = NULL;

HRESULT hr =

m_seApp->ActiveDocument->QueryInterface(&partDoc);

 

if (hr != S_OK)

partDoc = m_seApp->Documents->Add

(__T("SolidEdge.PartDocument"));

if (partDoc)

{

ProfileSetPtr profileSet =

partDoc->ProfileSets->Add();

RefPlanePtr refPlane =

partDoc->RefPlanes->Item((long)1);

ProfilePtr profile =

profileSet->Profiles->Add

(refPlane);

LRESULT pos = SendMessage(GetDlgItem((HWND)m_hwnd, IDC_SLIDER1),

(UINT) TBM_GETPOS, 0, 0);

double size = (((double)pos +1)/200);

 

profile->Lines2d->AddBy2Points(-size, -size, -size, size);

profile->Lines2d->AddBy2Points(-size, size, size, size);

profile->Lines2d->AddBy2Points(size, size, size, -size);

profile->Lines2d->AddBy2Points(size, -size, -size, -size);

 

CComSafeArray profiles(1);

profiles.SetAt(0, profile);

hr = partDoc->Models->AddFiniteExtrudedProtrusion(1,

profiles.GetSafeArrayPtr(), igSymmetric, (size*2));

}

 

 

I use IUnknown* (VT_UNKNOWN) for the CComSAFEARRAY.

The IDC_SLIDER1 control is just a slider that sets the size (just playing around...)

 

Hope this helps

Calum

 

Posted by: Calum McLellan
Post date: 4/2/2007 7:49:57 PM

RE: SAFEARRAY

What type library do I have to import in order to use CComSAFEARRAY class?

 

Thank you

 

Terry

 

Posted by: Terry Goto
Post date: 4/3/2007 2:11:27 AM

RE: SAFEARRAY

Hi Terry,

 

add the following include to your header:

 

#include

 

Cheers

Calum

 

Posted by: Calum McLellan
Post date: 4/3/2007 2:24:42 AM

RE: SAFEARRAY

My compiler (C++ Builder) does not have this atlsafe.h so I need to go in hard way defining SAFEARRAY, please help...

 

Thank you

 

Terry

 

Posted by: Terry Goto
Post date: 4/3/2007 4:12:15 AM

RE: SAFEARRAY

Hi Terry

 

atlsafe.h is in "C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include". This may just be a part of Visual Studio, or it may be installed with the VC++ 2005 redistributable (available here).

 

If it's not a part of the redist. then this should work (I'm writing this on the fly, so there may be the odd small error):

 

Instead of:

 

CComSafeArray profiles(1);

profiles.SetAt(0, profile);

hr = partDoc->Models->AddFiniteExtrudedProtrusion(1,

profiles.GetSafeArrayPtr(), igSymmetric, (size*2));

 

 

Try:

 

SAFEARRAY* pProfiles = NULL;

/* Allocate Safe Array */

pProfiles = SafeArrayCreateVector(VT_UNKNOWN, 0, 1 );

 

/* Ensure Safe Array Allocation */

if (pProfiles)

{

/* Populate Safe Array */

long index = 0;

hr = SafeArrayPutElement(pProfiles, &index, profile);

if (SUCCEEDED(hr))

hr = partDoc->Models->AddFiniteExtrudedProtrusion(1,

&pProfiles, igSymmetric, (size*2));

 

 

Cheers

Calum

 

Posted by: Calum McLellan
Post date: 4/3/2007 8:01:45 PM