AcadToolImpl.h 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401
  1. //
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Copyright 2015 Autodesk, Inc. All rights reserved.
  5. //
  6. // Use of this software is subject to the terms of the Autodesk license
  7. // agreement provided at the time of installation or download, or which
  8. // otherwise accompanies this software in either electronic or hard copy form.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. // ******************************************************************************************************************************************
  12. /*
  13. The AcadToolImpl class handles general AutoCAD Tool functionality by parsing the tool's type information at
  14. runtime to discover details about the custom interface. This information is used to persist the tool via XML (ATC files),
  15. support the default property inspector for the tool properties, handle drag/drop notifications, and support
  16. for Color and Layer property controls . At the same time, the developer is free to override any
  17. functionality handled by this class by implementing the necessary virtual functions.
  18. Included in the class are helper functions to generate Catalogs, Palettes, Tool instances and Command Tools (see
  19. notes below for details).
  20. Directions for use:
  21. 1 - Generate a custom COM interface (ATL Simple Object) with the ATL Wizard.
  22. 2 - Create a bitmap icon resource in this module for iconic depiction of your tool.
  23. The standard size for tool icons are 65x65. Create a string-type resource ID for the resource ID. e.g. "IDB_MYTOOLIMAGE"
  24. set in the Visual Studio properties window for the image.
  25. 3 - Derive your class from AcadToolImpl, listing it just below CComCoClass in the declaration.
  26. Add the template arguments for the AcadToolImpl class:
  27. <Child Class Name, Tool Interface Class, Tool CLSID, Tool's Name, Tool's Image resource name>
  28. Note: Because they are template LPCWSTR arguments, the Tools Name and image name must be declared globally
  29. (but not statically) as WCHARs. The best place to do this is in the Tool's .cpp file, declaring them as extern in
  30. the tools header, to avoid LNK2005.
  31. 4 - Remove the derivation for CComObjectRootEx and IDispatchImpl for this CoClass, leaving only CComCoClass and
  32. AcadToolImpl.
  33. When steps 3 and 4 are done it should look like this (fictitious arguments):
  34. #include "AcadToolImpl.h"
  35. extern WCHAR szEmployeeName[MAX_PATH]; // Declared in the tools .cpp file
  36. extern WCHAR szEmployeeImage[MAX_PATH];// - -
  37. class ATL_NO_VTABLE CEmployeeTool :
  38. public CComCoClass<CEmployeeTool, &CLSID_EmployeeTool>,
  39. public AcadToolImpl<CEmployeeTool,IEmployeeTool, &CLSID_EmployeeTool,szEmployeeName,szEmployeeImage>
  40. {
  41. 5 - Remove the COM_MAP and all the COM_INTERFACE_ENTRY entries from the CoClass header.
  42. 6 - Add the properties you want your tool to represent to the COM object via the ATL Wizard to the CoClass and IDL.
  43. Additionally, the AcadToolImpl class automatically supports the Color and Layer Combo Box ActiveX controls to include
  44. these features in your tools, if you chose. To support either of them, add them as members to your interface as the
  45. following entries in your IDL:
  46. Color is a type VARIANT property
  47. Layer is a BSTR property
  48. Note: They must have the property names 'Color' and 'Layer'. The methods get/put_Color() and get/put_LayerColor()
  49. are implemented in this base class so you can remove the CoClass declaration and implementation for these
  50. members, or you can call the base-versions from your overrides. For each control you want, you will need to add an
  51. entry to the prop-display MAP, outlined below.
  52. If you chose not to support these controls, just leave them out of your interface; no other work is needed.
  53. 7 - Add specific member variables, excluding 'Color' and 'Layer' (which are represented in this class) to represent these
  54. properties in the CoClass. Implement the Get and Put methods to refer to these members. For your reference, 'Color' and 'Layer'
  55. are declared in this class as:
  56. m_Color - AcCmColor
  57. m_szLayer - WCHAR[512]
  58. 8 - Add the following MAP to the class definition. These will allow you to add definitions for the AutoCAD-specific
  59. ComboBoxes such as Color Layer and Linetype. The BEGIN and END are required only:
  60. BEGIN_PERPROPDISPLAY_MAP2()
  61. END_PERPROPDISPLAY_MAP2()
  62. 9 - Add the following MAP to the class definition. This map will allow you to
  63. define global properties which can be modified in a Flyout Tool which will be applied
  64. to all the custom tool instances in the package the Flyout Tool represents.
  65. BEGIN_FLYOUT_SPECIFIC_MAP()
  66. END_FLYOUT_SPECIFIC_MAP()
  67. For each property you want to set as a global Flyout property, add the following
  68. FLYOUT_ENTRY for the DISPID of the property.
  69. FLYOUT_ENTRY(<DISPID>)
  70. If you want to support any of the property controls available (see Step 6), add entries to the MAP with the same format as
  71. outlined in 'Per-Property Customization in the Property Inspector' within the 'PropertyPalette API' section
  72. of the ObjectARX online help.
  73. Example of support for Color, Layer and Linetype Combo Box controls in the Tool:
  74. BEGIN_PERPROPDISPLAY_MAP2()
  75. PROP_DISP_ENTRY2(5, "AcPEXCtl.AcPePropertyEditorColor.16", NULL, NULL, NULL, NULL, 0x000000ff, FALSE, 1, 0)
  76. PROP_DISP_ENTRY2(6, "AcPEXCtl.AcPePropertyEditorLayer.16", NULL, NULL, NULL, NULL, 0x000000ff, FALSE, 1, 0)
  77. END_PERPROPDISPLAY_MAP2()
  78. Note: The first argument in this map is the DISPID for the corresponding control
  79. 10 - Implement GetResourceInstance(). This can be placed publicly in the child class' header file.
  80. virtual HINSTANCE GetResourceInstance()
  81. {
  82. return _AtlBaseModule.GetResourceInstance();
  83. }
  84. 11 - include actc_i.c to the StdAfx.cpp file.
  85. #include "actc_i.c"
  86. 11 - You can chose to override any virtual IAcadTool or IAcadStockTool method in the child class if needed.
  87. Additional virtual functions are defined in the base class to handle execution, drag/drop and additional persistence support
  88. for your tools. The are:
  89. executeCallback() - Called when the tool is run
  90. dropCallback() - Called when a tool is created from dropping an entity on the palette
  91. LoadPropertyValue() - Called to handle reading all or extra property data from XML
  92. SavePropertyValue() - Called to handle writing all or extra property data to XML
  93. executeCallback() will be called when the user runs the tool, but after the document is locked and a reentrant
  94. mutex is set. This is where you define what the tool does. A typical example would be to instantiate a Prompt
  95. class (see the AsdkPromptBase class for details).
  96. dropCallback() will be called when entities are dropped on the palette from a block table record. An AcDbEntity
  97. pointer is passed representing the dropped entity, which should be used to populate the properties of the newly
  98. created tool (which will be the *this* object since it's an overriden member).
  99. Load/SavePropertyValue() is called when the framework is reading or writing (respectively) the
  100. properties themselves to the ATC (XML) file for the tool. Override these members if you need to persist extra
  101. data along with the property values, or if you want to be solely responsible for how the tool is persisted.
  102. An example is with a boolean representing the Unspecified state (IPropertyUnspecified) for a special ComboBox
  103. such as Color or Layer. An index representing which control (DISPID) is being written is passed along with
  104. an XML DOM node pointer to read/write with. Remember to call the base-class version of this method if you want
  105. the base class to handle standard persistence of the property.
  106. 10 - Be certain to override the New function to handle instantiation of your member variables. This should be done
  107. here rather than within the constructor, as the framework handles creation of your tool itself.
  108. Notes:
  109. 1) This implementation class will automatically support properties of all VARIANT types supported in the
  110. property inspector. While the Color property is marshalled across as a VT_DISPATCH, this sample
  111. persists the color as a LONG since XML can't represent interface pointers. This is handled in this class' version of
  112. Load/SavePropertyValue.
  113. If you define properties in your tool interface of less frequently used types (e.g. a GUID), you may
  114. need to override the Load/SavePropertyValue() method to convert to and from string to support them yourself.
  115. So, if IXMLDOMAttributePtr::get_value(the method used internally to persist your properties) can't persist the types, you
  116. will need to convert them to string or other type and persist them manually either with the
  117. Load/SavePropertyValue()or directly overriding Load() and Save() from the base class.
  118. See IXMLDOMAttributePtr::get_value and set_value for details about what VARIANTS types can be persisted in XML with the DOM.
  119. 2) Included as members in this class are functions to create ATC files based on your new tool. The are:
  120. CreateStockToolATC() Creates the stock tool catalog, and a general tool catalog.
  121. CreatePaletteATC() Creates a Palette, and adds it to the catalog passed in.
  122. CreateToolATC() Creates an instance of your tool, placing it in the Palette passed in
  123. CreateCommandToolATC() Creates a command tool which executes the passed macro string.
  124. CreateFlyoutToolATC() Creates a Flyout Tool, which can contain packages of other tools
  125. CreateShapeCatalogATC() Creates a shape package which can be represented by a Flyout Tool.
  126. A typical usage of these functions might be:
  127. CComObject<CEmployeeTool> tool;
  128. AcTcCatalog *pCatalog=tool.CreateStockToolATC(L"EmployeeCatalog");
  129. AcTcPalette *pPalette=tool.CreatePaletteATC(pCatalog,L"EmployeePalette");
  130. tool.CreateToolATC(pPalette);
  131. AcTcGetManager()->LoadCatalogs(); // Refresh the Palette in the AutoCAD UI.
  132. The CreateToolATC and CreateFlyoutToolATC have optional arguments to override
  133. the tool's name and image for each instance. If not used, the values passed in as the
  134. template arguments in the class declaration will be used.
  135. Generally, these functions would only be used to create the catalog ATC files, but distribution of these files to end users would be
  136. handled by an installer.
  137. */
  138. #pragma once
  139. #include "AcImportXml.h"
  140. using namespace MSXML;
  141. #include "AcPExCtl.h"
  142. #include "opmdialog.h"
  143. #include "Ac64BitHelpers.h"
  144. // This is to avoid including AcTcUi.h, which would require MFC...TODO, we need to remove the CTypedPtrArray dependency to fully
  145. // remove the dependency on MFC here. This should be done with an overloaded global function in AcTcUi...
  146. typedef CTypedPtrArray<CPtrArray, AcTcCatalogItem*> AcTcCatalogItemArray;
  147. BOOL AcTcUiFilterShapesDialog(AcTcCatalogItem* pPackage,
  148. AcTcCatalogItemArray* pActiveShapes,
  149. AcTcTool*& pCurrentShape,
  150. CWnd* pParentWnd);
  151. // Ok. Here is the explanation of these macros. Since we need to implement the IPerPropertyDisplayImpl
  152. // helper interface class here, we need to declare a static function which returns the static map defined
  153. // by their macros. However, since the user will declare the actual MAP in the child class, we must forward
  154. // this call to the child using the template argument for the child. Take a look at GetPerPropDisplayArray in
  155. // this class.
  156. struct PER_PROP_DISP_ENTRY2
  157. {
  158. DISPID m_dispid;
  159. LPCWSTR m_ProgID;
  160. LPCWSTR m_lpLeftIconRes;
  161. UINT m_nLeftIconType;
  162. LPCWSTR m_lpEllipsisBmpRes;
  163. UINT m_nEllipsisBmpType;
  164. COLORREF m_TextColor;
  165. bool m_bFullView;
  166. DWORD m_dwIntegralHeight;
  167. long m_nWeight;
  168. };
  169. // These are basically equivalent to those defined in IPerPropertyDisplayImpl
  170. // use this #define for the textcolor item in PROP_DISP_ENTRY in order to use the
  171. // default UI label color in the UI; any other value for textcolor is treated
  172. // as a COLORREF
  173. #ifndef TEXTCOLOR_DEFAULT
  174. #define TEXTCOLOR_DEFAULT 0x80000008
  175. #endif // TEXTCOLOR_DEFAULT
  176. #define BEGIN_PERPROPDISPLAY_MAP2() \
  177. static PER_PROP_DISP_ENTRY2* GetPerPropDisplayArray2() \
  178. { \
  179. static PER_PROP_DISP_ENTRY2 pPerPropDisplayArray[] = \
  180. {
  181. #define PROP_DISP_ENTRY2(dispid, progid, lpLeftIconRes, lpLeftIconType, \
  182. lpEllipsisBmpRes, lpEllipsisBmpType, textcolor, \
  183. bFullView, dwIntegralHeight, nWeight) \
  184. {dispid, progid, lpLeftIconRes, lpLeftIconType, lpEllipsisBmpRes, \
  185. lpEllipsisBmpType, textcolor, bFullView, \
  186. dwIntegralHeight, nWeight}, \
  187. #define END_PERPROPDISPLAY_MAP2() \
  188. {-1, NULL, NULL, PICTYPE_UNINITIALIZED, NULL, PICTYPE_UNINITIALIZED, TEXTCOLOR_DEFAULT, false, -1, -1}\
  189. }; \
  190. return pPerPropDisplayArray; \
  191. }
  192. struct PER_FLYOUT_ENTRY
  193. {
  194. DISPID dispid;
  195. };
  196. #define BEGIN_FLYOUT_SPECIFIC_MAP()\
  197. static PER_FLYOUT_ENTRY* GetFlyoutMap()\
  198. {\
  199. static PER_FLYOUT_ENTRY pFlyoutEntry[]=\
  200. {
  201. #define FLYOUT_ENTRY(dispid)\
  202. {dispid},
  203. #define END_FLYOUT_SPECIFIC_MAP()\
  204. {-1}\
  205. };\
  206. return pFlyoutEntry;\
  207. }
  208. static void *pAcadToolImpl=NULL;// Used to refer to the instance that spawns the separate IOPMPropertyDialog instance
  209. template <class TT,class T,const CLSID* pclsid,LPCWSTR szToolName,LPCWSTR szToolImage,const IID* piid = &__uuidof(T),const GUID* plibid = &CAtlModule::m_libid>
  210. class ATL_NO_VTABLE AcadToolImpl :
  211. public CComObjectRootEx<CComSingleThreadModel>,
  212. public IDispatchImpl<T, piid, plibid, /*wMajor =*/ 1, /*wMinor =*/ 0>,
  213. public IAcadTool,
  214. public IAcadTool2,
  215. public IAcadStockTool,
  216. public IDropTarget,
  217. public IPropertyUnspecified,
  218. public IPerPropertyDisplayImpl<AcadToolImpl<TT,T,pclsid,szToolName,szToolImage,piid,plibid> >,
  219. public IOPMPropertyExtension,
  220. public IAcadToolContextMenu,
  221. public IPerPropertyBrowsing,
  222. public IOPMPropertyDialog,
  223. public IAcadToolFlyoutShape
  224. {
  225. public:
  226. AcadToolImpl()
  227. {
  228. wcscpy_s(m_szLayer,L"0");
  229. wcscpy_s(m_FlyoutTools,L"\0");
  230. dispColor=dispLayer=0;
  231. m_bColorUnspecified=m_bLayerUnspecified=TRUE;
  232. m_hWndEditWindow=NULL;
  233. m_pToolProp=NULL;
  234. mcfAutoCAD = (CLIPFORMAT)::RegisterClipboardFormat(acedClipFormatName());
  235. }
  236. ~AcadToolImpl()
  237. {
  238. m_ToolMap.setLogicalLength(0);
  239. }
  240. static PER_PROP_DISP_ENTRY* GetPerPropDisplayArray()
  241. {
  242. return (PER_PROP_DISP_ENTRY*)TT::GetPerPropDisplayArray2();
  243. }
  244. AcCmColor m_Color;
  245. WCHAR m_szLayer[512]; // Represents a Layer combo box in the tool property inspector
  246. DISPID dispColor,dispLayer,dispFlyout;
  247. HWND m_hWndEditWindow;
  248. CComPtr<IAcadToolProperties> m_pToolProp;
  249. bool m_bFlyout; // Is this tool a flyout tool? (not persisted through IDispatch)
  250. GUID m_FlyoutPackageId;// If so, what is the ID of the package (also not persisted through IDispatch)
  251. GUID m_CurrentShapeId;// And what is the ID of the current shape within this package.
  252. WCHAR m_FlyoutTools[64];
  253. BEGIN_COM_MAP(AcadToolImpl)
  254. COM_INTERFACE_ENTRY(T)
  255. COM_INTERFACE_ENTRY(IDispatch)
  256. COM_INTERFACE_ENTRY(IAcadTool)
  257. COM_INTERFACE_ENTRY(IAcadStockTool)
  258. COM_INTERFACE_ENTRY(IDropTarget)
  259. COM_INTERFACE_ENTRY(IPropertyUnspecified)
  260. COM_INTERFACE_ENTRY(IPerPropertyDisplay)
  261. COM_INTERFACE_ENTRY(IOPMPropertyExtension)
  262. COM_INTERFACE_ENTRY(IAcadToolContextMenu)
  263. COM_INTERFACE_ENTRY(IPerPropertyBrowsing)
  264. COM_INTERFACE_ENTRY(IOPMPropertyDialog)
  265. COM_INTERFACE_ENTRY(IAcadToolFlyoutShape)
  266. END_COM_MAP()
  267. protected:
  268. // Default members:
  269. HWND m_hPreviewWnd;
  270. BOOL m_bColorUnspecified,m_bLayerUnspecified;
  271. struct TOOL_MAP_ENTRY
  272. {
  273. WCHAR szDesc[512];
  274. DISPID dispId;
  275. };
  276. AcArray<TOOL_MAP_ENTRY> m_ToolMap;
  277. CLIPFORMAT mcfAutoCAD;
  278. public:
  279. // ************************************************************************************
  280. // IAcadStockTool member
  281. public:
  282. STDMETHOD(CreateTool) (/*[out, retval]*/ IUnknown** ppTool)
  283. {
  284. // Return the interface pointer for the IAcadTool (which for us is this object).
  285. HRESULT hr=GetPropertyTypeInfo();
  286. return _InternalQueryInterface(IID_IAcadTool, (void**) ppTool);
  287. }
  288. // ************************************************************************************
  289. // IAcadTool members
  290. public:
  291. STDMETHOD(get_EditMode) (/*[out, retval]*/ long* pVal)
  292. {
  293. // Default Edit Mode.
  294. *pVal = kEditDefault;
  295. return S_OK;
  296. }
  297. STDMETHOD(GetStockTool) (/*[out, retval]*/ IUnknown** ppToolClass)
  298. {
  299. // Get the Stock Tool for this Tool (which for us is this object).
  300. return _InternalQueryInterface(IID_IAcadStockTool, (void**) ppToolClass);
  301. }
  302. STDMETHOD(Load) (/*[in]*/ IUnknown* pXmlElement)
  303. {
  304. CComQIPtr<MSXML::IXMLDOMNode> pEntityNode=pXmlElement;
  305. if (pEntityNode == NULL)
  306. return E_INVALIDARG;
  307. MSXML::IXMLDOMNodePtr pAttributeNode,pChild;
  308. if(GetChildNode(pEntityNode, L"Tool",&pAttributeNode))
  309. // Load the Tool members, via the COM interface.
  310. for(int i=0;i<m_ToolMap.length();i++)
  311. if(GetChildNode(pAttributeNode, m_ToolMap.at(i).szDesc,&pChild))
  312. LoadPropertyValue(pChild,i+1);
  313. return S_OK;
  314. }
  315. STDMETHOD(LoadFromFlyout)(IUnknown* pXmlElement)
  316. {
  317. // This is equivalent to load, but we are limiting the properties we load here
  318. // based upon what the design of the tool specifies as global properties from a flyout tool with FLYOUT_ENTRY entries.
  319. CComQIPtr<MSXML::IXMLDOMNode> pEntityNode=pXmlElement;
  320. if (pEntityNode == NULL)
  321. return E_INVALIDARG;
  322. MSXML::IXMLDOMNodePtr pAttributeNode,pChild;
  323. PER_FLYOUT_ENTRY *pFlyoutMap=TT::GetFlyoutMap();
  324. if(GetChildNode(pEntityNode, L"Tool",&pAttributeNode))
  325. // Load the Tool members, via the COM interface.
  326. for(int i=0;i<m_ToolMap.length();i++)
  327. if(GetChildNode(pAttributeNode, m_ToolMap.at(i).szDesc,&pChild))
  328. {
  329. int ii=0;
  330. bool bGlobalProp=false;
  331. while(pFlyoutMap[ii].dispid!=-1)
  332. {
  333. if(pFlyoutMap[ii].dispid==i+1)
  334. {
  335. bGlobalProp=true;
  336. break;
  337. }
  338. ii++;
  339. }
  340. if(bGlobalProp)
  341. LoadPropertyValue(pChild,i+1);
  342. }
  343. return S_OK;
  344. }
  345. STDMETHOD(Save) (/*[in]*/ IUnknown* pXmlElement)
  346. {
  347. if (pXmlElement == NULL)
  348. return E_INVALIDARG;
  349. MSXML::IXMLDOMNodePtr pEntityNode,pChildNode,pToolNode;
  350. CComQIPtr<MSXML::IXMLDOMNode> pParentNode=pXmlElement;
  351. // Add child nodes within this node for us to populate.
  352. if(!GetChildNode(pParentNode,L"Tool",&pEntityNode))
  353. AddChildNode(pParentNode, L"Tool", MSXML::NODE_ELEMENT, &pEntityNode);
  354. // Save the Tools members, via the COM interface.
  355. for(int i=0;i<m_ToolMap.length();i++)
  356. {
  357. if(!GetChildNode(pEntityNode, m_ToolMap.at(i).szDesc,&pChildNode))
  358. AddChildNode(pEntityNode,m_ToolMap.at(i).szDesc,MSXML::NODE_ELEMENT,&pChildNode);
  359. SavePropertyValue(pChildNode,i+1);
  360. }
  361. return S_OK;
  362. }
  363. STDMETHOD(executeCallback)() {return E_NOTIMPL;}
  364. STDMETHOD(dropCallback)(AcDbEntity *pEntity){return E_NOTIMPL;}
  365. STDMETHOD(Execute) (/*[in]*/ LONG_PTR lFlag, /*[in]*/ DWORD_PTR /*HWND*/ hWnd, /*[in]*/ DWORD point, /*[in]*/ DWORD dwKeyState)
  366. {
  367. // This method is called when the user uses this tool. Generally, this should ultimately place
  368. // the content the tool represents into the drawing. This can be done by directly placing the
  369. // object in the block table record, or using the Running object command object (see the AsdkPromptBase class)
  370. // to jig the object.
  371. // Prevent multiple entries into this tool.
  372. static bool bExecuteMutex=false;
  373. if(bExecuteMutex)
  374. return S_OK;
  375. bExecuteMutex=true;
  376. // Set the focus to AutoCAD
  377. ::SetFocus(adsw_acadDocWnd());
  378. // Lock the document
  379. AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
  380. if(!pDb)
  381. return E_FAIL;
  382. AcAxDocLock docLock( pDb, AcAxDocLock::kNormal );
  383. if(docLock.lockStatus() != Acad::eOk){
  384. return E_FAIL;
  385. }
  386. // If this tool is run within a shape package, we will want to apply the global properties
  387. // from the flyout (parent) tool here. (This can't be done at load time :-((().
  388. AcTcTool *pFlyoutTool=NULL;
  389. if(GetFlyoutTool(pFlyoutTool))
  390. {
  391. // Apply properties from the parent tool here...
  392. CComPtr<IUnknown> pUnk;
  393. BOOL bRet = pFlyoutTool->GetToolData(&pUnk);
  394. LoadFromFlyout(pUnk);
  395. }
  396. wcscpy_s(m_FlyoutTools,L"");//Reset this each time the tool is run.
  397. executeCallback(); // Allow the Child class to handle execution directly.
  398. bExecuteMutex=false;
  399. return S_OK;
  400. }
  401. BOOL GetFlyoutTool(AcTcTool*& pFlyoutTool)
  402. {
  403. pFlyoutTool = NULL;
  404. if(!wcscmp(m_FlyoutTools,L"")){
  405. return FALSE;
  406. }
  407. GUID flyoutToolId;
  408. BOOL bRet = FALSE;
  409. // We always return first flyout tool. If there are multiple flyout
  410. // tools assert as a warning so that the caller will know.
  411. bRet = GuidFromString(m_FlyoutTools, flyoutToolId);
  412. if (!bRet)
  413. // Invalid guid
  414. return FALSE;
  415. // Get the tool object from the manager
  416. AcTcManager* pMgr = AcTcGetManager();
  417. pFlyoutTool = (AcTcTool*) pMgr->FindItem(flyoutToolId);
  418. if (pFlyoutTool == NULL)
  419. return FALSE;
  420. if (pFlyoutTool->GetType() != kItemTool)
  421. return FALSE;
  422. // We need to enforce the fact that flyouts that allow the shapes to snarf into them
  423. // for their FLYOUT_SPECIFIC properties be the same type of tool...
  424. CComPtr<T> pThisTool;
  425. if(!SUCCEEDED(QueryInterface(*piid,(void**)&pThisTool)))
  426. return E_FAIL;
  427. return TRUE;
  428. }
  429. STDMETHOD(GetData) (/*[in]*/ VARIANT *pObjUnkArray, /*[in]*/ VARIANT *pDynUnkArray)
  430. {
  431. // The framework is going to edit this tool. It needs to know which properties will be edited.
  432. CComPtr<IUnknown> pUnk;
  433. _InternalQueryInterface(IID_IUnknown, (void**) &pUnk);
  434. // GetUnknownArrays is a helper function which populates the args passed in here with arrays
  435. // of our static interface, and a NULL array for the dynamic properties, which this class doesn't define.
  436. GetUnknownArrays(1, &pUnk, pObjUnkArray, pDynUnkArray);
  437. return S_OK;
  438. }
  439. // If you want custom editing of your tool, handle these Edit methods (and return kEditCustom from get_EditMode).
  440. // Otherwise the framework will handle it for you (default for this example).
  441. STDMETHOD(BeginEdit) ()
  442. {
  443. return S_OK;
  444. }
  445. STDMETHOD (Edit) (/*[in]*/ IUnknown* pProp,/*[in]*/ LONG_PTR /*HWND*/ hWndParent, /*[out]*/ VARIANT_BOOL* pRet)
  446. {
  447. m_hWndEditWindow=(HWND)hWndParent;
  448. return S_OK;
  449. }
  450. STDMETHOD (EndEdit)(/*[in]*/ VARIANT_BOOL bEditCancelled){return E_NOTIMPL;}
  451. STDMETHOD (Dropped)(/*[in]*/ BSTR bstrUrl)
  452. {
  453. return E_NOTIMPL;
  454. }
  455. STDMETHOD(GetDropTarget) (/*[out, retval]*/ IUnknown** ppDropTarget)
  456. {
  457. // return our IDropTarget interface...
  458. return _InternalQueryInterface(IID_IDropTarget, (void**) ppDropTarget);
  459. }
  460. STDMETHOD (Refreshed)(/*[in]*/ BSTR bstrUrl)
  461. {
  462. return E_NOTIMPL;
  463. }
  464. STDMETHOD (SetEditorWindow)(/*[in]*/ LONG_PTR /*HWND*/ hWndEditor, /*[in]*/ IUnknown* pPropInspector)
  465. {
  466. // Cache the preview window...not used in this default example.
  467. m_hPreviewWnd = (HWND) hWndEditor;
  468. return E_NOTIMPL;
  469. }
  470. STDMETHOD (ValidateEditChanges)()
  471. {
  472. // Called when the user edits the tool in the default editor. Implement this to validate changes
  473. // made to your tools here.
  474. return E_NOTIMPL;
  475. }
  476. STDMETHOD(SetToolProperties) (/*[in]*/ IUnknown* pProp)
  477. {
  478. // Cache the tool properties object for later use.
  479. HRESULT hr = pProp->QueryInterface(IID_IAcadToolProperties, (void**) &m_pToolProp);
  480. if(!m_pToolProp)
  481. return E_FAIL;
  482. hr=m_pToolProp->get_ShapePackageId(&m_FlyoutPackageId);
  483. hr = m_pToolProp->get_CurrentShapeId(&m_CurrentShapeId);
  484. return S_OK;
  485. }
  486. STDMETHOD (GetToolProperties)(/*[out, retval]*/ IUnknown** pToolProp)
  487. {
  488. // Return the tool properties here...
  489. m_pToolProp->QueryInterface(IID_IAcadToolProperties,(void**)pToolProp);
  490. return S_OK;
  491. }
  492. STDMETHOD(New) ()
  493. {
  494. // You should really override this method, and initialize all your members.
  495. return E_NOTIMPL;
  496. }
  497. // IAcadTool2 members
  498. STDMETHOD(UpdateImage)(void)
  499. {
  500. return E_NOTIMPL;
  501. }
  502. STDMETHOD(GetContextMenu) (/*[in]*/ INT_PTR nContextFlag, /*[in]*/ DWORD_PTR /*HMENU*/ hMenu, /*[in]*/ UINT idCmdFirst,/*[in]*/ UINT idCmdLast, /*[out, retval]*/ DWORD_PTR* pFlag){return E_NOTIMPL;}
  503. STDMETHOD(GetCommandString) (/*[in]*/ UINT idCmd, /*[out, retval]*/BSTR* pbstrHelpText){return E_NOTIMPL;}
  504. STDMETHOD(InvokeCommand) (/*[in]*/ UINT idCmd, /*[in]*/ DWORD_PTR /*HWND*/ hWnd){return E_NOTIMPL;}
  505. STDMETHOD(GetDragDropContextInfo) (/*[in]*/ IUnknown* pIUnknown, /*[out]*/BSTR* pbstrText, /*[out]*/ DWORD* pFlag)
  506. {
  507. _bstr_t bstrName(szToolName);
  508. *pbstrText = bstrName.copy();
  509. return S_OK;
  510. }
  511. STDMETHOD(BeginMultipleEdit) (/*[in]*/ VARIANT tools,
  512. /*[in]*/ VARIANT stockToolIds)
  513. {
  514. return E_NOTIMPL;
  515. }
  516. STDMETHOD(EndMultipleEdit) (/*[in]*/ VARIANT tools,
  517. /*[in]*/ VARIANT stockToolIds,
  518. /*[in]*/ VARIANT_BOOL bEditCancelled)
  519. {
  520. return E_NOTIMPL;
  521. }
  522. STDMETHOD (MultipleEdit) (/*[in]*/ VARIANT tools,
  523. /*[in]*/ VARIANT stockToolIds,
  524. /*[in]*/ LONG_PTR /*HWND*/ hWndParent,
  525. /*[out]*/ VARIANT_BOOL* pRet)
  526. {
  527. return E_NOTIMPL;
  528. }
  529. // ************************************************************************************
  530. // IAcadToolContextMenu members - Override these if you need custom context menus
  531. STDMETHOD(Customize)(/* [in] */ int nContextFlag,
  532. /* [in] */ DWORD_PTR hMenu,
  533. /* [in] */ UINT idCmdFirst,
  534. /* [in] */ UINT idCmdLast,
  535. /* [in] */ GUID *pPaletteId,
  536. /* [retval][out] */ DWORD *pFlag)
  537. {
  538. return E_NOTIMPL;
  539. }
  540. STDMETHOD(GetMenuHelp)( /* [in] */ UINT idCmd,
  541. /* [retval][out] */ BSTR *pbstrHelpText)
  542. {
  543. return E_NOTIMPL;
  544. }
  545. STDMETHOD(InvokeMenuCommand)(/* [in] */ UINT idCmd,
  546. /* [in] */ GUID *pPaletteId,
  547. /* [in] */ DWORD_PTR hWnd,
  548. /* [retval][out] */ DWORD *pFlag)
  549. {
  550. return E_NOTIMPL;
  551. }
  552. // ************************************************************************************
  553. // IDropTarget members
  554. STDMETHOD(DragEnter) (/*[unique][in]*/ IDataObject __RPC_FAR *pDataObj, /*[in]*/ DWORD grfKeyState, /*[in]*/ POINTL pt, /*[out][in]*/ DWORD __RPC_FAR *pdwEffect)
  555. {
  556. *pdwEffect = DROPEFFECT_COPY;
  557. return S_OK;
  558. }
  559. STDMETHOD(DragOver) (/*[in]*/ DWORD grfKeyState, /*[in]*/ POINTL pt, /*[out][in]*/ DWORD __RPC_FAR *pdwEffect)
  560. {
  561. *pdwEffect = DROPEFFECT_COPY;
  562. return S_OK;
  563. }
  564. STDMETHOD(DragLeave) (void){return E_NOTIMPL;}
  565. STDMETHOD(Drop) (/*[unique][in]*/ IDataObject __RPC_FAR *pDataObj, /*[in]*/ DWORD grfKeyState, /*[in]*/ POINTL pt, /*[out][in]*/ DWORD __RPC_FAR *pdwEffect)
  566. {
  567. *pdwEffect = DROPEFFECT_COPY;
  568. COleDataObject data;
  569. data.Attach(pDataObj, FALSE);
  570. // This feature utilizes the AutoCAD Drag and Drop functionality, which uses the Windows System Clipboard.
  571. // First, get the clipboard info.
  572. ClipboardInfo clipInfo;
  573. if (!GetClipInfo(&data, &clipInfo))
  574. return E_FAIL;
  575. AcDbDatabase tempDb(false, true);
  576. Acad::ErrorStatus es = tempDb.readDwgFile(clipInfo.szTempFile);
  577. if (es != Acad::eOk)
  578. return E_FAIL;
  579. AcDbBlockTableRecordIterator *pItr = NULL;
  580. {
  581. AcDbBlockTableRecordPointer pBTR(ACDB_MODEL_SPACE,&tempDb,AcDb::kForRead);
  582. if(pBTR->newIterator(pItr)!=Acad::eOk)
  583. return E_FAIL;
  584. }
  585. AcDbEntity *pDropEntity=NULL;
  586. while(!pItr->done())
  587. {
  588. // The first entity in (the temporary) Model Space should be our entity...
  589. if(pItr->getEntity(pDropEntity, AcDb::kForRead)!=Acad::eOk)
  590. {
  591. delete pItr;
  592. return E_FAIL;
  593. }
  594. break;// we only need the first one...
  595. pItr->step();
  596. }
  597. delete pItr;
  598. if(pDropEntity==NULL)
  599. return E_FAIL;
  600. // Entities dropped from the editor generally should not have unspecified versions of these...
  601. m_bLayerUnspecified=FALSE;
  602. m_bColorUnspecified=FALSE;
  603. HRESULT hr=dropCallback(pDropEntity); // Allow the Child class to handle how the tools are created when content is dropped.
  604. pDropEntity->close();
  605. if(!SUCCEEDED(hr))
  606. return E_FAIL;
  607. // Now apply properties to the toolprop object...
  608. if (m_pToolProp != NULL) {
  609. hr=m_pToolProp->put_Name(CComBSTR(szToolName));
  610. WCHAR modulePath[MAX_PATH];
  611. HINSTANCE hInst=_AtlBaseModule.GetResourceInstance();
  612. DWORD res=GetModuleFileName(hInst,modulePath,MAX_PATH);
  613. AcTcImage image;
  614. HBITMAP hBitmap=::LoadBitmap(_AtlBaseModule.GetResourceInstance(),szToolImage);
  615. image.Load(hBitmap);
  616. SIZE size;
  617. image.GetSize(&size);
  618. hr=m_pToolProp->SetImage(size.cx,size.cy,NULL,CComBSTR(szToolImage),CComBSTR(modulePath));
  619. }
  620. data.Detach();
  621. return hr;
  622. }
  623. // ************************************************************************************
  624. // IPropertyUnspecified Members
  625. STDMETHOD (IsValueUnspecified)(/*[in]*/ VARIANT varId, /*[out]*/ VARIANT_BOOL *pVal)
  626. {
  627. *pVal = VARIANT_FALSE;
  628. if (varId.ulVal == dispColor || varId.ulVal == dispLayer)
  629. { if (varId.ulVal == dispColor && m_bColorUnspecified)
  630. *pVal=VARIANT_TRUE;
  631. if (varId.ulVal == dispLayer && m_bLayerUnspecified)
  632. *pVal=VARIANT_TRUE;
  633. }
  634. return S_OK;
  635. }
  636. STDMETHOD (SetUnspecified)(/*[in]*/ VARIANT varId, /*[in]*/ VARIANT_BOOL bIsUnspecified)
  637. {
  638. if (varId.ulVal == dispColor)
  639. m_bColorUnspecified = (bIsUnspecified == VARIANT_TRUE ? true : false);
  640. else if (varId.ulVal == dispLayer)
  641. m_bLayerUnspecified = (bIsUnspecified == VARIANT_TRUE ? true : false);
  642. return S_OK;
  643. }
  644. STDMETHOD (IsUnspecifiedAllowed)(/*[in]*/ VARIANT varId, /*[out]*/ VARIANT_BOOL *pVal)
  645. {
  646. if (varId.ulVal == dispColor || varId.ulVal == dispLayer)
  647. *pVal=VARIANT_TRUE;
  648. else
  649. *pVal = VARIANT_FALSE;
  650. return S_OK;
  651. }
  652. STDMETHOD (GetUnspecifiedString)(VARIANT,BSTR *str)
  653. {
  654. // Called to get the string which specifies an undefined value in these controls..
  655. _bstr_t unspecifiedString(L"*Unspecified*");
  656. *str = unspecifiedString.copy();
  657. return S_OK;
  658. }
  659. STDMETHOD(GetEllipsisBitMap) (
  660. /* [in] */ VARIANT varId,
  661. /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *pBitMap){return E_NOTIMPL;}
  662. STDMETHOD(GetPropHelpProc) (
  663. /* [in] */ VARIANT varId,
  664. /* [out] */ LONG __RPC_FAR *pHelpProc){return E_NOTIMPL;}
  665. // Extract the dropped data from the clipboard.
  666. BOOL GetClipInfo(COleDataObject* pDataObject, ClipboardInfo* pClipboardInfo)
  667. {
  668. CLIPFORMAT cFormat = mcfAutoCAD;
  669. if (!pDataObject->IsDataAvailable(cFormat)) {
  670. return FALSE;
  671. }
  672. STGMEDIUM stgMedium = { TYMED_HGLOBAL, NULL };
  673. FORMATETC fmt = { cFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  674. BOOL bValid = pDataObject->GetData(cFormat, &stgMedium, &fmt);
  675. if (bValid && stgMedium.hGlobal != NULL)
  676. {
  677. ClipboardInfo* pClipInfo=(ClipboardInfo*)::GlobalLock(stgMedium.hGlobal);
  678. // Copy all the data
  679. *pClipboardInfo = *pClipInfo;
  680. ::GlobalUnlock(stgMedium.hGlobal);
  681. ::ReleaseStgMedium(&stgMedium);
  682. return TRUE;
  683. }
  684. return FALSE;
  685. }
  686. virtual HRESULT GetPropertyTypeInfo()
  687. {
  688. // This is the function called to determine the DISPIDs and property names for the child class' interface so
  689. // they can be automatically supported. These are stored in the TOOL_MAP. It should only be called once per-creation.
  690. T *pITool;
  691. // Get IDispatch interface for object
  692. if (!SUCCEEDED(QueryInterface(*piid,(void**)&pITool)))
  693. return E_FAIL;
  694. // Find out if we have Type Info (we should have)
  695. unsigned int count = 0;
  696. if (!SUCCEEDED(pITool->GetTypeInfoCount(&count))) {
  697. pITool->Release();
  698. return E_FAIL;
  699. }
  700. // If no Type Info, exit
  701. if (!count)
  702. return E_FAIL;// No properties to Jig ???
  703. // Get iTypeInfo interface for object for any locale
  704. CComPtr<ITypeInfo> pTypeInfo;
  705. if (!SUCCEEDED(pITool->GetTypeInfo(0, NULL, &pTypeInfo))) {
  706. pITool->Release();
  707. return E_FAIL;
  708. }
  709. pITool->Release();
  710. // Retrieve type attributes - to find number of methods for entity
  711. TYPEATTR * pTypeAttr;
  712. if (!SUCCEEDED(pTypeInfo->GetTypeAttr(&pTypeAttr)))
  713. return E_FAIL;
  714. int numFuncs = pTypeAttr->cFuncs;
  715. pTypeInfo->ReleaseTypeAttr(pTypeAttr);
  716. m_ToolMap.setLogicalLength(0);// Clear the array.
  717. // Iterate over all methods.
  718. for(int i = 0; i < numFuncs; i++)
  719. {
  720. //Get the function description
  721. FUNCDESC * pFuncDesc;
  722. if (!SUCCEEDED(pTypeInfo->GetFuncDesc(i, &pFuncDesc)))
  723. return E_FAIL;
  724. //Get the member ID
  725. MEMBERID memberID;
  726. memberID = pFuncDesc->memid;
  727. if(memberID < 1000) // Assumes the IDs below 1000 are the child class' methods
  728. {
  729. UINT nReturnedNames;
  730. // Since the DISPID will be shared by both 'put' and 'get' functions, we will enter here twice for each property, though we
  731. // only need to use one. The 'get' version will have the VT_BYREF or'ed in the VARTYPE,
  732. // so we can chose to ignore this one to get the true type from the property 'put' version.
  733. if(pFuncDesc->invkind==INVOKE_PROPERTYGET)
  734. continue;
  735. // This is equivalent to checking invkind...
  736. //if(pFuncDesc->lprgelemdescParam[nReturnedNames-1].tdesc.vt & VT_BYREF)
  737. // continue;
  738. // Allocate one BSTR pointer array.
  739. BSTR bstrNames[1] = {NULL};
  740. if (!SUCCEEDED(pTypeInfo->GetNames(memberID, bstrNames, 1, &nReturnedNames)))
  741. return E_FAIL;
  742. if(nReturnedNames<1)
  743. continue; // no need to delete the bstr array...since the size is zero...
  744. CComBSTR bstrVal(bstrNames[0]);
  745. COLE2T szName(bstrVal);
  746. TOOL_MAP_ENTRY mapEntry;
  747. wcscpy_s(mapEntry.szDesc,szName);
  748. mapEntry.dispId=memberID;
  749. m_ToolMap.append(mapEntry);
  750. // Determine the Color and Layer DISPIDs.
  751. if(!wcscmp(szName,L"Color"))
  752. dispColor=memberID;
  753. if(!wcscmp(szName,L"Layer"))
  754. dispLayer=memberID;
  755. if(!wcscmp(szName,L"Flyout"))
  756. dispFlyout=memberID;
  757. // Only one element array.
  758. SysAllocString(bstrNames[0]);
  759. }
  760. }
  761. return S_OK;
  762. }
  763. HRESULT PutToolProperty(int index,VARIANT vValue)
  764. {
  765. // Places the property value to the tool instance from vValue via COM.
  766. // Note: Here, index is 1 based, and should match the DISPIDs for each property.
  767. // index-1 is the index into the TOOL_MAP...vValue is the value to set.
  768. WORD wflags = DISPATCH_PROPERTYPUT;
  769. DISPID putid = DISPID_PROPERTYPUT;
  770. // Get IDispatch from the tool interface.
  771. CComPtr<IDispatch> pDisp;
  772. if(!SUCCEEDED(QueryInterface(*piid,(void**)&pDisp)))
  773. return E_FAIL;
  774. DISPPARAMS dispparams;
  775. dispparams.rgvarg = &vValue;
  776. dispparams.rgdispidNamedArgs= &putid;
  777. dispparams.cArgs = 1;
  778. dispparams.cNamedArgs = 1;
  779. return pDisp->Invoke(m_ToolMap[index-1].dispId,
  780. IID_NULL,
  781. LOCALE_USER_DEFAULT,
  782. wflags,
  783. &dispparams,
  784. NULL,NULL,NULL);
  785. }
  786. HRESULT GetToolProperty(int index,VARIANT& vValue)
  787. {
  788. // Note: Here, index is 1 based, and should match the DISPIDs for each property.
  789. // Retrieves the property value from the tool instance, placing it into vValue.
  790. // Get IDispatch from the tool interface.
  791. CComPtr<IDispatch> pDisp;
  792. if(!SUCCEEDED(QueryInterface(*piid,(void**)&pDisp)))
  793. return E_FAIL;
  794. DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  795. return pDisp->Invoke(
  796. m_ToolMap[index-1].dispId,
  797. IID_NULL,
  798. LOCALE_USER_DEFAULT,
  799. DISPATCH_PROPERTYGET,
  800. &dispparamsNoArgs, &vValue, NULL, NULL);
  801. }
  802. //IPerPropertyBrowsing
  803. STDMETHOD(GetDisplayString)(DISPID dispID,BSTR *pbstr)
  804. {
  805. return E_NOTIMPL;
  806. }
  807. STDMETHOD(MapPropertyToPage)(DISPID dispID,CLSID *pCLSID)
  808. {
  809. if(dispID==dispFlyout)
  810. {
  811. *pCLSID=*pclsid;
  812. pAcadToolImpl=(void*)this;
  813. return S_OK;
  814. }
  815. else
  816. return E_NOTIMPL;
  817. }
  818. STDMETHOD(GetPredefinedStrings)(DISPID dispID,CALPOLESTR *pcaStringsOut,CADWORD *pcaCookiesOut)
  819. {
  820. return E_NOTIMPL;
  821. }
  822. STDMETHOD(GetPredefinedValue)(DISPID dispID,DWORD dwCookie,VARIANT *pVarOut)
  823. {
  824. return E_NOTIMPL;
  825. }
  826. // *******************************************************************************************
  827. // IOPMPropertyDialog
  828. STDMETHOD(DoModal)(BSTR* propValueString,AcDbObjectIdArray* ObjectIdArray)
  829. {
  830. IAcadToolProperties *pToolProp=GetThisToolsProperties();
  831. if(!pToolProp)
  832. return E_FAIL;
  833. AcTcManager* pMgr = AcTcGetManager();
  834. if (!pMgr)
  835. return E_FAIL;
  836. // Get the shape package
  837. //
  838. GUID id;
  839. pToolProp->get_ShapePackageId(&id);
  840. AcTcCatalogItem* pShapeCatalog = pMgr->GetShapeCatalog();
  841. AcTcCatalogItem* pShapePackage=pShapeCatalog->FindInChildren(id);
  842. if (!pShapePackage)
  843. return E_FAIL;
  844. // Get the activeshapes
  845. VARIANT varShapes;
  846. HRESULT hr = pToolProp->get_ActiveShapeIds(&varShapes);
  847. if(!(varShapes.vt & VT_ARRAY && varShapes.vt & VT_BSTR))
  848. return E_INVALIDARG;
  849. SAFEARRAY* sPt=varShapes.parray;
  850. if(SafeArrayGetDim(sPt)!=1)
  851. return E_INVALIDARG;
  852. long lLower,lUpper;
  853. SafeArrayGetLBound(sPt,1,&lLower);
  854. SafeArrayGetUBound(sPt,1,&lUpper);
  855. //AcTcCatalogItemArray activeShapes;
  856. AcTcCatalogItemArray activeShapes;
  857. for(long i=lLower; i<=lUpper; i++) {
  858. VARIANT val;
  859. SafeArrayGetElement(sPt,&i,&val);
  860. GUID id;
  861. GuidFromString(CW2T(val.bstrVal), id);
  862. AcTcCatalogItem* pItem = pShapePackage->FindInChildren(id, FALSE);
  863. if (pItem == NULL)
  864. continue;
  865. if (pItem->GetType() == kItemTool)
  866. activeShapes.Add(pItem);
  867. }
  868. // Get the current shape
  869. //
  870. GUID currentShapeId;
  871. hr = pToolProp->get_CurrentShapeId(&currentShapeId);
  872. AcTcTool* pCurrentShape = (AcTcTool*)pShapePackage->FindInChildren(currentShapeId, FALSE);
  873. // Display the filter shape dialog for the user to edit the
  874. // active shapes
  875. if(!AcTcUiFilterShapesDialog(pShapePackage, &activeShapes,pCurrentShape, NULL))
  876. return E_FAIL;
  877. // Now replace the active shapes with those updated by the user.
  878. INT_PTR nCount = activeShapes.GetSize();
  879. SAFEARRAYBOUND rgsaBound;
  880. rgsaBound.lLbound = 0L;
  881. //Active shape size can't be more than 1M
  882. rgsaBound.cElements = AcIntPtrToInt(nCount);
  883. VariantClear(&varShapes);
  884. varShapes.vt = VT_ARRAY | VT_VARIANT;
  885. sPt=varShapes.parray;
  886. varShapes.parray = SafeArrayCreate(VT_VARIANT, 1, &rgsaBound);
  887. for (long i=0; i<nCount; i++) {
  888. AcTcCatalogItem* pItem = activeShapes[i];
  889. pItem->GetID(&id);
  890. VARIANT varGuid;
  891. varGuid.vt = VT_BSTR;
  892. varGuid.bstrVal=StringFromGuid(id);
  893. hr = SafeArrayPutElement(varShapes.parray, &i,&varGuid);
  894. }
  895. hr=pToolProp->put_ActiveShapeIds(&varShapes);
  896. return S_OK;
  897. }
  898. // IAcadToolFlyoutShape methods
  899. STDMETHOD(SetFlyoutTools) (/* [in] */ VARIANT* pFlyoutToolIds)
  900. {
  901. wcscpy_s(m_FlyoutTools,L"");
  902. if (pFlyoutToolIds == NULL)
  903. return S_OK;
  904. SAFEARRAY* saFlyoutToolIds=pFlyoutToolIds->parray;
  905. if(SafeArrayGetDim(saFlyoutToolIds)!=1)
  906. return E_INVALIDARG;
  907. long lLower,lUpper;
  908. SafeArrayGetLBound(saFlyoutToolIds,1,&lLower);
  909. SafeArrayGetUBound(saFlyoutToolIds,1,&lUpper);
  910. for(long i=lLower; i<=lUpper; i++) {
  911. VARIANT val;
  912. SafeArrayGetElement(saFlyoutToolIds,&i,&val);
  913. wcscpy_s(m_FlyoutTools,CW2T(val.bstrVal));
  914. }
  915. return S_OK;
  916. }
  917. // ************************************************************************************
  918. // IOPMPropertyExtension
  919. STDMETHOD(Editable)(DISPID dispID,BOOL __RPC_FAR * bEditable)
  920. {
  921. return E_NOTIMPL;
  922. }
  923. STDMETHOD(GetDisplayName)(DISPID dispID,BSTR * propName)
  924. {
  925. return E_NOTIMPL;
  926. }
  927. STDMETHOD(ShowProperty)(DISPID dispID,BOOL * pShow)
  928. {
  929. // This is here to distiguish when a given tool instance is a flyout. For Flyouts, we only want
  930. // to edit properties which are called out in the child class with FLYOUT_ENTRYs. In addition, we don't want to show the
  931. // Flyout option for non-flyout tools.
  932. *pShow=TRUE;
  933. IAcadToolProperties *pToolProp=GetThisToolsProperties();
  934. if(!pToolProp)
  935. return E_FAIL;
  936. VARIANT_BOOL vbFlyout;
  937. pToolProp->get_IsFlyoutEnabled(&vbFlyout);
  938. if(vbFlyout)
  939. {
  940. PER_FLYOUT_ENTRY *pFlyoutMap=TT::GetFlyoutMap();
  941. for(int i=0;i<m_ToolMap.length();i++)
  942. {
  943. int ii=0;
  944. bool bGlobalProp=false;
  945. while(pFlyoutMap[ii].dispid!=-1)
  946. {
  947. if(pFlyoutMap[ii].dispid==dispID)
  948. {
  949. bGlobalProp=true;
  950. break;
  951. }
  952. ii++;
  953. }
  954. if(bGlobalProp)
  955. *pShow=TRUE;
  956. else
  957. *pShow=FALSE;
  958. }
  959. }
  960. else
  961. if(dispID==dispFlyout)
  962. *pShow=FALSE;
  963. return S_OK;
  964. }
  965. BOOL GuidFromString(LPWSTR pszGuid, GUID& id)
  966. {
  967. ZeroMemory(&id, sizeof(GUID));
  968. if (pszGuid == NULL)
  969. return FALSE;
  970. // Enclose the guid in braces if not enclosed already,
  971. // otherwise CLSIDFromString will fail.
  972. WCHAR tsFormatGuid[64]=L"{";
  973. if(wcslen(pszGuid) > 0 && pszGuid[0] !=L'{')
  974. wcscat_s(tsFormatGuid,pszGuid);
  975. if(wcslen(pszGuid) > 0 && pszGuid[wcslen(tsFormatGuid)-1] !=L'}')
  976. wcscat_s(tsFormatGuid,L"}");
  977. HRESULT hr = CLSIDFromString(CT2W(tsFormatGuid), &id);
  978. return SUCCEEDED(hr);
  979. }
  980. CComBSTR StringFromGuid(const GUID& id)
  981. {
  982. // If we use CComBSTR it crashes. Use LPOLESTR.
  983. LPOLESTR pbstrGuid = NULL;
  984. HRESULT hr = StringFromCLSID(id, &pbstrGuid);
  985. if (FAILED(hr) || pbstrGuid == NULL)
  986. return L"";
  987. CW2T szVal(pbstrGuid);
  988. LPWSTR sId(szVal);
  989. // Remove open and close braces from the guid
  990. sId=_wcsninc(sId,1);
  991. _wcsrev(sId);
  992. sId=_wcsninc(sId,1);
  993. _wcsrev(sId);
  994. CComBSTR bstr(sId);
  995. CoTaskMemFree(pbstrGuid);
  996. return bstr;
  997. }
  998. // Handling of the True Color Combo Box property here.
  999. STDMETHOD (get_Color)(VARIANT *pVar)
  1000. {
  1001. if (pVar == NULL)
  1002. return E_FAIL;
  1003. VariantInit(pVar);
  1004. pVar->vt = VT_DISPATCH;
  1005. CComQIPtr<IAcadAcCmColor> pIAcadAcCmColor;
  1006. HRESULT hr = pIAcadAcCmColor.CoCreateInstance(CLSID_AcadAcCmColor);
  1007. if (FAILED(hr) || !pIAcadAcCmColor)
  1008. return E_FAIL;
  1009. CComBSTR colorName(m_Color.colorName());
  1010. CComBSTR bookName(m_Color.bookName());
  1011. pIAcadAcCmColor->put_EntityColor(m_Color.color());
  1012. pIAcadAcCmColor->SetNames(colorName, bookName);
  1013. hr = pIAcadAcCmColor->QueryInterface(IID_IDispatch, (void**) &pVar->pdispVal);
  1014. if(SUCCEEDED(hr))
  1015. return S_OK;
  1016. else
  1017. return E_FAIL;
  1018. }
  1019. STDMETHOD (put_Color)(VARIANT pVar)
  1020. {
  1021. if (V_VT(&pVar) != VT_DISPATCH)
  1022. return E_FAIL;
  1023. if (pVar.pdispVal == NULL)
  1024. return E_FAIL;
  1025. HRESULT hr = S_OK;
  1026. CComQIPtr<IAcadAcCmColor> pIAcadAcCmColor;
  1027. hr = pVar.pdispVal->QueryInterface(IID_IAcadAcCmColor, (void**) &pIAcadAcCmColor);
  1028. if (FAILED(hr) || !pIAcadAcCmColor)
  1029. return E_FAIL;
  1030. BSTR colorName, bookName;
  1031. long lEntityColor;
  1032. colorName = bookName = NULL;
  1033. lEntityColor = 0;
  1034. hr = pIAcadAcCmColor->get_EntityColor(&lEntityColor);
  1035. hr = pIAcadAcCmColor->get_ColorName(&colorName);
  1036. hr = pIAcadAcCmColor->get_BookName(&bookName);
  1037. m_Color.setColor(lEntityColor);
  1038. m_Color.setNames(CW2T(colorName),CW2T(bookName));
  1039. return S_OK;
  1040. }
  1041. // Handling the Layer Combo Box property here.
  1042. STDMETHOD (get_Layer)(BSTR* pVal)
  1043. {
  1044. CComBSTR bStr(m_szLayer);
  1045. bStr.CopyTo(pVal);
  1046. return S_OK;
  1047. }
  1048. STDMETHOD (put_Layer)(BSTR newVal)
  1049. {
  1050. CComBSTR bStr(newVal);
  1051. COLE2T szName(bStr);
  1052. wcscpy_s(m_szLayer,szName);
  1053. return S_OK;
  1054. }
  1055. STDMETHOD(put_Flyout)(BSTR var)
  1056. {
  1057. // Nothing to do here...
  1058. return S_OK;
  1059. }
  1060. STDMETHOD(get_Flyout)(BSTR *pVar)
  1061. {
  1062. CComBSTR bstr(L"<Choose Commands>");
  1063. bstr.CopyTo(pVar);
  1064. return S_OK;
  1065. }
  1066. BOOL GetUnknownArrays(int nCount,
  1067. IUnknown** pObjUnkArray,
  1068. VARIANT* pStatUnkArray,
  1069. VARIANT* pDynPMUnkArrays)
  1070. {
  1071. if (nCount < 1)
  1072. return FALSE;
  1073. pStatUnkArray->vt = VT_ARRAY | VT_VARIANT;
  1074. pDynPMUnkArrays->vt = VT_ARRAY | VT_VARIANT;
  1075. SAFEARRAYBOUND rgsaBound;
  1076. rgsaBound.lLbound = 0L;
  1077. rgsaBound.cElements = nCount;
  1078. pStatUnkArray->parray = SafeArrayCreate(VT_VARIANT, 1, &rgsaBound);
  1079. pDynPMUnkArrays->parray = SafeArrayCreate(VT_VARIANT,1,&rgsaBound);
  1080. HRESULT hr;
  1081. try {
  1082. for (long i = 0; i < nCount; i++)
  1083. {
  1084. VARIANT statVariant;
  1085. VariantClear(&statVariant);
  1086. statVariant.vt = VT_UNKNOWN;
  1087. statVariant.punkVal=pObjUnkArray[i];
  1088. hr = SafeArrayPutElement(pStatUnkArray->parray, &i, &statVariant);
  1089. VARIANT dynamicPMArray;
  1090. VariantClear(&dynamicPMArray);
  1091. dynamicPMArray.vt = VT_ARRAY | VT_VARIANT;
  1092. SAFEARRAYBOUND dynamicBound;
  1093. dynamicBound.lLbound = 0L;
  1094. dynamicBound.cElements = 1L;
  1095. dynamicPMArray.parray = SafeArrayCreate(VT_VARIANT, 1, &dynamicBound);
  1096. VARIANT statVariant2;
  1097. VariantClear(&statVariant2);
  1098. statVariant2.vt = VT_UNKNOWN;
  1099. statVariant2.punkVal=NULL;
  1100. long bound=0;
  1101. hr=SafeArrayPutElement(dynamicPMArray.parray, &bound,&statVariant2);
  1102. hr=SafeArrayPutElement(pDynPMUnkArrays->parray, &i, &dynamicPMArray);
  1103. }
  1104. }
  1105. catch(int)
  1106. {
  1107. return FALSE;
  1108. }
  1109. return TRUE;
  1110. }
  1111. // XML Persistence helper functions...
  1112. BOOL GetAttribute(MSXML::IXMLDOMNode* pNode,
  1113. LPCWSTR pszAttName,
  1114. MSXML::IXMLDOMAttribute** ppChild)
  1115. {
  1116. if (ppChild == NULL)
  1117. return FALSE;
  1118. *ppChild = NULL;
  1119. if (pNode == NULL || pszAttName == NULL)
  1120. return FALSE;
  1121. // Read the attributes of the item
  1122. //
  1123. MSXML::IXMLDOMNamedNodeMapPtr pAttributes;
  1124. pNode->get_attributes(&pAttributes);
  1125. if (pAttributes == NULL) {
  1126. // Wrong node type...
  1127. return FALSE;
  1128. }
  1129. long nCount;
  1130. pAttributes->get_length(&nCount);
  1131. if (nCount < 1) {
  1132. return FALSE;
  1133. }
  1134. MSXML::IXMLDOMAttributePtr pAttr;
  1135. pAttr = pAttributes->getNamedItem(_bstr_t(pszAttName));
  1136. if (pAttr == NULL) {
  1137. // The named attribute is not found
  1138. return FALSE;
  1139. }
  1140. *ppChild = pAttr.GetInterfacePtr();
  1141. // AddRef before returning
  1142. if (*ppChild != NULL)
  1143. (*ppChild)->AddRef();
  1144. return TRUE;
  1145. }
  1146. BOOL GetChildNode(MSXML::IXMLDOMNode* pNode,
  1147. LPCWSTR pszNodeName,
  1148. MSXML::IXMLDOMNode** ppChild)
  1149. {
  1150. try {
  1151. if (ppChild == NULL)
  1152. return FALSE;
  1153. *ppChild = NULL;
  1154. if (pNode == NULL || pszNodeName == NULL)
  1155. return FALSE;
  1156. // Get the named child element from the list of children
  1157. //
  1158. MSXML::IXMLDOMNodeListPtr pChildren;
  1159. pNode->get_childNodes(&pChildren);
  1160. if (pChildren == NULL) {
  1161. return FALSE;
  1162. }
  1163. int nCount = pChildren->Getlength();
  1164. if (nCount < 1) {
  1165. // No children
  1166. return FALSE;
  1167. }
  1168. for (long i=0; i<nCount; i++) {
  1169. MSXML::IXMLDOMNodePtr pNode;
  1170. pChildren->get_item(i, &pNode);
  1171. CComBSTR bstrName;
  1172. pNode->get_nodeName(&bstrName);
  1173. COLE2T szName(bstrName);
  1174. if(wcscmp(szName,pszNodeName) == 0) {
  1175. *ppChild = pNode.GetInterfacePtr();
  1176. // AddRef before returning
  1177. if (*ppChild != NULL)
  1178. (*ppChild)->AddRef();
  1179. return TRUE;
  1180. }
  1181. }
  1182. } catch (_com_error &e) {
  1183. SetLastError(e.Error());
  1184. return FALSE;
  1185. } catch(...)
  1186. {
  1187. return FALSE;
  1188. }
  1189. // Named child not found
  1190. return FALSE;
  1191. }
  1192. BOOL GetChildNodeValue(MSXML::IXMLDOMNode* pNode,
  1193. LPCWSTR pszNodeName,
  1194. LPWSTR pszValue)
  1195. {
  1196. try {
  1197. if (pNode == NULL || pszNodeName == NULL)
  1198. return FALSE;
  1199. MSXML::IXMLDOMNodePtr pChild;
  1200. if (!GetChildNode(pNode, pszNodeName, &pChild)) {
  1201. // Child not found
  1202. return FALSE;
  1203. }
  1204. CComVariant val;
  1205. HRESULT hr = S_OK;
  1206. if (pChild->hasChildNodes()) {
  1207. // Get the text child and then get the value so that we can get the
  1208. // text whether the node has the text directly or as cdata.
  1209. //
  1210. MSXML::IXMLDOMNodePtr pText;
  1211. pChild->get_firstChild(&pText);
  1212. hr = pText->get_nodeValue(&val);
  1213. } else {
  1214. // Get the node value directly
  1215. hr = pChild->get_nodeValue(&val);
  1216. }
  1217. if (FAILED(hr))
  1218. return FALSE;
  1219. if (val.vt != VT_NULL) {
  1220. // Node value data type should be string
  1221. if (val.vt != VT_BSTR)
  1222. return FALSE;
  1223. pszValue = COLE2T(val.bstrVal);
  1224. }
  1225. } catch (_com_error &e) {
  1226. SetLastError(e.Error());
  1227. return FALSE;
  1228. } catch(...) {
  1229. return FALSE;
  1230. }
  1231. return TRUE;
  1232. }
  1233. BOOL AddChildNode(MSXML::IXMLDOMNode* pNode,
  1234. LPCWSTR pszChildNodeName,
  1235. short nNodeType,
  1236. MSXML::IXMLDOMNode** ppChild
  1237. )
  1238. {
  1239. try {
  1240. if (ppChild == NULL)
  1241. return FALSE;
  1242. *ppChild = NULL;
  1243. if (pNode == NULL || pszChildNodeName == NULL)
  1244. return FALSE;
  1245. MSXML::IXMLDOMDocumentPtr pDoc;
  1246. MSXML::DOMNodeType type;
  1247. pNode->get_nodeType(&type);
  1248. if (type == MSXML::NODE_DOCUMENT)
  1249. pDoc = pNode;
  1250. else {
  1251. pNode->get_ownerDocument(&pDoc);
  1252. if (pDoc == NULL)
  1253. return FALSE;
  1254. }
  1255. _variant_t varType(nNodeType);
  1256. _bstr_t varName(pszChildNodeName);
  1257. MSXML::IXMLDOMNodePtr pNewNode = pDoc->createNode(varType, varName, L"");;
  1258. *ppChild = pNewNode.GetInterfacePtr();
  1259. // AddRef before returning
  1260. if (*ppChild != NULL)
  1261. (*ppChild)->AddRef();
  1262. pNode->appendChild(*ppChild);
  1263. } catch (_com_error &e) {
  1264. SetLastError(e.Error());
  1265. return FALSE;
  1266. } catch(...) {
  1267. return FALSE;
  1268. }
  1269. return TRUE;
  1270. }
  1271. BOOL GetAttributeValue(MSXML::IXMLDOMNode* pNode,
  1272. LPCWSTR pszAttName,
  1273. VARIANT& var)
  1274. {
  1275. if (! pNode || !pszAttName)
  1276. return FALSE;
  1277. MSXML::IXMLDOMAttributePtr pAttr;
  1278. if (!GetAttribute(pNode, pszAttName, &pAttr))
  1279. return FALSE;
  1280. HRESULT hr = pAttr->get_value(&var); // Retrieve the value into the VARIANT. VT Type will be discovered automatically.
  1281. return TRUE;
  1282. }
  1283. BOOL GetAttributeValue(MSXML::IXMLDOMNode* pNode,
  1284. LPCWSTR pszAttName,
  1285. long& lValue)
  1286. {
  1287. lValue = 0;
  1288. if (pNode == NULL || pszAttName == NULL)
  1289. return FALSE;
  1290. MSXML::IXMLDOMAttributePtr pAttr;
  1291. if (!GetAttribute(pNode, pszAttName, &pAttr))
  1292. return FALSE;
  1293. CComVariant val;
  1294. HRESULT hr = pAttr->get_value(&val);
  1295. if (val.vt == VT_BSTR) {
  1296. lValue = _tstol(COLE2T(val.bstrVal));
  1297. } else {
  1298. lValue = val.lVal;
  1299. }
  1300. return TRUE;
  1301. }
  1302. template <size_t nSize> inline
  1303. BOOL GetAttributeValue(MSXML::IXMLDOMNode* pNode,
  1304. LPCWSTR pszAttName,
  1305. WCHAR (&pszValue)[nSize]){
  1306. return GetAttributeValue(pNode, pszAttName, pszValue, nSize);
  1307. }
  1308. BOOL GetAttributeValue(MSXML::IXMLDOMNode* pNode,
  1309. LPCWSTR pszAttName,
  1310. LPWSTR pszValue,
  1311. size_t nSize)
  1312. {
  1313. if (pNode == NULL || pszAttName == NULL)
  1314. return FALSE;
  1315. MSXML::IXMLDOMAttributePtr pAttr;
  1316. if (!GetAttribute(pNode, pszAttName, &pAttr))
  1317. return FALSE;
  1318. CComVariant val;
  1319. HRESULT hr = pAttr->get_value(&val);
  1320. CComBSTR bstr(val.bstrVal);
  1321. COLE2T szValue(bstr);
  1322. wcscpy_s(pszValue, nSize, szValue);
  1323. return TRUE;
  1324. }
  1325. BOOL GetAttributeValue(MSXML::IXMLDOMNode* pNode,
  1326. LPCWSTR pszAttName,
  1327. short& sValue)
  1328. {
  1329. try {
  1330. sValue = 0;
  1331. if (pNode == NULL || pszAttName == NULL)
  1332. return FALSE;
  1333. MSXML::IXMLDOMAttributePtr pAttr;
  1334. if (!GetAttribute(pNode, pszAttName, &pAttr))
  1335. return FALSE;
  1336. CComVariant val;
  1337. HRESULT hr = pAttr->get_value(&val);
  1338. if(val.vt == VT_BSTR){
  1339. sValue = _tstoi(COLE2T(val.bstrVal));
  1340. } else {
  1341. sValue = 0;
  1342. }
  1343. } catch (_com_error &e) {
  1344. SetLastError(e.Error());
  1345. return FALSE;
  1346. } catch(...) {
  1347. return FALSE;
  1348. }
  1349. return TRUE;
  1350. }
  1351. BOOL GetAttributeValue(MSXML::IXMLDOMNode* pNode,
  1352. LPCWSTR pszAttName,
  1353. double& fValue)
  1354. {
  1355. try {
  1356. fValue = 0.0;
  1357. if (pNode == NULL || pszAttName == NULL)
  1358. return FALSE;
  1359. MSXML::IXMLDOMAttributePtr pAttr;
  1360. if (!GetAttribute(pNode, pszAttName, &pAttr))
  1361. return FALSE;
  1362. CComVariant val;
  1363. HRESULT hr = pAttr->get_value(&val);
  1364. if(val.vt == VT_BSTR){
  1365. fValue = _tstof(CW2T(val.bstrVal));
  1366. } else {
  1367. fValue = 0.0;
  1368. }
  1369. } catch (_com_error &e) {
  1370. SetLastError(e.Error());
  1371. return FALSE;
  1372. } catch(...) {
  1373. return FALSE;
  1374. }
  1375. return TRUE;
  1376. }
  1377. inline BOOL SetAttributeValue(MSXML::IXMLDOMNode* pNode,
  1378. LPCWSTR pszAttName,
  1379. double fValue)
  1380. {
  1381. MSXML::IXMLDOMElementPtr pElement = pNode;
  1382. if (pNode == NULL || pElement == NULL || pszAttName == NULL)
  1383. return FALSE;
  1384. CComVariant var(fValue);
  1385. HRESULT hr = pElement->setAttribute(pszAttName, var);
  1386. return SUCCEEDED(hr);
  1387. }
  1388. virtual BOOL LoadPropertyValue(MSXML::IXMLDOMNode* pNode,
  1389. int index)
  1390. {
  1391. // Retrieves the indexed property value from XML, and marshals it via COM to the tool.
  1392. VARIANT vValue;
  1393. VariantInit(&vValue);
  1394. // Note: Here, index is 1 based, and should match the DISPIDs for each property.
  1395. if(dispColor==index)
  1396. {
  1397. // XML doesn't support persisting Dispatch pointers, so we must persist the Color, ColorName and
  1398. // BookName directly here.
  1399. MSXML::IXMLDOMNodePtr pColorNode,pColorBookNode;
  1400. if(GetChildNode(pNode, L"TrueColor",&pColorNode))
  1401. {
  1402. // \ TrueColor
  1403. if(GetChildNode(pColorNode,L"ColorValue",&pColorBookNode))
  1404. {
  1405. // \TrueColor\colorValue
  1406. GetAttributeValue(pColorBookNode, L"Unspecified", (long&)m_bColorUnspecified);
  1407. long color;
  1408. GetAttributeValue(pColorBookNode, L"Color", color);
  1409. m_Color.setColor(color);
  1410. }
  1411. WCHAR sColorName[512]={_T("")},sColorBook[512]={_T("")};
  1412. if(GetChildNode(pColorNode,_T("ColorName"),&pColorBookNode))
  1413. // \TrueColor\ColorName
  1414. GetAttributeValue(pColorBookNode, L"Color", sColorName);
  1415. if(GetChildNode(pColorNode,L"ColorBook",&pColorBookNode))
  1416. // \TrueColor\ColorBook
  1417. GetAttributeValue(pColorBookNode, L"Color", sColorBook);
  1418. // We could wrap this value in the VARIANT as a dispatch pointer, and pass it through,
  1419. // but it would only ultimately set the m_Color variable as we do here next.
  1420. // The Dispatch pointer is only really important when we marshal the color back into
  1421. // the Property Inspector.
  1422. const WCHAR* pNullName = NULL;
  1423. m_Color.setNames( wcslen(sColorName) ? sColorName : pNullName,
  1424. wcslen(sColorBook) ? sColorBook : pNullName);
  1425. }
  1426. return TRUE;
  1427. }
  1428. if(dispLayer == index)
  1429. GetAttributeValue(pNode, L"Unspecified", (long&)m_bLayerUnspecified);
  1430. GetAttributeValue(pNode,L"PropertyValue",vValue); // Get the value from the XML file through the VARIANT.
  1431. PutToolProperty(index,vValue);// Place the value into the member variable in the child interface.
  1432. return TRUE;
  1433. }
  1434. virtual BOOL SavePropertyValue(MSXML::IXMLDOMNode* pNode,
  1435. int index)
  1436. {
  1437. // Sets the XML for the indexed property.
  1438. VARIANT vValue;
  1439. VariantInit(&vValue);
  1440. HRESULT hr=GetToolProperty(index,vValue);
  1441. // Note: Here, index is 1 based, and should match the DISPIDs for each property.
  1442. if(dispColor==index)
  1443. {
  1444. // XML doesn't support persisting Dispatch pointers, so we must persist the Color, ColorName and
  1445. // BookName directly here.
  1446. // \ TrueColor
  1447. MSXML::IXMLDOMNodePtr pColorNode,pColorBookNode;
  1448. if(!GetChildNode(pNode,L"TrueColor",&pColorNode))
  1449. AddChildNode(pNode, L"TrueColor", MSXML::NODE_ELEMENT, &pColorNode);
  1450. if (pColorNode == NULL)
  1451. return FALSE;
  1452. // \TrueColor \ColorValue
  1453. if(!GetChildNode(pColorNode,L"ColorValue",&pColorBookNode))
  1454. AddChildNode(pColorNode, L"ColorValue", MSXML::NODE_ELEMENT, &pColorBookNode);
  1455. SetAttributeValue(pColorBookNode, L"Unspecified", (long&)m_bColorUnspecified);
  1456. long color=m_Color.color();
  1457. SetAttributeValue(pColorBookNode, L"Color",color);
  1458. LPWSTR pColorName = (LPWSTR)m_Color.colorName();
  1459. if (pColorName)
  1460. {
  1461. // \TrueColor\ColorName
  1462. if(!GetChildNode(pColorNode,L"ColorName",&pColorBookNode))
  1463. AddChildNode(pColorNode, L"ColorName", MSXML::NODE_ELEMENT, &pColorBookNode);
  1464. SetAttributeValue(pColorBookNode,L"Color",pColorName);
  1465. }
  1466. LPWSTR pBookName = (LPWSTR)m_Color.bookName();
  1467. if(pBookName)
  1468. {
  1469. // \TrueColor\ColorBook
  1470. if(!GetChildNode(pColorNode,L"ColorBook",&pColorBookNode))
  1471. AddChildNode(pColorNode, L"ColorBook",MSXML::NODE_ELEMENT, &pColorBookNode);
  1472. SetAttributeValue(pColorBookNode,L"Color",pBookName);
  1473. }
  1474. return TRUE;
  1475. }
  1476. // Set the unspecified state for the Layer control.
  1477. if(dispLayer==index)
  1478. SetAttributeValue(pNode, L"Unspecified", (long)m_bLayerUnspecified);
  1479. return SetAttributeValue(pNode,L"PropertyValue",vValue); // Set the value in the XML file through the VARIANT.
  1480. }
  1481. BOOL SetAttributeValue(MSXML::IXMLDOMNode* pNode,
  1482. LPCWSTR pszAttName,
  1483. long lValue)
  1484. {
  1485. MSXML::IXMLDOMElementPtr pElement = pNode;
  1486. if (pNode == NULL || pElement == NULL || pszAttName == NULL)
  1487. return FALSE;
  1488. CComVariant var(lValue);
  1489. HRESULT hr = pElement->setAttribute(pszAttName, var);
  1490. return SUCCEEDED(hr);
  1491. }
  1492. BOOL SetAttributeValue(MSXML::IXMLDOMNode *pNode,
  1493. LPCWSTR pszAttName,
  1494. VARIANT& var)
  1495. {
  1496. MSXML::IXMLDOMElementPtr pElement = pNode;
  1497. if (pNode == NULL || pElement == NULL || pszAttName == NULL)
  1498. return FALSE;
  1499. HRESULT hr = pElement->setAttribute(pszAttName, &var);
  1500. return SUCCEEDED(hr);
  1501. }
  1502. BOOL SetAttributeValue(MSXML::IXMLDOMNode* pNode,
  1503. LPCWSTR pszAttName,
  1504. LPWSTR pszValue)
  1505. {
  1506. MSXML::IXMLDOMElementPtr pElement = pNode;
  1507. if (pNode == NULL || pElement == NULL || pszAttName == NULL)
  1508. return FALSE;
  1509. CComVariant var(pszValue);
  1510. HRESULT hr = pElement->setAttribute(pszAttName, var);
  1511. return SUCCEEDED(hr);
  1512. }
  1513. BOOL RemoveChildren(MSXML::IXMLDOMNode* pNode)
  1514. {
  1515. try {
  1516. if (pNode == NULL)
  1517. return FALSE;
  1518. MSXML::IXMLDOMNodeListPtr pChildren;
  1519. HRESULT hr = pNode->get_childNodes(&pChildren);
  1520. if ( FAILED(hr) || (pChildren == NULL))
  1521. return FALSE;
  1522. MSXML::IXMLDOMNodePtr pChildNode = pChildren->nextNode();
  1523. for (; pChildNode != NULL; pChildNode = pChildren->nextNode()){
  1524. MSXML::IXMLDOMNodePtr pRemove = pNode->removeChild(pChildNode);
  1525. // Release it
  1526. pRemove = NULL;
  1527. }
  1528. } catch (_com_error &e) {
  1529. SetLastError(e.Error());
  1530. return FALSE;
  1531. } catch(...) {
  1532. return FALSE;
  1533. }
  1534. return TRUE;
  1535. }
  1536. // ******************************************************
  1537. // Catalog, Palette and Tool creation helper functions...
  1538. AcTcPalette *CreatePaletteATC(AcTcCatalog *pCatalog,LPWSTR szPaletteName)
  1539. {
  1540. GUID guid;
  1541. // Create a Palette...
  1542. if(!SUCCEEDED(CoCreateGuid(&guid)))
  1543. return NULL;
  1544. AcTcPalette *pPalette = new AcTcPalette;
  1545. try
  1546. {
  1547. if(!pPalette->SetID(&guid))
  1548. throw 0;
  1549. if(!pPalette->SetName(szPaletteName))
  1550. throw 0;
  1551. if(-1 == pCatalog->AddChild(pPalette))
  1552. throw 0;
  1553. }
  1554. catch (int)
  1555. {
  1556. delete pPalette;
  1557. return NULL;
  1558. }
  1559. try
  1560. {
  1561. if(!pCatalog->SetToolTipText(szPaletteName))
  1562. throw 0;
  1563. if(!pCatalog->SetDescription(szPaletteName))
  1564. throw 0;
  1565. if(!AcTcGetManager()->SaveCatalogs())
  1566. throw 0;
  1567. }
  1568. catch(int)
  1569. {
  1570. pCatalog->DeleteChild(pPalette);
  1571. return NULL;
  1572. }
  1573. return pPalette;
  1574. }
  1575. AcTcTool *CreateToolATC(AcTcPackage *pPalette, LPCWSTR szToolNameOverride=NULL,
  1576. LPCWSTR szToolImageOverride=NULL,
  1577. BOOL bImageFile=FALSE)
  1578. {
  1579. GUID guid;
  1580. if(!SUCCEEDED(CoCreateGuid(&guid)))
  1581. return NULL;
  1582. // Add a tool to the palette.
  1583. AcTcTool* pTool = new AcTcTool();
  1584. try
  1585. {
  1586. if(!pTool->SetID(&guid))
  1587. throw 0;
  1588. if(!pTool->SetStockToolID(pclsid))
  1589. throw 0;
  1590. // Attach the tool icon to the tool...
  1591. AcTcImage image;
  1592. HBITMAP hBitmap=NULL;
  1593. if(szToolImageOverride)
  1594. {
  1595. if(bImageFile)
  1596. hBitmap=(HBITMAP)::LoadImage(
  1597. NULL, szToolImageOverride, IMAGE_BITMAP,
  1598. 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
  1599. else
  1600. hBitmap=::LoadBitmap(_AtlBaseModule.GetResourceInstance(),szToolImageOverride);
  1601. }
  1602. else
  1603. hBitmap=::LoadBitmap(_AtlBaseModule.GetResourceInstance(),szToolImage);
  1604. image.Load(hBitmap);
  1605. AcTcImageList *pList=pTool->GetImageList();
  1606. if(!pList)
  1607. throw 0;
  1608. pList->Add(&image);
  1609. if(szToolNameOverride)
  1610. {
  1611. if(!pTool->SetName(szToolNameOverride))
  1612. throw 0;
  1613. if(!pTool->SetToolTipText(szToolNameOverride))
  1614. throw 0;
  1615. if(!pTool->SetDescription(szToolNameOverride))
  1616. throw 0;
  1617. }
  1618. else
  1619. {
  1620. if(!pTool->SetName(szToolName))
  1621. throw 0;
  1622. if(!pTool->SetToolTipText(szToolName))
  1623. throw 0;
  1624. if(!pTool->SetDescription(szToolName))
  1625. throw 0;
  1626. }
  1627. if(!pTool->SetToolType(AcTc::kToolNormal))
  1628. throw 0;
  1629. // Coerce the tool to persist itself (via Save())
  1630. IUnknown *pUnk=NULL;
  1631. MSXML::IXMLDOMNode* pToolData;
  1632. if(!pTool->GetToolData((IUnknown**)&pToolData))
  1633. throw 0;
  1634. if(!SUCCEEDED(GetPropertyTypeInfo()))
  1635. throw 0;
  1636. if(!SUCCEEDED(Save(pToolData)))
  1637. throw 0;
  1638. if(-1 == pPalette->AddChild(pTool))
  1639. throw 0;
  1640. }
  1641. catch(int)
  1642. {
  1643. delete pTool;
  1644. return NULL;
  1645. }
  1646. try
  1647. {
  1648. if(!AcTcGetManager()->SaveCatalogs())
  1649. throw 0;
  1650. if(!AcTcGetManager()->SaveCatalogs(AcTc::kShapeCatalog))// Save in case pPalette is a shape package.
  1651. throw 0;
  1652. }
  1653. catch(int)
  1654. {
  1655. pPalette->DeleteChild(pTool);
  1656. return NULL;
  1657. }
  1658. return pTool;
  1659. }
  1660. AcTcTool *CreateFlyoutToolATC(AcTcPackage *pPalette, AcTcPackage *pShapePackage, LPCWSTR szToolNameOverride=NULL)
  1661. {
  1662. GUID toolGUID;
  1663. // Add a tool to the palette.
  1664. AcTcTool* pTool = new AcTcTool();
  1665. try
  1666. {
  1667. if(!SUCCEEDED(CoCreateGuid(&toolGUID)))
  1668. throw 0;
  1669. if(!pTool->SetID(&toolGUID))
  1670. throw 0;
  1671. if(!pTool->SetStockToolID(pclsid))
  1672. throw 0;
  1673. if(szToolNameOverride)
  1674. {
  1675. if(!pTool->SetName(szToolNameOverride))
  1676. throw 0;
  1677. if(!pTool->SetToolTipText(szToolNameOverride))
  1678. throw 0;
  1679. if(!pTool->SetDescription(szToolNameOverride))
  1680. throw 0;
  1681. }
  1682. else
  1683. {
  1684. if(!pTool->SetName(szToolName))
  1685. throw 0;
  1686. if(!pTool->SetToolTipText(szToolName))
  1687. throw 0;
  1688. if(!pTool->SetDescription(szToolName))
  1689. throw 0;
  1690. }
  1691. if(!pTool->SetToolType(AcTc::kToolFlyout))
  1692. throw 0;
  1693. if(!pTool->EnableFlyout(TRUE))
  1694. throw 0;
  1695. if(!pTool->SetShapePackage(pShapePackage))
  1696. throw 0;
  1697. // Coerce the tool to persist itself (via Save()) with the values set witin the New() override.
  1698. IUnknown *pUnk=NULL;
  1699. MSXML::IXMLDOMNode* pToolData;
  1700. if(!pTool->GetToolData((IUnknown**)&pToolData))
  1701. throw 0;
  1702. if(!SUCCEEDED(GetPropertyTypeInfo()))
  1703. throw 0;
  1704. if(!SUCCEEDED(Save(pToolData)))
  1705. throw 0;
  1706. if(-1 == pPalette->AddChild(pTool))
  1707. throw 0;
  1708. }
  1709. catch(int)
  1710. {
  1711. delete pTool;
  1712. return NULL;
  1713. }
  1714. // APIs Exist to specify programatically which tools appear in the flyout list. Here is a commented example
  1715. // (This snippet simply adds all the tools in the shape package to the active list):
  1716. /*
  1717. AcTcTool *shapeToolsArray[32];
  1718. for(int i=0;i<(pShapePackage->GetChildCount() )&& i<32;i++)
  1719. shapeToolsArray[i]=(AcTcTool*)pShapePackage->GetChild(i);
  1720. bResult=pTool->SetActiveShapes((AcTcCatalogItem**)shapeToolsArray,pShapePackage->GetChildCount());
  1721. // We must now add the 'ActiveShapes' entries into the CustomData ATC section for the shape package with each tool's ID that we select.
  1722. CComPtr<IUnknown> pCustomDataUnk;
  1723. MSXML::IXMLDOMNodePtr pChild;
  1724. if( pShapePackage->GetCustomData(&pCustomDataUnk) )
  1725. {
  1726. CComQIPtr<MSXML::IXMLDOMNode> pCustomDataNode =pCustomDataUnk;
  1727. MSXML::IXMLDOMNodePtr pActiveShape;
  1728. //If the active shapes does not exist create one
  1729. if(!GetChildNode(pCustomDataNode,L"ActiveShapes",&pActiveShape))
  1730. AddChildNode(pCustomDataNode,L"ActiveShapes",MSXML::NODE_ELEMENT,&pActiveShape);
  1731. for(int i=0;i<pShapePackage->GetChildCount();i++)
  1732. {
  1733. GUID shapeGUID;
  1734. pShapePackage->GetChild(i)->GetID(&shapeGUID);
  1735. CComVariant varGUID(shapeGUID);
  1736. AddChildNode(pActiveShape,L"Shape",MSXML::NODE_ELEMENT,&pChild);
  1737. SetAttributeValue(pChild,L"idValue",varGUID);
  1738. }
  1739. }
  1740. */
  1741. try
  1742. {
  1743. if(!AcTcGetManager()->SaveCatalogs())
  1744. throw 0;
  1745. if(!AcTcGetManager()->SaveCatalogs(AcTc::kShapeCatalog))
  1746. throw 0;
  1747. }
  1748. catch(int)
  1749. {
  1750. pPalette->DeleteChild(pTool);
  1751. return NULL;
  1752. }
  1753. return pTool;
  1754. }
  1755. AcTcTool *CreateCommandToolATC(AcTcPackage *pPalette,LPWSTR szToolName,LPCWSTR szBitmapName, LPWSTR macroString)
  1756. {
  1757. // Add a basic COMMAND tool to the catalog to demonstrate how to create generic tools
  1758. // to run Acad commands. Note, this does not require a COM object to use.
  1759. GUID guid;
  1760. BOOL bResult;
  1761. AcTcTool *pTool = new AcTcTool();
  1762. try
  1763. {
  1764. if(!SUCCEEDED(CoCreateGuid(&guid)))
  1765. throw 0;
  1766. if(!pTool->SetID(&guid))
  1767. throw 0;
  1768. const GUID GenericStockToolId = {0x2ae7120b,0xcee4,0x47a5,{0x9b,0x50,0xef,0x9f,0x3a,0xde,0x24,0xac}};
  1769. if(!pTool->SetStockToolID(&GenericStockToolId))
  1770. throw 0;
  1771. if(!pTool->SetName(szToolName))
  1772. throw 0;
  1773. // Attach a separate tool icon to this tool.
  1774. AcTcImage image;
  1775. AcTcImageList *pList=pTool->GetImageList();
  1776. if(!pList)
  1777. throw 0;
  1778. HBITMAP hBitmap=::LoadBitmap(_AtlBaseModule.GetResourceInstance(),szBitmapName);
  1779. bResult=image.Load(hBitmap);
  1780. pList->Add(&image);
  1781. // Now add the entry to represents the string passed to the commandline when this tool is run.
  1782. CComPtr<IUnknown>pToolDataUnk;
  1783. MSXML::IXMLDOMNodePtr pToolData;
  1784. if(pTool->GetToolData(&pToolDataUnk))
  1785. {
  1786. CComQIPtr<MSXML::IXMLDOMNode> pToolData=pToolDataUnk;
  1787. RemoveChildren(pToolData);
  1788. MSXML::IXMLDOMNodePtr pNode,pNodeText;
  1789. if(TRUE == AddChildNode(pToolData, L"Macro", MSXML::NODE_ELEMENT, &pNode))
  1790. if(TRUE == AddChildNode(pNode, L"", MSXML::NODE_CDATA_SECTION, &pNodeText))
  1791. pNodeText->put_text(CComBSTR(macroString));
  1792. }
  1793. else
  1794. throw 0;
  1795. if(-1 == pPalette->AddChild(pTool))
  1796. throw 0;
  1797. }
  1798. catch(int)
  1799. {
  1800. delete pTool;
  1801. return NULL;
  1802. }
  1803. try
  1804. {
  1805. if(!AcTcGetManager()->SaveCatalogs())// AutoCAD will create the correct ATC files within the roamable profile folder.
  1806. throw 0;
  1807. if(!AcTcGetManager()->SaveCatalogs(AcTc::kShapeCatalog))
  1808. throw 0;
  1809. }
  1810. catch(int)
  1811. {
  1812. pPalette->DeleteChild(pTool);
  1813. return NULL;
  1814. }
  1815. return pTool;
  1816. }
  1817. AcTcCatalog *CreateStockToolATC(LPWSTR szCatalogName)
  1818. {
  1819. // Set the module handle so we can use the resources within this ARX for the tool icons.
  1820. CAcModuleResourceOverride resourceOverride;
  1821. GUID guid;
  1822. // Create the stock tool catalog entry:
  1823. AcTcStockTool *pStockTool=new AcTcStockTool;
  1824. AcTcCatalog *pStockToolCatalog=new AcTcCatalog;
  1825. try
  1826. {
  1827. if(!pStockTool->SetID(pclsid))
  1828. throw 0;
  1829. if(!pStockTool->SetComClassID(*pclsid))
  1830. throw 0;
  1831. // Set the module file name for the Stock Tool's COM interface object: modulePath set in initialize()...
  1832. WCHAR modulePath[MAX_PATH];
  1833. HINSTANCE hInst=_AtlBaseModule.GetResourceInstance();
  1834. HMODULE moduleHandle=hInst;
  1835. if(!moduleHandle)
  1836. throw 0;
  1837. GetModuleFileName(hInst,modulePath,MAX_PATH);
  1838. if(!pStockTool->SetModuleFileName(modulePath))
  1839. throw 0;
  1840. // Allow the framework to handle the StockTool now...
  1841. if(-1 == pStockToolCatalog->AddChild(pStockTool))
  1842. throw 0;
  1843. else {
  1844. // the catalog now owns this object and will delete it when
  1845. // the catalog is deleted. So, we set pStockTool to nullptr
  1846. // to prevent it being double deleted in the catch(int)s
  1847. // below.
  1848. //
  1849. pStockTool = nullptr;
  1850. }
  1851. if(-1 == AcTcGetManager()->AddStockToolCatalog(pStockToolCatalog))
  1852. throw 0;
  1853. }
  1854. catch(int)
  1855. {
  1856. delete pStockToolCatalog;
  1857. delete pStockTool;
  1858. return NULL;
  1859. }
  1860. AcTcCatalog *pCatalog=new AcTcCatalog;
  1861. try
  1862. {
  1863. // Create the tool catalog entry.
  1864. if(!SUCCEEDED(CoCreateGuid(&guid)))
  1865. throw 0;
  1866. if(!pCatalog->SetID(&guid))
  1867. throw 0;
  1868. if(!pCatalog->SetName(szCatalogName))
  1869. throw 0;
  1870. if(-1 ==AcTcGetManager()->AddCatalog(pCatalog))
  1871. throw 0;
  1872. if(!AcTcGetManager()->SaveCatalogs())
  1873. throw 0;
  1874. if(!AcTcGetManager()->SaveCatalogs(AcTc::kStockToolCatalog))
  1875. throw 0;
  1876. }
  1877. catch(int)
  1878. {
  1879. delete pStockToolCatalog;
  1880. delete pCatalog;
  1881. return NULL;
  1882. }
  1883. return pCatalog;
  1884. }
  1885. AcTcPackage *CreateShapeCatalogATC(LPWSTR szShapeName)
  1886. {
  1887. AcTcManager *pManager = AcTcGetManager();
  1888. AcTcCatalog *pShapesCatalog = NULL;
  1889. if(pManager)
  1890. {
  1891. pShapesCatalog = (AcTcCatalog *)pManager->GetShapeCatalog();
  1892. if(!pShapesCatalog)
  1893. return NULL;
  1894. }
  1895. else
  1896. return NULL;
  1897. //if the package does not exist create one new package
  1898. AcTcPackage *pPackage=GetCustomShapePackage(pShapesCatalog,szShapeName);
  1899. if (NULL==pPackage)
  1900. {
  1901. pPackage = new AcTcPackage;
  1902. try
  1903. {
  1904. if(!pPackage->SetName(szShapeName))
  1905. throw 0;
  1906. GUID shapeGuid;
  1907. if(!SUCCEEDED(CoCreateGuid(&shapeGuid)))
  1908. throw 0;
  1909. if(!pPackage->SetID(&shapeGuid))
  1910. throw 0;
  1911. if(-1 == pShapesCatalog->AddChild(pPackage))
  1912. throw 0;
  1913. }
  1914. catch(int)
  1915. {
  1916. delete pPackage;
  1917. return NULL;
  1918. }
  1919. }
  1920. if(!AcTcGetManager()->SaveCatalogs(AcTc::kShapeCatalog))
  1921. {
  1922. pShapesCatalog->DeleteChild(pPackage);
  1923. return NULL;
  1924. }
  1925. return pPackage;
  1926. }
  1927. IAcadToolProperties* GetThisToolsProperties()
  1928. {
  1929. AcadToolImpl<TT,T,pclsid,szToolName,szToolImage>* pThisTool=(AcadToolImpl<TT,T,pclsid,szToolName,szToolImage>*)pAcadToolImpl;
  1930. CComQIPtr<IAcadTool> pAcadTool(pThisTool);
  1931. if (!pAcadTool)
  1932. return NULL;
  1933. CComPtr<IUnknown> pUnkToolProp;
  1934. HRESULT hr = pAcadTool->GetToolProperties(&pUnkToolProp);
  1935. if (FAILED(hr))
  1936. return NULL;
  1937. CComQIPtr<IAcadToolProperties> pToolProp(pUnkToolProp);
  1938. if(!pToolProp)
  1939. return NULL;
  1940. return pToolProp;
  1941. }
  1942. AcTcPackage* GetCustomShapePackage(AcTcCatalog *pCatalog,
  1943. LPCWSTR szPackageName)
  1944. {
  1945. if(!pCatalog)
  1946. return NULL;
  1947. AcTcPackage *pPackage = NULL;
  1948. for(int i=0;i<pCatalog->GetChildCount();i++)
  1949. {
  1950. pPackage=(AcTcPackage *)pCatalog->GetChild(i);
  1951. if(pPackage)
  1952. {
  1953. WCHAR szPackageNameEnum[128];
  1954. pPackage->GetName(szPackageNameEnum,128);
  1955. if(!wcscmp(szPackageName,szPackageNameEnum))
  1956. return pPackage;
  1957. }
  1958. }
  1959. return NULL;
  1960. }
  1961. AcTcPackage* GetCustomShapePackage(AcTcCatalog *pCatalog,
  1962. GUID szPackageID)
  1963. {
  1964. if(!pCatalog)
  1965. return NULL;
  1966. AcTcPackage *pPackage = NULL;
  1967. for(int i=0;i<pCatalog->GetChildCount();i++)
  1968. {
  1969. pPackage=(AcTcPackage *)pCatalog->GetChild(i);
  1970. if(pPackage)
  1971. {
  1972. GUID szPackageIdEnum;
  1973. pPackage->GetID(szPackageIdEnum);
  1974. if(IsEqualGuid(szPackageId,szPackageIdEnum))
  1975. return pPackage;
  1976. }
  1977. }
  1978. return NULL;
  1979. }
  1980. };