天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 72|回复: 0

ObjectArx 使用COM接口添加CAD特性表自定义数据

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
问题:
现在想在CAD的特性表上添加自定义数据,用来显示数据和修改数据。

思路:
通过ObjectArx提供的工作手册,找到了 SheetSet 的说明(如图),但是没有找到示例。

不过也可以了解到是通过COM接口来实现。通过摸索,现在可以自定义添加基本类型的数据显示和修改了,将操作记录如下。
目前下拉列表如何添加还有待研究,后续会再更新。

解决:
1、准备工作:需要先生成GUID以备使用。
GUIDGEN.exe 可能存在路径:
“C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\guidgen.exe”
“D:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\guidgen.exe”

使用GUIDGEN.exe 生成两个UID供接口和属性类使用。

数值类型说明:(这里只说明几个常用类型,更多类型可详见:[url]https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.interopservices.varenum?view=net-6.0[/url])

/*===================================================================
*                                         VARTYPE 数据类型
*===================================================================*/
/*
* VT_I1                        char
* VT_I2                        short
* VT_I4                        long
* VT_I8                        64位整数
* VT_INT                int
* VT_R4                        float
* VT_R8                        double
* VT_DATE                日期
* VT_BSTR                字符串类型
* VT_BYREF                引用
* VT_LPSTR                以 NULL 结尾的字符串
* VT_LPWSTR                由 null 终止的宽字符串
* VT_PTR                指针
* VT_VECTOR                简单的已计数数组
* VT_ARRAY                SAFEARRAY 指针
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
::SysAllocString 进行cstring 到 bstr的转换

2、在Z_PIDDynamicProperty.h文件中添加定义:
在 Forward Declarations 添加接口IZ_pidEntityDynPropSitNumber定义:

// Forward Declarations
#ifndef __IZ_pidEntityDynPropSitNumber_FWD_DEFINED__
#define __IZ_pidEntityDynPropSitNumber_FWD_DEFINED__
typedef interface IZ_pidEntityDynPropSitNumber IZ_pidEntityDynPropSitNumber;
#endif        /* __IZ_pidEntityDynPropSitNumber_FWD_DEFINED__ */
1
2
3
4
5
添加属性类Z_pidEntityDynPropSitNumber定义:

#ifndef __Z_pidEntityDynPropSitNumber_FWD_DEFINED__
#define __Z_pidEntityDynPropSitNumber_FWD_DEFINED__
#ifdef __cplusplus
typedef class Z_pidEntityDynPropSitNumber Z_pidEntityDynPropSitNumber;
#else
typedef struct Z_pidEntityDynPropSitNumber Z_pidEntityDynPropSitNumber;
#endif /* __cplusplus */
#endif        /* __Z_pidEntityDynPropSitNumber_FWD_DEFINED__ */
1
2
3
4
5
6
7
8
添加接口IZ_pidEntityDynPropSitNumber定义并绑定一个UID:

#ifndef __IZ_pidEntityDynPropSitNumber_INTERFACE_DEFINED__
#define __IZ_pidEntityDynPropSitNumber_INTERFACE_DEFINED__
       /* interface IZ_pidEntityDynPropSitNumber */
       /* [unique][helpstring][nonextensible][dual][uuid][object] */
       EXTERN_C const IID IID_IZ_pidEntityDynPropSitNumber;
#if defined(__cplusplus) && !defined(CINTERFACE)
       MIDL_INTERFACE("2C378F4A-928B-4359-8CCD-1BB499D1E6A4")
              IZ_pidEntityDynPropSitNumber : public IDispatch
       {
       public:
       };
