Get Object's Persistent Reference ID Example (C++ COM)
This example shows how to get the selected object's persistent reference
ID. This example also shows how to use a modified SafeArray template class
to expect BYTE SafeArrays to parse the VARIANT returned by IModelDocExtension::GetPersistReference3.
//-----------------------------------------
// Preconditions:
// 1. Start Microsoft Visual Studio 2010.
// a. Click File > New > Project > Visual C++ > Win32 Console Application.
// b. Type the name of your project in Name.
// c. Click OK.
// d. Click Next.
// e. Select ATL and click Finish.
// f. Click Project > projectname Properties > Configuration Properties >
// C/C++ and type the path to sldworks.tlb and swconst.tlb,
// typically C:\Program Files\SolidWorks Corp\SolidWorks, in
// Additional Include Directories
// g. Click OK.
// 2. Replace the code in the code window with this code.
// 3. Create a header file called smartvars.h containing this code and
// add the header file to your project.
// 4. Start up SolidWorks and open a model document.
// 5. Select a vertex, line, face, or some other
// selectable entity.
// 6. Click Debug > Start Debugging.
// 7. Click Yes.
//
// Postconditions:
// 1. Gets each byte value in a Variant SafeArray of byte values
// of the persistent reference ID.
// 2. Pops up a message box showing the size of of the persistent
// reference ID assigned to the selected object.
// 3. Click OK to close the message box.
//-----------------------------------------
//This code
#include "stdafx.h"
#include <string>
#import "sldworks.tlb" raw_interfaces_only, raw_native_types, no_namespace, named_guids //SolidWorks type library
#import "swconst.tlb" no_namespace, raw_native_types, no_namespace, named_guids //SolidWorks constants type library
#include "smartvars.h"
template <typename T>
std::string number_to_string(T number)
{
return dynamic_cast<std::stsringstream *> (&(std::stringstream() << number))->str();
}
int _tmain(int argc, TCHAR* argv[])
{
//Initialize COM
//Do this before using ATL smart pointers so that
//COM is available
CoInitialize(NULL);
//Use a block so that the smart pointers are destructed when
//scope of this block is exited
{
//Use ATL smart pointers
CComPtr<ISldWorks> swApp;
if(swApp.CoCreateInstance(L"SldWorks.Application", NULL, CLSCTX_LOCAL_SERVER) != S_OK){
return(0);
}
CComPtr<IModelDoc2> swDoc;
swApp->get_IActiveDoc2(&swDoc);
CComPtr<IModelDocExtension> swDocExt;
swDoc->get_Extension(&swDocExt);
CComPtr<ISelectionMgr> swSelMgr;
swDoc->get_ISelectionManager(&swSelMgr);
CComPtr<IDispatch> disp;
swSelMgr->GetSelectedObject6(1, -1, &disp);
//Get the persistent reference ID for the selected object
_variant_t varPersist;
swDocExt->GetPersistReference3(disp, &varPersist);
long sizePersistIDs;
swDocExt->GetPersistReferenceCount3(disp, &sizePersistIDs);
CString strPersist;
SafeByteArray byteArr(varPersist);
BYTE* bytes = new BYTE[byteArr.getSize()];
for(int i = 0; i < byteArr.getSize(); i++)
{
bytes[i] = byteArr[i];
//TODO: Do something with the bytes array
}
_bstr_t s;
s = (long)sizePersistIDs;
CComBSTR msg;
msg = (OLESTR("Size of persistent reference IDs: "));
msg.AppendBSTR(s);
long res;
//Pop up a message box with the size of persistent
//reference IDs for the selected object
swApp->SendMsgToUser2(msg, 0, 0, &res);
//Delete the array
delete [] bytes;
}
//ATL smart pointers are destructed so that all COM objects
//held on to are released
//Shut down COM because you no longer need it
CoUninitialize();
return(0);
}
//smartvars.h
#pragma once
#include <cassert>
template <class T,int type> class SafeArray
{
public:
SafeArray(VARIANT *input):
m_input(input),
m_access(false),
m_bCreate(false),
m_pSafeArray(NULL),
m_arrayData(NULL),
m_result(S_OK)
{
if(m_input != NULL)
{
if (V_VT(m_input) != VT_EMPTY)
{
m_pSafeArray = V_ARRAY (m_input);
m_result = SafeArrayAccessData ( m_pSafeArray, (void HUGEP**)&m_arrayData);
m_access = m_result == S_OK ;
}
else
m_access = true;
}
else
{
ASSERT(FALSE);
m_input = &m_target;
}
}
SafeArray(const VARIANT &input) :
m_access(true),
m_bCreate(false),
m_pSafeArray(NULL),
m_arrayData(NULL),
m_result(S_OK)
{
m_input = (VARIANT *) &input;
if (V_VT(m_input) != VT_EMPTY)
{
m_pSafeArray = V_ARRAY (m_input);
m_result = SafeArrayAccessData ( m_pSafeArray, (void HUGEP**)&m_arrayData);
m_access = m_result == S_OK ;
}
else
m_access = true;
}
SafeArray(unsigned int size,unsigned int dims = 1):
m_input(&m_target),
m_access(false),
m_bCreate(true),
m_pSafeArray(NULL),
m_arrayData(NULL),
m_result(S_OK)
{
ASSERT(size >= 0);
if(size > 0)
{
m_rgsabound[0].lLbound = 0;
m_rgsabound[0].cElements = (int) size;
m_pSafeArray = SafeArrayCreate(type, (int)dims, m_rgsabound);
V_VT(m_input) = VT_ARRAY | type;
m_result = SafeArrayAccessData( m_pSafeArray, (void HUGEP**)&m_arrayData);
m_access = m_result == S_OK ;
if(!m_access)
V_VT(m_input) = VT_EMPTY;
}
else
{
V_VT(m_input) = VT_EMPTY;
m_access = true;
}
}
inline HRESULT status(){return m_result;}
inline int getSize(int index = 0) {return (m_access&&m_pSafeArray)?m_pSafeArray->rgsabound[index].cElements:0;}
~SafeArray(){UnaccessData();}
operator T* () {ASSERT(m_access);return m_arrayData;}
operator VARIANT () {ASSERT(m_access);UnaccessData();return *m_input;}
T & operator[](int i) {assert(m_access&&m_arrayData);return m_arrayData[i];}
SAFEARRAY* getSafeArrayData() {return m_pSafeArray;}
private:
void UnaccessData(){
if(m_access){
m_result = SafeArrayUnaccessData( m_pSafeArray );
if(m_bCreate && m_result == S_OK)
V_ARRAY(m_input) = m_pSafeArray;
m_access = false;
}
}
bool m_bCreate;
bool m_access;
VARIANT *m_input;
VARIANT m_target;
T *m_arrayData ;
SAFEARRAY *m_pSafeArray;
SAFEARRAYBOUND m_rgsabound[1];
HRESULT m_result;
};
template <typename T> inline T GetSpecificInterface(IUnknown* pUnk, const IID& iid, T &specificInterface)
{
specificInterface = NULL;
If (NULL != pUnk)
{
HRESULT res = pUnk->QueryInterface(iid, (LPVOID*)&specificInterface);
if (specificInterface)
specificInterface->Release
}
return specificdInterface;
}
typedef SafeArray<VARIANT_BOOL, VT_BOOL> SafeBooleanArray ;
typedef SafeArray<double, VT_R8> SafeDoubleArray ;
typedef SafeArray<long, VT_I4> SafeLongArray ;
typedef SafeArray<BYTE, VT_I1> SafeByteArray ;
typedef SafeArray<BYTE, VT_UI1> SafeUByteArray ;
typedef SafeArray<BSTR, VT_BSTR> SafeBSTRArray ;
typedef SafeArray<LPDISPATCH, VT_DISPATCH> SafeDISPATCHArray ;
typedef SafeArray<LPVARIANT, VT_VARIANT> SafeVARIANTArray ;