|
问题:
现在想在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) ;
}
|
|