#else  /* C style interface */
       typedef struct IZ_pidEntityDynPropSitNumberVtbl
       {
              BEGIN_INTERFACE
                     HRESULT(STDMETHODCALLTYPE* QueryInterface)(
                           IZ_pidEntityDynPropSitNumber* This,
                           /* [in] */ REFIID riid,
                           /* [annotation][iid_is][out] */
                           _COM_Outptr_  void** ppvObject);
              ULONG(STDMETHODCALLTYPE* AddRef)(
                     IZ_pidEntityDynPropSitNumber* This);
              ULONG(STDMETHODCALLTYPE* Release)(
                     IZ_pidEntityDynPropSitNumber* This);
              HRESULT(STDMETHODCALLTYPE* GetTypeInfoCount)(
                     IZ_pidEntityDynPropSitNumber* This,
                     /* [out] */ UINT* pctinfo);
              HRESULT(STDMETHODCALLTYPE* GetTypeInfo)(
                     IZ_pidEntityDynPropSitNumber* This,
                     /* [in] */ UINT iTInfo,
                     /* [in] */ LCID lcid,
                     /* [out] */ ITypeInfo** ppTInfo);
              HRESULT(STDMETHODCALLTYPE* GetIDsOfNames)(
                     IZ_pidEntityDynPropSitNumber* This,
                     /* [in] */ REFIID riid,
                     /* [size_is][in] */ LPOLESTR* rgszNames,
                     /* [range][in] */ UINT cNames,
                     /* [in] */ LCID lcid,
                     /* [size_is][out] */ DISPID* rgDispId);
              /* [local] */ HRESULT(STDMETHODCALLTYPE* Invoke)(
                     IZ_pidEntityDynPropSitNumber* This,
                     /* [annotation][in] */
                     _In_  DISPID dispIdMember,
                     /* [annotation][in] */
                     _In_  REFIID riid,
                     /* [annotation][in] */
                     _In_  LCID lcid,
                     /* [annotation][in] */
                     _In_  WORD wFlags,
                     /* [annotation][out][in] */
                     _In_  DISPPARAMS* pDispParams,
                     /* [annotation][out] */
                     _Out_opt_  VARIANT* pVarResult,
                     /* [annotation][out] */
                     _Out_opt_  EXCEPINFO* pExcepInfo,
                     /* [annotation][out] */
                     _Out_opt_  UINT* puArgErr);
              END_INTERFACE
       } IZ_pidEntityDynPropSitNumberVtbl;
       interface IZ_pidEntityDynPropSitNumber
       {
              CONST_VTBL struct IZ_pidEntityDynPropSitNumberVtbl* lpVtbl;
       };
#ifdef COBJMACROS
#define IZ_pidEntityDynPropSitNumber_QueryInterface(This,riid,ppvObject)   \
    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IZ_pidEntityDynPropSitNumber_AddRef(This)      \
    ( (This)->lpVtbl -> AddRef(This) )
#define IZ_pidEntityDynPropSitNumber_Release(This)     \
    ( (This)->lpVtbl -> Release(This) )
#define IZ_pidEntityDynPropSitNumber_GetTypeInfoCount(This,pctinfo)  \
    ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) )
#define IZ_pidEntityDynPropSitNumber_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
    ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) )
#define  IZ_pidEntityDynPropSitNumber_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)     \
    ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) )
#define  IZ_pidEntityDynPropSitNumber_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)  \
    ( (This)->lpVtbl ->  Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) )
#endif /* COBJMACROS */
#endif        /* C style interface */
#endif /* __IZ_pidEntityDynPropSitNumber_INTERFACE_DEFINED__ */

Z_pidEntityDynPropSitNumber绑定另一个UID:

EXTERN_C const CLSID CLSID_Z_pidEntityDynPropSitNumber;
#ifdef __cplusplus
class DECLSPEC_UUID("5CA62DBE-430E-4CC5-A2A3-9F7D9DC76801")
Z_pidEntityDynPropSitNumber;
#endif

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
3、在Z_PIDDynamicProperty.idl文件中:
绑定UID和添加接口描述:

