ADN Open CIS
Сообщество программистов Autodesk в СНГ

24/05/2013

Не-COM свойства со списком возможных значений

В Палитре свойств вы можете найти свойства, которые принимают только значения, которые перечислены для свойства. Если вы хотите создать такое свойство, тогда вам нужно создать новый перечисляемый тип и использовать его для создания нового AcRxValueType, который реализует интерфейс IAcRxEnumeration

Файл заголовка

Код - C++: [Выделить]
  1. ////////////////////////////////////////////
  2. // MyEnumType
  3. ////////////////////////////////////////////
  4.  
  5. typedef enum {} MyEnum;
  6.  
  7. template<typename ValueType>
  8. class MyValueTypeTemplate : public AcRxValueType
  9. {
  10. public:
  11.   MyValueTypeTemplate(const ACHAR* name,
  12.     const IAcRxEnumeration& pEnum,
  13.     AcRxMemberCollectionConstructorPtr memberConstruct,
  14.     void* userData = NULL):
  15.   AcRxValueType(name,pEnum, sizeof(ValueType),
  16.     memberConstruct, userData) {}
  17.   virtual int subToString(const void* instance, ACHAR* buffer,
  18.     size_t sizeInACHARs, AcRxValueType::StringFormat format)
  19.     const ADESK_OVERRIDE;
  20.   virtual bool subEqualTo(const void* a, const void* b)
  21.     const ADESK_OVERRIDE;
  22. };
  23.  
  24. template<typename ValueType>
  25. class MyEnumTypeTemplate :
  26.   public MyValueTypeTemplate<ValueType>, public IAcRxEnumeration
  27. {
  28.   AcArray<const AcRxEnumTag*> m_tags;
  29.  
  30. public:
  31.   MyEnumTypeTemplate(const ACHAR* name,
  32.     AcRxMemberCollectionConstructorPtr memberConstruct,
  33.     void* userData = NULL):
  34.   MyValueTypeTemplate<ValueType>(
  35.     name,*this, memberConstruct, userData) {}
  36.  
  37.   ~MyEnumTypeTemplate()
  38.   {
  39.     for (int i=m_tags.length()-1;i>=0;i--)
  40.       AcRxMember::deleteMember(m_tags[i]);
  41.   }
  42.  
  43.   virtual int count() const ADESK_OVERRIDE
  44.   {
  45.     return m_tags.length();
  46.   }
  47.  
  48.   virtual const AcRxEnumTag& getAt(int i) const ADESK_OVERRIDE
  49.   {
  50.     return *m_tags[i];
  51.   }
  52.  
  53.   void append(AcRxEnumTag& tag)
  54.   {
  55.     m_tags.append(&tag);
  56.     void acdbImpSetOwnerForEnumTag(
  57.       const AcRxClass*, AcRxEnumTag*);
  58.     acdbImpSetOwnerForEnumTag(this, &tag);
  59.   }
  60. };
  61.  
  62. ////////////////////////////////////////////
  63. // MyListProperty
  64. ////////////////////////////////////////////
  65.  
  66. class MyListProperty : public AcRxProperty 
  67. {
  68. public:
  69.   static AcRxObject * makeMyListProperty();
  70.  
  71.   static const ACHAR * kCategoryName;
  72.   static AcRxCategory * category;
  73.  
  74.   MyListProperty();
  75.   virtual ~MyListProperty();
  76.  
  77.   virtual Acad::ErrorStatus subGetValue(
  78.     const AcRxObject* pO, AcRxValue& value) const;
  79.  
  80.   virtual Acad::ErrorStatus subSetValue(
  81.     AcRxObject* pO, const AcRxValue& value) const;
  82. };

 

C++ файл

