dynpropmgr.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //
  2. //
  3. //////////////////////////////////////////////////////////////////////////////
  4. //
  5. // Copyright 2015 Autodesk, Inc. All rights reserved.
  6. //
  7. // Use of this software is subject to the terms of the Autodesk license
  8. // agreement provided at the time of installation or download, or which
  9. // otherwise accompanies this software in either electronic or hard copy form.
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Written by Cyrille Fauvel
  14. // Autodesk Developer Technical Services
  15. // The AcRxDynPropMgr class is used internally by AcRxArxApp to map
  16. // dynamic property classes to AcRxClass instances. ObjectARX applications
  17. // that do not use AcRxArxApp may use AcRxDynPropMgr by dynamically
  18. // instantiating it in the acrxEntryPoint method's AcRx::kInitAppMsg case,
  19. // and deleting it in the AcRx::kUnloadAppMsg case.
  20. //
  21. // AcRxDynPropMgr uses the OPM_DYNPROP_OBJECT_ENTRY_AUTO macro for its
  22. // mappings to classes. Clients should declare one OPM_DYNPROP_OBJECT_ENTRY_AUTO
  23. // macro for each class mapping, i.e.:
  24. //
  25. // OPM_DYNPROP_OBJECT_ENTRY_AUTO(CMyDynProp, AcDbLine)
  26. // OPM_DYNPROP_OBJECT_ENTRY_AUTO(CMyDynProp, AcDbCircle)
  27. //
  28. // To instanciate zero selection mode properties attach properties to AcDbDatabase,
  29. // I.e.:
  30. //
  31. // OPM_DYNPROP_OBJECT_ENTRY_AUTO(CMyDynProp, AcDbDatabase)
  32. //
  33. // Use the OPM_DYNPROP_COMMAND_ENTRY_AUTO macro to map properties to a command, I.e.:
  34. //
  35. // OPM_DYNPROP_COMMAND_ENTRY_AUTO(CMyDynProp, MyCommandName)
  36. //
  37. // For support of the old IDynamicProperty, use the OPM_DYNPROP_OBJECT_LEGACY1ENTRY_AUTO
  38. // macro, i.e.:
  39. //
  40. // OPM_DYNPROP_OBJECT_LEGACY1ENTRY_AUTO (CMyLegacyDynProp, AcDbLine)
  41. // OPM_DYNPROP_OBJECT_LEGACY1ENTRY_AUTO (CMyLegacyDynProp, AcDbCircle)
  42. //
  43. // These macros should appear in the dynamic property class header file
  44. // after the class declaration.
  45. //-----------------------------------------------------------------------------
  46. #pragma once
  47. //-----------------------------------------------------------------------------
  48. struct _OPM_DYNPROP_ENTRY {
  49. _ATL_CREATORFUNC *pfnCreateInstance ;
  50. const ACHAR *strCmd ;
  51. AcRxClass *pClass ;
  52. IDynamicProperty *pProp ;
  53. const CLSID* pclsid ;
  54. IPropertySource *pPropSrc ;
  55. } ;
  56. #pragma section("OPM_DYNPROP$__a", read, shared)
  57. #pragma section("OPM_DYNPROP$__z", read, shared)
  58. #pragma section("OPM_DYNPROP$__m", read, shared)
  59. extern "C" {
  60. __declspec(selectany) __declspec(allocate("OPM_DYNPROP$__a")) _OPM_DYNPROP_ENTRY* __pOpmObjMapEntryFirst =NULL ;
  61. __declspec(selectany) __declspec(allocate("OPM_DYNPROP$__z")) _OPM_DYNPROP_ENTRY* __pOpmObjMapEntryLast =NULL ;
  62. }
  63. #if defined(_WIN64) || defined(_AC64)
  64. #define OPM_DYNPROP_OBJECT_ENTRY_PRAGMA(classname, rxclass) __pragma(comment(linker, "/include:__pOpmObjMap_" #rxclass #classname)) ;
  65. #else
  66. #define OPM_DYNPROP_OBJECT_ENTRY_PRAGMA(classname, rxclass) __pragma(comment(linker, "/include:___pOpmObjMap_" #rxclass #classname)) ;
  67. #endif
  68. #define OPM_DYNPROP_OBJECT_ENTRY_MAKE(classname, rxclass, clsid) \
  69. __declspec(selectany) _OPM_DYNPROP_ENTRY __OpmObjMap_##rxclass##classname = {classname::_CreatorClass::CreateInstance, NULL, rxclass::desc (), NULL, &clsid, NULL} ; \
  70. extern "C" __declspec(allocate("OPM_DYNPROP$__m")) __declspec(selectany) _OPM_DYNPROP_ENTRY* const __pOpmObjMap_##rxclass##classname = &__OpmObjMap_##rxclass##classname ; \
  71. OPM_DYNPROP_OBJECT_ENTRY_PRAGMA(classname, rxclass)
  72. #define OPM_DYNPROP_OBJECT_ENTRY_AUTO(classname, rxclass) \
  73. OPM_DYNPROP_OBJECT_ENTRY_MAKE(classname, rxclass, __uuidof (IDynamicProperty2))
  74. #define OPM_DYNPROP_OBJECT_LEGACY1ENTRY_AUTO(classname, rxclass) \
  75. OPM_DYNPROP_OBJECT_ENTRY_MAKE(classname, rxclass, __uuidof (IDynamicProperty))
  76. #if defined(_WIN64) || defined(_AC64)
  77. #define OPM_DYNPROP_COMMAND_ENTRY_PRAGMA(classname, cmdname) __pragma(comment(linker, "/include:__pOpmObjMap_" #cmdname #classname)) ;
  78. #else
  79. #define OPM_DYNPROP_COMMAND_ENTRY_PRAGMA(classname, cmdname) __pragma(comment(linker, "/include:___pOpmObjMap_" #cmdname #classname)) ;
  80. #endif
  81. #define OPM_DYNPROP_COMMAND_ENTRY_MAKE(classname, cmdname, clsid) \
  82. __declspec(selectany) _OPM_DYNPROP_ENTRY __OpmObjMap_##cmdname##classname = {classname::_CreatorClass::CreateInstance, _RXST(#cmdname), NULL, NULL, &clsid} ; \
  83. extern "C" __declspec(allocate("OPM_DYNPROP$__m")) __declspec(selectany) _OPM_DYNPROP_ENTRY* const __pOpmObjMap_##cmdname##classname = &__OpmObjMap_##cmdname##classname ; \
  84. OPM_DYNPROP_COMMAND_ENTRY_PRAGMA(classname, cmdname)
  85. #define OPM_DYNPROP_COMMAND_ENTRY_AUTO(classname, cmdname) \
  86. OPM_DYNPROP_COMMAND_ENTRY_MAKE(classname, cmdname, __uuidof (IDynamicProperty2))
  87. #define OPM_DYNPROP_COMMAND_LEGACY1ENTRY_AUTO(classname, cmdname) \
  88. OPM_DYNPROP_COMMAND_ENTRY_MAKE(classname, cmdname, __uuidof (IDynamicProperty))
  89. #define OPM_DYNPROP_PERINSTANCE_ENTRY_AUTO(classname, rxclass) \
  90. OPM_DYNPROP_OBJECT_ENTRY_MAKE(classname, rxclass, __uuidof (IPropertySource))
  91. //-----------------------------------------------------------------------------
  92. class AcRxDynPropManager {
  93. public:
  94. AcRxDynPropManager () {
  95. _OPM_DYNPROP_ENTRY **m_ppOpmObjMapEntryFirst =&__pOpmObjMapEntryFirst + 1 ;
  96. _OPM_DYNPROP_ENTRY **m_ppOpmObjMapEntryLast =&__pOpmObjMapEntryLast ;
  97. for ( _OPM_DYNPROP_ENTRY **ppEntry =m_ppOpmObjMapEntryFirst ; ppEntry < m_ppOpmObjMapEntryLast ; ppEntry++ ) {
  98. if ( *ppEntry != NULL ) {
  99. if ( *((*ppEntry)->pclsid) == __uuidof (IDynamicProperty2) || *((*ppEntry)->pclsid) == __uuidof (IDynamicProperty) ) {
  100. //- Dynamic properties via the Property Manager
  101. CComPtr<IPropertyManager> pPropMan ;
  102. ATLASSERT( !((*ppEntry)->pClass && (*ppEntry)->strCmd) ) ;
  103. ATLASSERT( (*ppEntry)->pClass || (*ppEntry)->strCmd ) ;
  104. if ( (*ppEntry)->pClass != NULL && (*ppEntry)->pClass == AcDbDatabase::desc () ) {
  105. //- Zero Selection property
  106. if ( (pPropMan =GET_OPMEXTENSION_CREATE_PROTOCOL ()->CreateOPMObjectProtocol (NULL, 2)->GetPropertyManager ()) == NULL )
  107. _com_issue_error (E_FAIL) ;
  108. } else if ( (*ppEntry)->pClass != NULL ) {
  109. //- Class property
  110. if ( (pPropMan =GET_OPMPROPERTY_MANAGER ((*ppEntry)->pClass)) == NULL )
  111. _com_issue_error (E_FAIL) ;
  112. } else {
  113. //- Command property
  114. if ( GET_OPMEXTENSION_CREATE_PROTOCOL ()->GetOPMManager ((*ppEntry)->strCmd, &pPropMan) == FALSE ) {
  115. if ( (pPropMan =GET_OPM_COMMAND_PROPERTY_MANAGER ((*ppEntry)->strCmd)) == NULL )
  116. _com_issue_error (E_FAIL) ;
  117. }
  118. OPMPropertyExtension *pOPMExt =GET_OPMEXTENSION_CREATE_PROTOCOL ()->CreateOPMCommandProtocol ((*ppEntry)->strCmd) ;
  119. pOPMExt->SetPropertyManager (pPropMan) ;
  120. }
  121. _com_util::CheckError ((*ppEntry)->pfnCreateInstance (NULL, *((*ppEntry)->pclsid), (void **)&((*ppEntry)->pProp))) ;
  122. (*ppEntry)->pProp->AddRef () ;
  123. _com_util::CheckError (pPropMan->AddProperty ((*ppEntry)->pProp)) ;
  124. } else if ( *((*ppEntry)->pclsid) == __uuidof (IPropertySource) ) {
  125. //- Per Instance Property
  126. ATLASSERT( (*ppEntry)->pClass ) ;
  127. _com_util::CheckError ((*ppEntry)->pfnCreateInstance (NULL, *((*ppEntry)->pclsid), (void **)&((*ppEntry)->pPropSrc))) ;
  128. CComBSTR propName ;
  129. (*ppEntry)->pPropSrc->get_Name (&propName) ;
  130. IPropertySource *pPropSrc =GET_OPM_PERINSTANCE_PROPERTY_SOURCES ()->GetPropertySourceAt (&propName) ;
  131. if ( pPropSrc == NULL ) {
  132. if ( GET_OPM_PERINSTANCE_PROPERTY_SOURCES ()->SetPropertySourceAt (&propName, (*ppEntry)->pPropSrc) == false )
  133. _com_issue_error (E_FAIL) ;
  134. } else {
  135. (*ppEntry)->pPropSrc->Release () ;
  136. (*ppEntry)->pPropSrc =pPropSrc ;
  137. pPropSrc =NULL ; //- Don't call release
  138. }
  139. if( GET_OPM_PERINSTANCE_EXTENSION_PROTOCOL ((*ppEntry)->pClass)->AddObjectPropertySourceName (&propName) == false )
  140. _com_issue_error (E_FAIL) ;
  141. }
  142. }
  143. }
  144. }
  145. virtual ~AcRxDynPropManager () {
  146. _OPM_DYNPROP_ENTRY **m_ppOpmObjMapEntryFirst =&__pOpmObjMapEntryFirst + 1 ;
  147. _OPM_DYNPROP_ENTRY **m_ppOpmObjMapEntryLast =&__pOpmObjMapEntryLast ;
  148. for ( _OPM_DYNPROP_ENTRY **ppEntry =m_ppOpmObjMapEntryFirst ; ppEntry < m_ppOpmObjMapEntryLast ; ppEntry++ ) {
  149. if ( *ppEntry != NULL ) {
  150. if ( *((*ppEntry)->pclsid) == __uuidof (IDynamicProperty2) || *((*ppEntry)->pclsid) == __uuidof (IDynamicProperty) ) {
  151. //- Dynamic properties via the Property Manager
  152. ATLASSERT( !((*ppEntry)->pClass && (*ppEntry)->strCmd) ) ;
  153. ATLASSERT( (*ppEntry)->pClass || (*ppEntry)->strCmd ) ;
  154. CComPtr<IPropertyManager> pPropMan ;
  155. if ( (*ppEntry)->pClass != NULL && (*ppEntry)->pClass == AcDbDatabase::desc () ) {
  156. //- Zero Selection property
  157. if ( (pPropMan =GET_OPMEXTENSION_CREATE_PROTOCOL ()->CreateOPMObjectProtocol (NULL, 2)->GetPropertyManager ()) == NULL )
  158. _com_issue_error (E_FAIL) ;
  159. } else if ( (*ppEntry)->pClass != NULL ) {
  160. //- Class property
  161. if ( (pPropMan =GET_OPMPROPERTY_MANAGER ((*ppEntry)->pClass)) == NULL )
  162. _com_issue_error (E_FAIL) ;
  163. } else {
  164. //- Command property
  165. if ( GET_OPMEXTENSION_CREATE_PROTOCOL ()->GetOPMManager ((*ppEntry)->strCmd, &pPropMan) == FALSE ) {
  166. if ( (pPropMan =GET_OPM_COMMAND_PROPERTY_MANAGER ((*ppEntry)->strCmd)) == NULL )
  167. _com_issue_error (E_FAIL) ;
  168. }
  169. }
  170. if ( (*ppEntry)->pProp != NULL ) {
  171. _com_util::CheckError (pPropMan->RemoveProperty ((*ppEntry)->pProp)) ;
  172. (*ppEntry)->pProp->Release () ;
  173. }
  174. } else if ( *((*ppEntry)->pclsid) == __uuidof (IPropertySource) ) {
  175. //- Per Instance Property
  176. ATLASSERT( (*ppEntry)->pClass ) ;
  177. CComBSTR propName ;
  178. (*ppEntry)->pPropSrc->get_Name (&propName) ;
  179. if ( GET_OPM_PERINSTANCE_EXTENSION_PROTOCOL ((*ppEntry)->pClass)->RemoveObjectPropertySourceName (&propName) == false )
  180. _com_issue_error (E_FAIL) ;
  181. if ( (*ppEntry)->pPropSrc->Release () <= 1 ) {
  182. if ( GET_OPM_PERINSTANCE_PROPERTY_SOURCES()->RemovePropertySourceAt (&propName) == false )
  183. _com_issue_error (E_FAIL) ;
  184. }
  185. }
  186. }
  187. }
  188. }
  189. } ;