[
    object,
      uuid(2C378F4A-928B-4359-8CCD-1BB499D1E6A4),
      dual,
      nonextensible,
      helpstring("IZ_pidEntityDynPropSitNumber Interface"),
      pointer_default(unique)
]
interface IZ_pidEntityDynPropSitNumber : IDispatch {
};


[
      uuid(5CA62DBE-430E-4CC5-A2A3-9F7D9DC76801),
      helpstring("Z_pidEntityDynPropSitNumber Class")
]
coclass Z_pidEntityDynPropSitNumber
{
      [default] interface IZ_pidEntityDynPropSitNumber;
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
4、添加对应的资源文件 IDR_Z_PIDENTITYDYNPROPSITNUMBER Z_pidEntityDynPropSitNumber.rgs
HKCR
{
    Z_PIDDynamicProperty.Z_pidAnnotationD.1 = s 'Z_pidEntityDynPropSitNumber  Class'
     {
            CLSID = s '{5CA62DBE-430E-4CC5-A2A3-9F7D9DC76801}'
     }
     Z_PIDDynamicProperty.Z_pidAnnotationDyn = s 'Z_pidEntityDynPropSitNumber  Class'
     {
            CLSID = s '{5CA62DBE-430E-4CC5-A2A3-9F7D9DC76801}'
            CurVer = s 'Z_PIDDynamicProperty.Z_pidAnnotationD.1'
     }
     NoRemove CLSID
     {
            ForceRemove {5CA62DBE-430E-4CC5-A2A3-9F7D9DC76801} = s  'Z_pidEntityDynPropSitNumber Class'
            {
                   ProgID = s 'Z_PIDDynamicProperty.Z_pidAnnotationD.1'
                   VersionIndependentProgID = s  'Z_PIDDynamicProperty.Z_pidAnnotationDyn'
                   ForceRemove 'Programmable'
                   InprocServer32 = s '%MODULE%'
                   {
                         val ThreadingModel = s 'Apartment'
                   }
                   val AppID = s '%APPID%'
                   'TypeLib' = s '{83142DFE-EAA6-456F-91CE-2E7E6F6AF7CA}'
            }
     }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
注意:这里的UID和前面设置的UID是对应的。

5、添加属性类头文件Z_pidEntityDynPropSitNumber.h:
#pragma once
#include "resource.h"
#include "Z_PIDDynamicProperty.h"
#include "Z_PID/Z_PIDEntity/Z_pidBaseEnt.h"
//----- CZ_pidEntityDynPropSitNumber
class ATL_NO_VTABLE CZ_pidEntityDynPropSitNumber :
       public CComObjectRootEx<CComSingleThreadModel>,
       public CComCoClass<CZ_pidEntityDynPropSitNumber,  &CLSID_Z_pidEntityDynPropSitNumber>,
       public ISupportErrorInfo,
       public IDispatchImpl<IZ_pidEntityDynPropSitNumber,  &IID_IZ_pidEntityDynPropSitNumber, &LIBID_Z_PIDDynamicPropertyLib, /*wMajor =*/ 1,  /*wMinor =*/ 0>,
       public ICategorizeProperties,
       public IDynamicProperty2
{
public:
       CZ_pidEntityDynPropSitNumber () {
       }
       DECLARE_REGISTRY_RESOURCEID(IDR_Z_PIDENTITYDYNPROPSITNUMBER)
       BEGIN_COM_MAP(CZ_pidEntityDynPropSitNumber)
              COM_INTERFACE_ENTRY(IZ_pidEntityDynPropSitNumber)
              COM_INTERFACE_ENTRY(IDispatch)
              COM_INTERFACE_ENTRY(ISupportErrorInfo)
              COM_INTERFACE_ENTRY(ICategorizeProperties)
              COM_INTERFACE_ENTRY(IDynamicProperty2)
       END_COM_MAP()
       //----- ISupportsErrorInfo
       STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
       DECLARE_PROTECT_FINAL_CONSTRUCT()
       HRESULT FinalConstruct () {
              return (S_OK) ;
       }
      
       void FinalRelease () {
       }
       IDynamicPropertyNotify2 *m_pNotify ;
public:
       //IDynamicProperty2
       STDMETHOD(GetGUID)(GUID* propGUID) ;
       STDMETHOD(GetDisplayName)(BSTR* bstrName) ;
       STDMETHOD(IsPropertyEnabled)(IUnknown *pUnk, BOOL* pbEnabled) ;
       STDMETHOD(IsPropertyReadOnly)(BOOL* pbReadonly) ;
       STDMETHOD(GetDescription)(BSTR* bstrName) ;
       STDMETHOD(GetCurrentValueName)(BSTR* pbstrName) ;
       STDMETHOD(GetCurrentValueType)(VARTYPE* pVarType) ;
       STDMETHOD(GetCurrentValueData)(IUnknown *pUnk, VARIANT* pvarData) ;
       STDMETHOD(SetCurrentValueData)(IUnknown *pUnk, const VARIANT varData) ;
       STDMETHOD(Connect)(IDynamicPropertyNotify2* pSink) ;
       STDMETHOD(Disconnect)() ;
       //ICategorizePropery
       STDMETHOD(MapPropertyToCategory)(DISPID dispid, PROPCAT* ppropcat) ;
       STDMETHOD(GetCategoryName)(PROPCAT propcat, LCID lcid, BSTR* pbstrName) ;
       //IZ_pidEntityDynPropSitNumber
} ;
OBJECT_ENTRY_AUTO(__uuidof(Z_pidEntityDynPropSitNumber),  CZ_pidEntityDynPropSitNumber)
OPM_DYNPROP_OBJECT_ENTRY_AUTO(CZ_pidEntityDynPropSitNumber, Z_pidBaseEnt)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
6、添加属性类的cpp文件 Z_pidEntityDynPropSitNumber.cpp:
#include "StdAfx.h"
#include "Z_pidEntityDynPropSitNumber.h"
//----- CZ_pidEntityDynPropSitNumber
STDMETHODIMP CZ_pidEntityDynPropSitNumber::InterfaceSupportsErrorInfo(REFIID riid)  {
       static const IID* arr [] ={
              &IID_IZ_pidEntityDynPropSitNumber
       } ;
       for ( int i =0 ; i < sizeof (arr) / sizeof (arr [0]) ; i++ ) {
              if ( InlineIsEqualGUID (*arr [i], riid) )
                     return (S_OK) ;
       }
       return (S_FALSE) ;
}
//----- IDynamicProperty
STDMETHODIMP CZ_pidEntityDynPropSitNumber::GetGUID (GUID *pPropGUID) {
       if ( pPropGUID == NULL )
              return (E_POINTER) ;
       // TODO: add your code here (and comment the line below)
       memcpy (pPropGUID, &CLSID_Z_pidEntityDynPropSitNumber, sizeof(GUID)) ;
       return (S_OK) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::GetDisplayName (BSTR *pBstrName) {
       if ( pBstrName == NULL )
              return (E_POINTER) ;
       // TODO: add your code here (and comment the line below)
       *pBstrName =::SysAllocString (L"位号") ;
       return (S_OK) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::IsPropertyEnabled (IUnknown *pUnk, BOOL  *pbEnabled) {
       if ( pUnk == NULL )
              return (E_INVALIDARG) ;
       if ( pbEnabled == NULL )
              return (E_POINTER) ;
       // TODO: add your code here (and comment the line below)
       *pbEnabled =TRUE ;
       return (S_OK) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::IsPropertyReadOnly (BOOL *pbReadOnly) {
       if ( pbReadOnly == NULL )
              return (E_POINTER) ;
       // TODO: add your code here (and comment the line below)
       *pbReadOnly =FALSE ;
       return (S_OK) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::GetDescription (BSTR *pBstrName) {
       if ( pBstrName == NULL )
              return (E_POINTER) ;
       // TODO: add your code here (and comment the line below)
       *pBstrName =::SysAllocString (L"位号") ;
       return (S_OK) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::GetCurrentValueName (BSTR *pBstrName) {
       if ( pBstrName == NULL )
              return (E_POINTER) ;
       // TODO: add your code here
       //return (S_OK) ; //----- If you do anything in there
       return (E_NOTIMPL) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::GetCurrentValueType (VARTYPE *pVarType)  {
       if ( pVarType == NULL )
              return (E_POINTER) ;
       // TODO: add your code here (and comment the line below)
       *pVarType = VT_R8; //-----
       return (S_OK) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::GetCurrentValueData (IUnknown *pUnk,  VARIANT *pVarData) {
       if ( pUnk == NULL )
              return (E_INVALIDARG) ;
       if ( pVarData == NULL )
              return (E_POINTER) ;
       // TODO: add your code here (and comment the 3 lines below)
       ::VariantInit (pVarData) ;
      
       V_VT(pVarData) = VT_BSTR;
      
       LONG_PTR oldID;
       ((ZwaNR_IAcadObject*)pUnk)->get_ObjectID(&oldID);
       AcDbObjectId objID;
       objID.setFromOldId(oldID);
       AcDbObjectPointer<Z_pidBaseEnt> pEntity(objID, AcDb::kForRead);
       if (Acad::eOk != pEntity.openStatus())
              return E_FAIL;
       CString sName = pEntity->number().c_str();
       V_BSTR(pVarData) = ::SysAllocString(sName);
       return (S_OK) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::SetCurrentValueData (IUnknown *pUnk,  const VARIANT varData) {
       if ( pUnk == NULL )
              return (E_INVALIDARG) ;
       // TODO: add your code here
       LONG_PTR oldID;
       ((ZwaNR_IAcadObject*)pUnk)->get_ObjectID(&oldID);
       AcDbObjectId objID;
       objID.setFromOldId(oldID);
       Zwa::DocumentLock lk;
       AcDbObjectPointer<Z_pidBaseEnt> pEntity(objID, AcDb::kForWrite);
       if (Acad::eOk != pEntity.openStatus())
              return E_FAIL;
       ZTString sNumber( ZTStringFormat(_T("{}"), varData.dblVal));
       pEntity->setNumber(sNumber);
      
       m_pNotify->OnChanged(pUnk);
      
       return (S_OK);
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::Connect (IDynamicPropertyNotify2  *pSink) {
       if ( pSink == NULL )
              return (E_POINTER) ;
       m_pNotify =pSink ;
       m_pNotify->AddRef () ;
       return (S_OK) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::Disconnect () {
       if ( m_pNotify ) {
              m_pNotify->Release () ;
              m_pNotify= NULL ;
       }
       return (S_OK) ;
}
//----- ICategorizePropertes
STDMETHODIMP CZ_pidEntityDynPropSitNumber::MapPropertyToCategory (DISPID dispid,  PROPCAT *pPropCat) {
       if ( pPropCat == NULL )
              return (E_POINTER) ;
       // TODO: add your code here (and comment the line below)
       *pPropCat =0 ;
       return (S_OK) ;
}
STDMETHODIMP CZ_pidEntityDynPropSitNumber::GetCategoryName (PROPCAT propcat, LCID  lcid, BSTR *pBstrName) {
       if ( pBstrName == NULL )
              return (E_POINTER) ;
       // TODO: add your code here (and comment the 3 lines below)
       if ( propcat != 0 )
              return (E_INVALIDARG) ;
       *pBstrName =::SysAllocString (L"实体") ;
       return (S_OK) ;
}

 

 

 

 

ObjectArx 使用COM接口添加CAD特性表自定义数据
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 11:45 , Processed in 0.131703 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表