Код - C++: [Выделить]
  1. ////////////////////////////////////////////
  2. // MyEnumType
  3. ////////////////////////////////////////////
  4.  
  5. void makeMyEnumTypeTemplateProperties(
  6.   class AcRxMemberCollectionBuilder & collectionBuilder, void*);
  7.  
  8. template<>
  9. int MyEnumTypeTemplate<MyEnum>::subToString(
  10.   const void *instance, ACHAR *buffer, size_t sizeInACHARs,
  11.   AcRxValueType::StringFormat format) const
  12. {
  13.   const ACHAR* formatString = L"%d";
  14.   MyEnum & value = *(MyEnum*)instance;
  15.   if (buffer==NULL)
  16.     return _scwprintf(formatString,value);
  17.   return swprintf_s(buffer,sizeInACHARs,formatString,value);
  18. }
  19.  
  20. template<>
  21. bool MyEnumTypeTemplate<MyEnum>::subEqualTo(
  22.   const void *a, const void* b) const
  23. {
  24.   MyEnum & v1 = *(MyEnum*)a;
  25.   MyEnum & v2 = *(MyEnum*)b;
  26.   return v1==v2;
  27. }
  28.  
  29. template<>
  30. struct AcRxValueType::Desc< MyEnum >
  31. {
  32.   __declspec(dllexport) static const AcRxValueType& value() throw();
  33.   static void del();
  34. };
  35.  
  36. MyEnumTypeTemplate<MyEnum>* s_pMyEnumTypeTemplate = NULL;
  37.  
  38. const AcRxValueType& AcRxValueType::Desc< MyEnum >::value() throw()
  39. {
  40.   if (s_pMyEnumTypeTemplate==NULL)
  41.   {
  42.     s_pMyEnumTypeTemplate = new MyEnumTypeTemplate<MyEnum>(
  43.       L"MyEnumProperties",&makeMyEnumTypeTemplateProperties);
  44.     AcRxEnumTag* pTag;
  45.     pTag = new  AcRxEnumTag  (L"Один", (int)0);
  46.     s_pMyEnumTypeTemplate->append(*pTag);
  47.     pTag = new  AcRxEnumTag  (L"Два", (int)1);
  48.     s_pMyEnumTypeTemplate->append(*pTag);
  49.     pTag = new  AcRxEnumTag  (L"Три", (int)2);
  50.     s_pMyEnumTypeTemplate->append(*pTag);
  51.     pTag = new  AcRxEnumTag  (L"Четыре", (int)3);
  52.     s_pMyEnumTypeTemplate->append(*pTag);
  53.   }
  54.   return *s_pMyEnumTypeTemplate;
  55. };
  56.  
  57. // Это должно вызываться, когда тип значения больше не нужен
  58. // Лучшее место для вызова этого метода, когда модуль выгружается (On_kUnloadAppMsg)
  59. void AcRxValueType::Desc< MyEnum >::del()
  60. {
  61.   if (s_pMyEnumTypeTemplate)
  62.   {
  63.     const ACHAR * name = s_pMyEnumTypeTemplate->name();
  64.  
  65.     if (acrxSysRegistry())
  66.       acrxClassDictionary->remove(s_pMyEnumTypeTemplate->name());
  67.  
  68.     s_pMyEnumTypeTemplate = NULL;
  69.   }
  70. };
  71.  
  72. void makeMyEnumTypeTemplateProperties(
  73.   class AcRxMemberCollectionBuilder & collectionBuilder, void*)
  74. {
  75. }
  76.  
  77. ////////////////////////////////////////////
  78. // MyListProperty
  79. ////////////////////////////////////////////
  80.  
  81. const ACHAR * MyListProperty::kCategoryName = _T("My Category");
  82.  
  83. AcRxCategory * MyListProperty::category = NULL;
  84.  
  85. MyListProperty::MyListProperty() :
  86. AcRxProperty(_T("My List Property"),
  87.   AcRxValueType::Desc< MyEnum >::value())
  88. {
  89.   if (category == NULL)
  90.   {
  91.     AcRxCategory * parent =  AcRxCategory::rootCategory();
  92.     category = parent->findDescendant(kCategoryName);
  93.     if (category == NULL)
  94.       category = new AcRxCategory(kCategoryName, parent);
  95.   }
  96.  
  97.   // OPM = Object Property Manager / Property Palette (Палитра свойств)
  98.  
  99.   // Добавим атрибут в категорию OPM Положение, в которой он будет виден
  100.   attributes().add(new AcRxUiPlacementAttribute(kCategoryName, 0));
  101.   // Добавим этот атрибут так, чтобы AutoCAD автоматически создал
  102.   // COM – обертку для этого свойства, т.е. он бы был виден в OPM
  103.   attributes().add(new AcRxGenerateDynamicPropertiesAttribute());
  104. }
  105.  
  106. MyListProperty::~MyListProperty()
  107. {
  108. }
  109.  
  110. /// <summary>
  111. /// Этот метод вызывается системой для получения
  112. /// свойства для определенного объекта
  113. /// </summary>
  114. Acad::ErrorStatus MyListProperty::subGetValue(
  115.   const AcRxObject* pO, AcRxValue& value) const
  116. {
  117.   AcDbEntity * ent = AcDbEntity::cast(pO);
  118.   if (ent == NULL)
  119.     return Acad::eNotThatKindOfClass;
  120.  
  121.   // Получение значения собственного свойства
  122.   // или там где мы хранили это значение
  123.   AEN1MyCircle * pMyCircle = AEN1MyCircle::cast(pO);
  124.   value = AcRxValue(static_cast<MyEnum>(pMyCircle->m_myEnum)); 
  125.  
  126.   return Acad::eOk;
  127. }
  128.  
  129. /// <summary>
  130. /// Этот метод вызывается системой для получения
  131. /// свойства для определенного объекта
  132. /// </summary>
  133. Acad::ErrorStatus MyListProperty::subSetValue(
  134.   AcRxObject* pO, const AcRxValue& value) const
  135. {
  136.   AcDbEntity * ent = AcDbEntity::cast(pO);
  137.   if (ent == NULL)
  138.     return Acad::eNotThatKindOfClass;
  139.  
  140.   const MyEnum * val = rxvalue_cast<MyEnum>(&value);
  141.   if (val == NULL)
  142.     return Acad::eInvalidInput;
  143.  
  144.   // Установка свойства собственного примитива
  145.   // или сохранение там, где мы хотим
  146.  
  147.   AEN1MyCircle * pMyCircle = AEN1MyCircle::cast(pO);
  148.   pMyCircle->m_myEnum = *val; 
  149.  
  150.   return Acad::eOk;
  151. }
  152.  
  153. /// <summary>
  154. /// Функция вызывается для создания экземпляра нашего класса
  155. /// </summary>
  156. AcRxObject * MyListProperty::makeMyListProperty()
  157. {
  158.   return new MyListProperty();
  159. }

 

Источник: http://adndevblog.typepad.com/autocad/2012/04/non-com-property-with-list-of-possible-values.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=41.0

Опубликовано 24.05.2013
Отредактировано 06.06.2013 в 00:29:54