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

问题:

现在想在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供接口和属性类使用。

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

/*===================================================================
*					 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 指针
*/

::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__ */

添加属性类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__ */

添加接口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
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;
};
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}'
            }
     }
}

注意:这里的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)
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) ;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,你需要创建一个 QT 窗口和一个下拉菜单。你可以使用 QT Designer 来创建它们。然后,你需要将 QT 窗口嵌入到 Auto CAD 中。这可以通过 ObjectARX 中的 AcApGetMainWnd 函数来实现。 接下来,你需要将下拉菜单添加到 QT 窗口中。这可以使用 QT 中的 QComboBox 类来实现。你需要在 QComboBox 中添加所有的选项,如下所示: ``` QComboBox *comboBox = new QComboBox(); comboBox->addItem("Option 1"); comboBox->addItem("Option 2"); comboBox->addItem("Option 3"); ``` 然后,你需要将 QT 窗口嵌入到 Auto CAD 中,并将下拉菜单添加到 Auto CAD 的菜单栏中。这可以使用 ObjectARX 中的 AcMenuBar 类来实现。你需要创建一个 AcMenuBar 对象,并使用 AddMenuBar 方法将其添加到 Auto CAD 的菜单栏中。然后,你需要使用 AddMenu 方法将一个新菜单添加到 AcMenuBar 对象中。最后,你需要使用 AddMenuItem 方法将 QComboBox 添加到新菜单中。 下面是一个示例代码: ``` void AddComboBoxToMenu() { // 获取 Auto CAD 主窗口 HWND hwndCAD = acedGetAcadHwnd(); // 创建 QT 窗口 QWidget *pQTWidget = new QWidget; QComboBox *pComboBox = new QComboBox(pQTWidget); pComboBox->addItem("Option 1"); pComboBox->addItem("Option 2"); pComboBox->addItem("Option 3"); // 将 QT 窗口嵌入到 Auto CAD 中 AcApGetMainWnd()->SetWindowLongPtr(GWLP_HWNDPARENT, (LONG_PTR)hwndCAD); pQTWidget->winId(); // 将下拉菜单添加到 Auto CAD 的菜单栏中 AcMenuBar *pMenuBar = new AcMenuBar; pMenuBar->AddMenuBar(); AcMenu *pMenu = pMenuBar->AddMenu(_T("MyMenu")); pMenu->AddMenuItem(_T("MyComboBox"), (long)pQTWidget->winId()); } ``` 注意,这只是一个简单的示例代码,并且可能需要根据你的需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值