tag:blogger.com,1999:blog-104259452008-05-10T17:12:22.502-03:00ObjectARX & DummiesFernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comBlogger71125tag:blogger.com,1999:blog-10425945.post-18961566255897869722008-04-29T16:39:00.001-03:002008-04-29T16:49:06.975-03:00AU2008 VotingHello,<br /><br />This year, AU (Autodesk University) classes will be rated by vote.<br />I have sent 3 classes under the <strong>Customization &amp; Programming</strong> Power Track.<br />If you plan to attend AU2008 and would like to see one of my classes please take some time to vote through the following link:<br /><br /><a href="https://www.surveymonkey.com/s.aspx?sm=Yy_2fqK2TzVXoIf7d0TuRulw_3d_3d">AU2008 Voting</a><br /><br />My classes are:<br /><br /><strong><em>1) The Power of ObjectARX® - The Lab – AutoCAD – Level: Advanced<br /><br />2) The Power of ObjectARX® - The Class – AutoCAD – Level: Intermediate<br /><br />3) Creating Your Own Vertical Application Through AutoCAD® OEM – AutoCAD – Level: Intermediate</em></strong><br /><br />Hope these classes are approved and I hope you are able to attend this year!<br />Regards,Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-89337714768851842752008-03-27T09:43:00.000-03:002008-03-27T10:40:26.314-03:00Version ControlHello,<br /><br />Probably you will need or already need some version controlling on your software or on its modules.<br />This is made through the <span style="color:#ff0000;"><strong>VS_VERSION_INFO</strong></span><span style="color:#000000;"> resource inside <strong>C++</strong> projects and through <strong><span style="color:#ff0000;">AssemblyInfo.cs</span></strong> file inside <strong>C#</strong> projects.</span><br /><br />I have found an old but up to date tool (<strong>runs from VS2002 to VS2008</strong>) which allows you to easily manage these version informations. This tool, from <a href="http://www.codeproject.com/script/Membership/Profiles.aspx?mid=820347">Julijan Sribar</a>, is an AddIn which tracks all opened projects and allow you to manage each version information. This tool is provided for free and its source code is also available for download: <a href="http://www.codeproject.com/KB/macros/versioningcontrolledbuild.aspx">Versioning Controlled Build</a><br /><br />Another issue is how to get this information at runtime to display, for instance, this version at an "<strong><em>About</em></strong>" like dialog inside your product. To do that in VC++ we need to read the VS_VERSION_INFO resource and get what we want. There is also another great article <a href="http://www.codeproject.com/KB/cpp/GetLocalVersionInfos.aspx">Retrieving version information from your local application's resource</a>, from <a href="http://www.codeproject.com/script/Membership/Profiles.aspx?mid=553157">luetz</a>,explaining how to do that.<br /><br />Through C# there is no big deal, you can read the version information from AssemblyInfo as follows:<br /><br /><span style="font-family:courier new;color:#3333ff;">System.Reflection.Assembly oAssembly = System.Reflection.Assembly.GetExecutingAssembly(); </span><br /><span style="font-family:courier new;color:#3333ff;">System.Diagnostics.FileVersionInfo oFileVersionInfo = FileVersionInfo.GetVersionInfo(oAssembly.Location) ;</span><br /><span style="font-family:courier new;color:#3333ff;">MessageBox.Show("Version Info", oFileVersionInfo.ProductVersion);</span><br /><br />Hope this help you to keep your file versions organized and updated!<br />Cheers!Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-87225332489555657892008-03-25T00:06:00.000-03:002008-03-25T00:16:42.444-03:00Blog Classes content updateHello,<br /><br />I have updated and fixed some classes sample code that are not UNICODE aware that will not compile inside VS2005 (ObjectARX 2007, 2008 and 2009).<br /><br />Basically, I have changed:<br /><br />- Add <strong><span style="color:#3333ff;">_T()</span></strong> macro to all strings;<br />- Changed strcpy() to <strong><span style="color:#3333ff;">_tcscpy()</span></strong> which is UNICODE aware;<br />- Changed char* to <strong><span style="color:#3333ff;">TCHAR*</span></strong> or to <strong><span style="color:#3333ff;">ACHAR*</span></strong> pointers;<br /><br /><strong><span style="color:#ff0000;">Important</span></strong>: <em>ACHAR is a typedef present inside "AdAChar.h" ObjectARX header. If you are trying to compile for non-UNICODE ObjectARX versions replace ACHAR* by TCHAR* (or char*) and you should get out of compilation errors.</em><br /><br />Cheers!Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-14591080584771149922008-03-19T00:39:00.000-03:002008-03-19T00:43:09.935-03:00VS2005 SamplesHello,<br /><br />I have updated some VS2002 samples to VS2005.<br />There are two new files, ending with "VC8" which are the VS2005 converted solution/projects.<br /><br />You can download these projects from here:<br /><br /><a href="http://files.ofcdesk.com/ThirdParty/files/ObjectARX/VS2005/">VS2005 Samples</a><br /><br />These should compile fine with ObjectARX 2007, 2008 and 2009.<br />Note that if you plan to be 100% compatible with these 3 releases you will need to use the 2007 version of ObjectARX SDK.<br /><br />Cheers!Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-51234786612938737602008-02-13T08:10:00.000-02:002008-02-13T08:22:01.483-02:00AutoCAD 2009Hello,<br /><br />Yesterday, February 12th, <strong>Autodesk</strong> has officially announced its <strong>2009 product line</strong>.<br />Read more about here:<br /><br /><a href="http://www.worldpressdays08.com/pages/page.cfm?action=products&amp;sub1=1">http://www.worldpressdays08.com/pages/page.cfm?action=products&amp;sub1=1</a><br /><br /><strong>AutoCAD 2009</strong> (codename <strong>Raptor</strong>) will implement several new features like these major ones:<br /><br />- View Cube (easy 3D view);<br />- Steering Wheel (easy 3D navigation);<br />- Office like Ribbon interface;<br />- Menu Browser;<br />- Action recorder;<br />- Geographic location;<br />- Modeless Layer manager (works now like a toolpallete);<br /><br />There are much more and you may find these detailed features soon at Autodesk website.<br /><br />My friend, Shaan Hurley, have a more detailed list at his Blog:<br /><a href="http://autodesk.blogs.com/between_the_lines/2008/02/the-2009-produc.html">http://autodesk.blogs.com/between_the_lines/2008/02/the-2009-produc.html</a><br /><br />Regarding to programming aspects, <strong>AutoCAD 2009</strong> is backward compatible with 2007 and 2008. This way an application compiled with <strong>ObjectARX 2007</strong> will be able to run inside all these 3 versions.<br /><br />Actually, AutoCAD 2009 was built using <strong>VS2005 Service Pack 1</strong> but if you plan to keep your project backward compatible it is recommended to <strong>use VS2005 without Service Pack</strong>.<br /><br />Probably the next version of AutoCAD will break the binary compatibility with 2007,2008 and 2009 and will use <strong>VS2008</strong>. Autodesk seems to be aligned with Microsoft Visual Studio evolution and will try to make only binary compatibility break on every 3 releases.<br /><br />Cheers!Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-5178082910388274422008-01-14T23:34:00.000-02:002008-01-14T23:37:04.365-02:00AutoCAD GUI testsHello,<br /><br />I would like to introduce a new Blog this year. It will be about AutoCAD Applications GUI tests. The idea behind this Blog is to discuss methods and tools that could be used to test all types of AutoCAD applications against AutoCAD interface to reach a better test experience approaching the real user environment.<br /><br />If you are interested on discuss this I would like to invite you to visit my new Blog at:<br /><br /><a href="http://acadguitest.blogspot.com/">http://acadguitest.blogspot.com/</a><br /><br />Best regards,Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-51113543395249910782007-12-04T08:51:00.000-02:002007-12-04T08:59:56.235-02:00AU2007 was huge!Hello,<br /><br />AU2007 was really huge. The initial estimations are around 10.000 attendees.<br />What can we expect for AU2008 ? 15.000 ???<br /><br />I will post on the next days my two courses materials but as one of my classes was recorded here is the link for the presentation (you will need to register to AU Online to be able to see the video):<br /><br /><a href="http://autodesk.mediasite.com/autodesk/autologinform/?peid=7a7838a8-1bc6-4d68-8b03-3158b14c023f">http://autodesk.mediasite.com/autodesk/autologinform/?peid=7a7838a8-1bc6-4d68-8b03-3158b14c023f</a><br /><br />Best Regards.Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-36654799363629883722007-10-22T23:52:00.000-02:002007-10-22T23:53:41.710-02:00AutoCAD next version ?Hello,<br /><br />We are approaching the end of 2007 and if Autodesk keep its policy with annual releases of AutoCAD we will probably have soon the next release which would be 2009.<br /><br />I would like to ask you what do you expect as new features of this upcoming release. Please add your comments to this post and soon we will see what's new from the next AutoCAD.<br /><br />Meanwhile, cross your fingers and wait for the official announcement.<br /><br />Best regards,Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-73679721452133962872007-08-28T18:03:00.000-03:002007-08-28T18:12:06.909-03:00AU2007Hello,<br /><br />For those who will have the opportunity to participate on this year's Autodesk University at Las Vegas I would like to suggest my two classes:<br /><br /><a><strong><span style="color:#000099;">CP401-2</span></strong></a><br /><span style="color:#000099;">The Power of ObjectARX®</span><br /><br /><a><strong><span style="color:#000099;">CP405-1</span></strong></a><br /><span style="color:#000099;">Creating Your Own Vertical Application Through AutoCAD® OEM<br /></span><br />Registration:<br /><a href="http://au.autodesk.com/2007/register/">http://au.autodesk.com/2007/register/</a><br /><br />Hope to meet you in Vegas this year!<br />Regards,<br />Fernando.Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-89899156173272761602007-05-30T10:42:00.000-03:002007-05-30T10:45:24.809-03:00AUGI BrazilHello,<br /><br />I would like to invite all Portuguese speaking world to visit the brand new <strong>AUGI Brasil</strong> website.<br /><br /><strong>AUGI Br</strong> was officially launched today (<strong>30/05/2007</strong>) which is the same day <strong>AutoCAD 2008</strong> is being officially announced here in Brazil.<br /><br /><a href="http://www.augibr.com">http://www.augibr.com</a><br /><br />Congratulations!<br /><br />Fernando.Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-42547262037361622582007-03-06T10:57:00.000-03:002007-03-06T11:01:26.575-03:00Debug AutoCAD 2007 from VS2005 on Windows VistaHello,<br /><br />After some research I have tried to <strong>Debug AutoCAD 2007</strong> again but this time starting the Visual Studio 2005 with "<strong>Run as Administrator</strong>" feature. Now I'm able to Debug AutoCAD 2007 from <strong>VS2005</strong>.<br /><br />More tips to come as soon as I figure out them... :)<br /><br />If you have discovered something else, please share with this Blog!<br /><br />Cheers!Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-39713934219058811912007-03-06T08:25:00.000-03:002007-03-06T10:43:43.010-03:00ObjectARX & Windows VistaHello,<br /><br />I have migrated to <strong>Windows Vista Ultimate</strong> and would like to share some problems / workaround I have made so far.<br /><br />The first issue you will face is related to <strong>Visual Studio</strong>. Windows Vista supports partially (<a href="http://go.microsoft.com/?linkid=5728666">VS2005</a>) and do not natively support previous versions. As I have several projects running on <strong>AutoCAD 2005 and 2006</strong> (they require <strong>VS2002</strong> to compile) I need a way to run then from inside Windows Vista. I have then remembered the good old <strong>Microsoft Virtual PC</strong> which is now free and has a new release 2007.<br /><br />I have downloaded and installed (<a href="http://www.microsoft.com/windows/products/winfamily/virtualpc/default.mspx">Virtual PC 2007</a>). After that I have then created a new virtual machine with <strong>Windows XP PRO SP2</strong> and then installed <strong>AutoCAD 2005</strong>, <strong>2006</strong> and <strong>VS2002</strong>. Of course my machine helps a lot because it runs an <strong>Intel Core 2 Duo</strong> processor and has <strong>2Gb RAM</strong>. The <strong>Virtual PC 2007</strong> runs well but it causes some erratic mouse moves and some small locks. Unsatisfied with that I then go to the Google and find out a great tip about how to improve <strong>Virtual PC 2007</strong> performance adding a new parameter to its (<a href="http://codebetter.com/blogs/jeff.lynch/archive/2006/11/28/VPC-2007-Beta_3A00_-Centrino-915-Chipset-Issues.aspx">XML configuration file</a>). After changed this it runs fast and without any erractic mouse moves. (Thanks to <strong><em>Jeff Lynch</em></strong>)<br /><br />Regarding to <strong>AutoCAD 2007</strong> and Windows Vista at the beginning I was unable to run it. As I'm new to Vista I have found a command when you right click on the application "<strong>Run as Administrator</strong>". This did the trick and now I'm able to open AutoCAD but I'm still unable to <strong>Debug</strong> or <strong>Attach to Process</strong> on Vista. This is not the proper solution once Autodesk already told us about some issues related with Vista and will release soon a Service Pack to <strong>AutoCAD 2007</strong> and <strong>LT 2007</strong>:<br /><br /><a href="http://autodesk.blogs.com/between_the_lines/2007/02/autocad_and_aut.html">AutoCAD 2007 and LT 2007</a><br /><br /><strong>AutoCAD 2008</strong>: It will be released soon and some good information about its integration with Windows Vista can be found here:<br /><br /><a href="http://autodesk.blogs.com/between_the_lines/2007/03/autocad_2008_wi.html">AutoCAD 2008</a><br /><br />(Thanks to <strong><em>Shaan Hurley</em></strong>)<br /><br />That's it for now.<br />Cheers!Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-77226235385054716842007-02-13T23:56:00.000-02:002007-02-14T00:00:50.596-02:00AutoCAD 2008 is coming...Hello,<br /><br />Autodesk has announced the upcoming AutoCAD 2008 version. It will be released on both 32-bit and 64-bit versions. There is no change on dwg file format. Further it will officially support Windows Vista.<br /><br />More information will be announced soon from Autodesk. Stay tuned at:<br /><br /><a href="http://www.autodesk.com">http://www.autodesk.com</a><br /><a href="http://through-the-interface.typepad.com/">http://through-the-interface.typepad.com/</a><br /><a href="http://autodesk.blogs.com/between_the_lines/">http://autodesk.blogs.com/between_the_lines/</a><br /><br />Cheers!Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-1168648402197229432007-01-12T22:33:00.001-02:002007-01-13T00:49:21.238-02:00Exercise2 - Step6<strong><span style="font-family:Verdana;font-size:85%;">Creating a Custom Entity – Exercise 2 – Step 6</span></strong><br /><strong><span style="font-family:Verdana;font-size:85%;"></span></strong><br /><span style="font-family:Verdana;font-size:85%;">On this step we will implement a pretty nice feature. Imagine you would like to add a </span><strong><span style="font-family:Verdana;font-size:85%;">hatch filling </span></strong><span style="font-family:Verdana;font-size:85%;">to your custom entity. We can take advantage of ObjectARX </span><strong><span style="font-family:Verdana;font-size:85%;">embedded object </span></strong><span style="font-family:Verdana;font-size:85%;">feature to implement this. There is a class called </span><strong><span style="font-family:Verdana;font-size:85%;">AcDbHatch </span></strong><span style="font-family:Verdana;font-size:85%;">which represents the AutoCAD hatch entity. This class can be used as an embedded object and we can use its </span><strong><span style="font-family:Verdana;font-size:85%;">worldDraw() </span></strong><span style="font-family:Verdana;font-size:85%;">method to draw our own hatch pattern. The first thing you need to do is to add an </span><strong><span style="font-family:Verdana;font-size:85%;">AcDbHatch </span></strong><span style="font-family:Verdana;font-size:85%;">member to our custom entity’s class. We will also declare the </span><strong><span style="font-family:Verdana;font-size:85%;">SetupHatch() </span></strong><span style="font-family:Verdana;font-size:85%;">method to setup the hatch properties. To do that, open the </span><strong><span style="font-family:Verdana;font-size:85%;">AuPolyline.h </span></strong><span style="font-family:Verdana;font-size:85%;">file, and place the following lines at the end of class declaration:</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">protected:</span><br /><span style="font-family:Lucida Console;font-size:85%;">AcDbHatch m_Hatch;</span><br /><span style="font-family:Lucida Console;font-size:85%;"></span><br /><span style="font-family:Lucida Console;font-size:85%;">public:</span><br /><span style="font-family:Lucida Console;font-size:85%;">void SetupHatch();</span><br /><span style="font-family:Verdana;font-size:85%;"></span></span><br /><span style="font-family:Verdana;font-size:85%;">Further, we will need to add 3 more methods to our entity to handle modifications. The first method will handle all </span><strong><span style="font-family:Verdana;font-size:85%;">graphic transformations</span></strong><span style="font-family:Verdana;font-size:85%;">. The 2 remaining methods will handle the </span><strong><span style="font-family:Verdana;font-size:85%;">STRETCH </span></strong><span style="font-family:Verdana;font-size:85%;">command:</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">public:</span><br /><span style="font-family:Lucida Console;font-size:85%;">virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d & xform);</span><br /><span style="font-family:Lucida Console;font-size:85%;">virtual Acad::ErrorStatus getStretchPoints(</span><br /><span style="font-family:Lucida Console;font-size:85%;">AcGePoint3dArray & stretchPoints) const;</span><br /><span style="font-family:Lucida Console;font-size:85%;">virtual Acad::ErrorStatus moveStretchPointsAt(</span><br /><span style="font-family:Lucida Console;font-size:85%;">const AcDbIntArray & indices, const AcGeVector3d &amp; offset);</span></span><br /><span style="font-family:Lucida Console;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">Our hatch object needs to be configured. To do this we will place, </span><u><span style="font-family:Verdana;font-size:85%;">inside the custom entity’s constructor </span></u><span style="font-family:Verdana;font-size:85%;">located at </span><strong><span style="font-family:Verdana;font-size:85%;">AuPolyline.cpp </span></strong><span style="font-family:Verdana;font-size:85%;">file, the following code (note that this configuration needs to be done only once so the constructor is the better place to put it):</span><br /><br /><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AuPolyline::AuPolyline () : AcDbPolyline ()<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.setNormal(AcGeVector3d::kZAxis);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.setElevation(this-&gt;elevation());<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.setAssociative(true);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.setPatternScale(1.0);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.setPatternAngle(45.0);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.setHatchStyle(AcDbHatch::kNormal);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.setPattern(AcDbHatch::kPreDefined,_T("LINE"));<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}</span></p><span style="font-family:Verdana;font-size:85%;">This configuration will set the hatch </span><strong><span style="font-family:Verdana;font-size:85%;">pattern</span></strong><span style="font-family:Verdana;font-size:85%;">, </span><strong><span style="font-family:Verdana;font-size:85%;">normal </span></strong><span style="font-family:Verdana;font-size:85%;">vector, </span><strong><span style="font-family:Verdana;font-size:85%;">elevation</span></strong><span style="font-family:Verdana;font-size:85%;">, </span><strong><span style="font-family:Verdana;font-size:85%;">scale</span></strong><span style="font-family:Verdana;font-size:85%;">, </span><strong><span style="font-family:Verdana;font-size:85%;">angle </span></strong><span style="font-family:Verdana;font-size:85%;">and </span><strong><span style="font-family:Verdana;font-size:85%;">style</span></strong><span style="font-family:Verdana;font-size:85%;">. In this example they are fixed but you may want to create one property for each of these parameters allowing the user to change them at runtime.</span><br /><span style="font-family:Verdana;font-size:85%;">Now we need to add the </span><strong><span style="font-family:Verdana;font-size:85%;">SetupHatch() </span></strong><span style="font-family:Verdana;font-size:85%;">method implementation to build the hatch loop according to our polyline boundary. The code will be as follows:</span><br /><br /><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">void AuPolyline::SetupHatch()<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">assertWriteEnabled();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Remove previous loop<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">for (int l=0; l&lt;m_Hatch.numLoops(); l++)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.removeLoopAt(l);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Insert the updated loop<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint2dArray vertexPts;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGeDoubleArray vertexBulges;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Collect points and bulges<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">for(int i=0; i&lt;numVerts(); i++) {<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint2d pt2d;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">double bulge = 0.0;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">this-&gt;getPointAt(i,pt2d);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">this-&gt;getBulgeAt(i,bulge);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">vertexPts.append(pt2d);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">vertexBulges.append(bulge);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Close the loop<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">vertexPts.append(vertexPts.first());<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">vertexBulges.append(vertexBulges.first());<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.appendLoop(AcDbHatch::kDefault, vertexPts, vertexBulges);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Refresh hatch<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.evaluateHatch();<br /></span><span style="font-family:Lucida Console;font-size:85%;"><span style="color:#3333ff;">}</span> </span></p><span style="font-family:Verdana;font-size:85%;"></span><span style="font-family:Verdana;font-size:85%;">On lines </span><strong><span style="font-family:Verdana;font-size:85%;">05-06 </span></strong><span style="font-family:Verdana;font-size:85%;">we make sure there is no previous loop inside hatch. At the line range </span><strong><span style="font-family:Verdana;font-size:85%;">11-18 </span></strong><span style="font-family:Verdana;font-size:85%;">we walk through the polyline vertexes and collect its points and bulges (</span><em><span style="font-family:Verdana;font-size:85%;">the bulge is the tangent of 1/4 of the included angle for the arc between the selected vertex and the next vertex</span></em><span style="font-family:Verdana;font-size:85%;">). The collected information will be stored at two dynamic vectors: </span><strong><span style="font-family:Verdana;font-size:85%;">AcGePoint3dArray </span></strong><span style="font-family:Verdana;font-size:85%;">and </span><strong><span style="font-family:Verdana;font-size:85%;">AcGeDoubleArray</span></strong><span style="font-family:Verdana;font-size:85%;">. On lines </span><strong><span style="font-family:Verdana;font-size:85%;">20-21 </span></strong><span style="font-family:Verdana;font-size:85%;">we close the polyline loop to </span><u><span style="font-family:Verdana;font-size:85%;">ensure our hatch boundary is closed</span></u><span style="font-family:Verdana;font-size:85%;">.</span><br /><span style="font-family:Verdana;font-size:85%;">On line </span><strong><span style="font-family:Verdana;font-size:85%;">22 </span></strong><span style="font-family:Verdana;font-size:85%;">we append the arrays to the hatch entity as one loop. The loop can be also a hole into the hatch surface but in this example our loop is </span><strong><span style="font-family:Verdana;font-size:85%;">AcDbHatch::kDefault</span></strong><span style="font-family:Verdana;font-size:85%;">. On line </span><strong><span style="font-family:Verdana;font-size:85%;">24 </span></strong><span style="font-family:Verdana;font-size:85%;">we finish the hatch configuration process by calling the </span><strong><span style="font-family:Verdana;font-size:85%;">evaluateHatch() </span></strong><span style="font-family:Verdana;font-size:85%;">method which will generate the hatch itself.</span><br /><span style="font-family:Verdana;font-size:85%;">We need to call the </span><strong><span style="font-family:Verdana;font-size:85%;">SetupHatch() </span></strong><span style="font-family:Verdana;font-size:85%;">method inside some of our methods. The first place is inside the </span><strong><span style="font-family:Verdana;font-size:85%;">dwgInFields()</span></strong><span style="font-family:Verdana;font-size:85%;">. Place a call to this method at the end of this method as follows:</span><br /><br /><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus AuPolyline::dwgInFields (AcDbDwgFiler *pFiler)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;"><span style="color:#ff0000;"><em><strong>[ some lines were not displayed for code brevity ]</strong></em></span><br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Setup hatch<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">SetupHatch();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">return (pFiler-&gt;filerStatus ()) ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}</span></p><span style="font-family:Verdana;font-size:85%;">Next, we need to place another call inside </span><strong><span style="font-family:Verdana;font-size:85%;">moveGripPointsAt() </span></strong><span style="font-family:Verdana;font-size:85%;">method. When user moves some of the GRIP points we need to </span><u><span style="font-family:Verdana;font-size:85%;">recalculate the hatch boundary</span></u><span style="font-family:Verdana;font-size:85%;">. We need to do this only in cases the selected GRIP is not our center point. The change is made on lines </span><strong><span style="font-family:Verdana;font-size:85%;">15-18 </span></strong><span style="font-family:Verdana;font-size:85%;">as follows:</span><br /><br /><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus AuPolyline::moveGripPointsAt (<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcDbVoidPtrArray &gripAppData,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcGeVector3d &amp;offset, const int bitflags)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">assertWriteEnabled () ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">for (int g=0; g&lt;gripAppData.length(); g++)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Get grip data back and see if it is our 0 Grip<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">int i = (int)gripAppData.at(g);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// If it is our grip, move the entire entity. If not, forward the call<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">if (i == 9999)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">this-&gt;transformBy(offset);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">else<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDbCurve::moveGripPointsAt (gripAppData, offset, bitflags);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">SetupHatch();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">return (Acad::eOk);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}</span></p><span style="font-family:Verdana;font-size:85%;">To make the hatch entity appear as part of our custom entity’s graphics we need to call its </span><strong><span style="font-family:Verdana;font-size:85%;">worldDraw() </span></strong><span style="font-family:Verdana;font-size:85%;">method from inside our entity’s </span><strong><span style="font-family:Verdana;font-size:85%;">worldDraw()</span></strong><span style="font-family:Verdana;font-size:85%;">: </span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><br /><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Adesk::Boolean AuPolyline::worldDraw (AcGiWorldDraw *mode)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;"><span style="color:#ff0000;"><strong><em>[ some lines were not displayed for code brevity ]</em></strong></span><br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// =======================================================<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// HATCH<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.worldDraw(mode);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">//------ Returning Adesk::kFalse here will force viewportDraw() call<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">return (Adesk::kTrue) ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}</span></p><span style="font-family:Verdana;font-size:85%;"></span><span style="font-family:Verdana;font-size:85%;">Finally, we need to implement the code for the </span><u><span style="font-family:Verdana;font-size:85%;">3 new methods </span></u><span style="font-family:Verdana;font-size:85%;">we have added to our custom entity’s class. Open the </span><strong><span style="font-family:Verdana;font-size:85%;">AuPolyline.cpp </span></strong><span style="font-family:Verdana;font-size:85%;">file and add the following methods:</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><br /><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// -------------------------------------------------------------------------<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus AuPolyline::transformBy(const AcGeMatrix3d & xform)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus retCode = AcDbPolyline::transformBy (xform) ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">m_Hatch.transformBy(xform);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">return (retCode) ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// -------------------------------------------------------------------------<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus AuPolyline::getStretchPoints(AcGePoint3dArray & stretchPoints) const<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDbIntArray osnapModes,geomIds;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">return this-&gt;getGripPoints(stretchPoints,osnapModes,geomIds) ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// -------------------------------------------------------------------------<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus AuPolyline::moveStretchPointsAt(<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcDbIntArray & indices,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcGeVector3d &amp; offset)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus ret = AcDbPolyline::moveGripPointsAt (indices, offset);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">SetupHatch();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">return ret;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">} </span></p><span style="font-family:Verdana;font-size:85%;">The first method on lines </span><strong><span style="font-family:Verdana;font-size:85%;">02-07</span></strong><span style="font-family:Verdana;font-size:85%;">, </span><strong><span style="font-family:Verdana;font-size:85%;">transformBy()</span></strong><span style="font-family:Verdana;font-size:85%;">, is responsible for all entity’s graphic transformations such as </span><strong><span style="font-family:Verdana;font-size:85%;">MOVE</span></strong><span style="font-family:Verdana;font-size:85%;">, </span><strong><span style="font-family:Verdana;font-size:85%;">ROTATE</span></strong><span style="font-family:Verdana;font-size:85%;">, </span><strong><span style="font-family:Verdana;font-size:85%;">SCALE</span></strong><span style="font-family:Verdana;font-size:85%;">, etc. First we forward the call to our base class and then apply the same transformation to the hatch. This way it will follow all transformations applied to our AuPolyline. </span><br /><span style="font-family:Verdana;font-size:85%;">The second method on lines </span><strong><span style="font-family:Verdana;font-size:85%;">09-13</span></strong><span style="font-family:Verdana;font-size:85%;">, </span><strong><span style="font-family:Verdana;font-size:85%;">getStretchPoints()</span></strong><span style="font-family:Verdana;font-size:85%;">, is responsible to return the points that are enabled to </span><u><span style="font-family:Verdana;font-size:85%;">stretch the entity</span></u><span style="font-family:Verdana;font-size:85%;">. In this case we would like to add all of our polyline vertexes. This method can reuse the </span><strong><span style="font-family:Verdana;font-size:85%;">getGripPoints() </span></strong><span style="font-family:Verdana;font-size:85%;">method which returns the same points we want.</span><br /><span style="font-family:Verdana;font-size:85%;">The last method on lines </span><strong><span style="font-family:Verdana;font-size:85%;">15-22</span></strong><span style="font-family:Verdana;font-size:85%;">, </span><strong><span style="font-family:Verdana;font-size:85%;">moveStretchPointsAt()</span></strong><span style="font-family:Verdana;font-size:85%;">, is responsible to apply the stretch transformation over the entity. We will also reuse the existing method </span><strong><span style="font-family:Verdana;font-size:85%;">moveGripPointsAt() </span></strong><span style="font-family:Verdana;font-size:85%;">because it does exactly what we need. Next we just need to call </span><strong><span style="font-family:Verdana;font-size:85%;">SetupHatch() </span></strong><span style="font-family:Verdana;font-size:85%;">again to ensure our hatch is updated with the new boundary resulting from the STRETCH command.</span><br /><span style="font-family:Verdana;font-size:85%;">Before test our custom entity, we need to place a call to </span><strong><span style="font-family:Verdana;font-size:85%;">SetupHatch() </span></strong><span style="font-family:Verdana;font-size:85%;">just before to close the entity on its creation stage. Open the </span><strong><span style="font-family:Verdana;font-size:85%;">acrxEntryPoint.cpp </span></strong><span style="font-family:Verdana;font-size:85%;">file, of </span><strong><span style="font-family:Verdana;font-size:85%;">AuUserInterface </span></strong><span style="font-family:Verdana;font-size:85%;">project, and locate the </span><strong><span style="font-family:Verdana;font-size:85%;">AuUserInterface_MyCommand1() </span></strong><span style="font-family:Verdana;font-size:85%;">method. See the code below:</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><br /><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">static void AuUserInterface_MyCommand1(void)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;"><span style="color:#ff0000;"><em><strong>[ some lines were not displayed for code brevity ]</strong></em></span><br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">pL-&gt;SetupHatch();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">pL-&gt;close();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}</span></p><span style="font-family:Verdana;font-size:85%;"></span><span style="font-family:Verdana;font-size:85%;">Now </span><strong><span style="font-family:Verdana;font-size:85%;">Build you Solution </span></strong><span style="font-family:Verdana;font-size:85%;">again. You should get no errors. Open AutoCAD, load your modules (remember, first </span><strong><span style="font-family:Verdana;font-size:85%;">BDX </span></strong><span style="font-family:Verdana;font-size:85%;">and then </span><strong><span style="font-family:Verdana;font-size:85%;">ARX</span></strong><span style="font-family:Verdana;font-size:85%;">). Fire </span><strong><span style="font-family:Verdana;font-size:85%;">MYCOMMAND1 </span></strong><span style="font-family:Verdana;font-size:85%;">command and create one AuPolyline entity. Next test the several features we have implemented. Try to </span><strong><span style="font-family:Verdana;font-size:85%;">COPY </span></strong><span style="font-family:Verdana;font-size:85%;">you entity, </span><strong><span style="font-family:Verdana;font-size:85%;">MOVE </span></strong><span style="font-family:Verdana;font-size:85%;">it, </span><strong><span style="font-family:Verdana;font-size:85%;">ROTATE </span></strong><span style="font-family:Verdana;font-size:85%;">it, </span><strong><span style="font-family:Verdana;font-size:85%;">SCALE </span></strong><span style="font-family:Verdana;font-size:85%;">it and apply a </span><strong><span style="font-family:Verdana;font-size:85%;">MIRROR</span></strong><span style="font-family:Verdana;font-size:85%;">. You can also use the </span><strong><span style="font-family:Verdana;font-size:85%;">STRETCH </span></strong><span style="font-family:Verdana;font-size:85%;">command and move the </span><strong><span style="font-family:Verdana;font-size:85%;">GRIP </span></strong><span style="font-family:Verdana;font-size:85%;">points to change the entity’s shape. </span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">Our </span><strong><span style="font-family:Verdana;font-size:85%;">AuPolyline </span></strong><span style="font-family:Verdana;font-size:85%;">entity is derived from </span><strong><span style="font-family:Verdana;font-size:85%;">AcDbPolyline</span></strong><span style="font-family:Verdana;font-size:85%;">, right? So do you expect that a specific polyline commands like </span><strong><span style="font-family:Verdana;font-size:85%;">PEDIT </span></strong><span style="font-family:Verdana;font-size:85%;">work with our entity? </span><strong><span style="font-family:Verdana;font-size:85%;">Yes, it works! </span></strong><span style="font-family:Verdana;font-size:85%;">Try to fire the </span><strong><span style="font-family:Verdana;font-size:85%;">PEDIT </span></strong><span style="font-family:Verdana;font-size:85%;">command and select our polyline. It will accept it and will allow you to change the AuPolyline as if it is a native AutoCAD Polyline. You can add new vertexes, remove existing, join new segments and even open the polyline (Figure 19). Great!</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><a href="http://photos1.blogger.com/x/blogger/6284/765/640/947370/Figure19.jpg"><img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/6284/765/320/147119/Figure19.jpg" border="0" /></a><br /><span style="font-family:Verdana;font-size:85%;">Figure 19 – AuPolyline modifications.</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><strong><span style="font-family:Verdana;font-size:85%;">Conclusion</span></strong><br /><span style="font-family:Verdana;font-size:85%;">In this session you have learned how to create a custom entity and add some of the possible features </span><strong><span style="font-family:Verdana;font-size:85%;">ObjectARX </span></strong><span style="font-family:Verdana;font-size:85%;">allows. </span><strong><em><span style="font-family:Verdana;font-size:85%;">This is really only the tip of the iceberg</span></em></strong><span style="font-family:Verdana;font-size:85%;">. There are much more you can do using </span><strong><span style="font-family:Verdana;font-size:85%;">ObjectARX </span></strong><span style="font-family:Verdana;font-size:85%;">classes and implementing more sophisticated features. I really hope you have enjoyed this session and hope it may help you to make the startup into the </span><strong><span style="font-family:Verdana;font-size:85%;">ObjectARX </span></strong><span style="font-family:Verdana;font-size:85%;">world.</span>Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-1168648377036127252007-01-12T22:33:00.000-02:002007-01-13T00:48:58.675-02:00Exercise2 - Step5<strong><span style="font-family:Verdana;font-size:85%;">Creating a Custom Entity – Exercise 2 – Step 5</span></strong><br /><strong><span style="font-family:Verdana;font-size:85%;"></span></strong><br /><span style="font-family:Verdana;font-size:85%;">Sometimes you need to distribute an AutoCAD drawing with custom entities inside. By default, when AutoCAD opens a drawing and find some entity it does not recognize, it protects this entity and </span><strong><span style="font-family:Verdana;font-size:85%;">packs its binary data into a Proxy entity</span></strong><span style="font-family:Verdana;font-size:85%;">. The proxy entity </span><strong><span style="font-family:Verdana;font-size:85%;">protects your object data </span></strong><span style="font-family:Verdana;font-size:85%;">avoiding unwanted users to manipulate your custom entities.</span><br /><span style="font-family:Verdana;font-size:85%;">The proxy entity is merely a dummy entity with a </span><strong><span style="font-family:Verdana;font-size:85%;">fixed graphical representation</span></strong><span style="font-family:Verdana;font-size:85%;">. Several features of your custom entity will not be available once your code is not there to provide these methods. If your drawing is opened by an unadvised user that would be nice if you inform this user about the missing application.</span><br /><span style="font-family:Verdana;font-size:85%;">The proxy can contain specific graphics which will be generated with a call to your </span><strong><span style="font-family:Verdana;font-size:85%;">worldDraw() </span></strong><span style="font-family:Verdana;font-size:85%;">method just before AutoCAD close the drawing. The worldDraw() method has a parameter, an </span><strong><span style="font-family:Verdana;font-size:85%;">AcGiWorldDraw </span></strong><span style="font-family:Verdana;font-size:85%;">pointer, that allows you to call a </span><strong><span style="font-family:Verdana;font-size:85%;">regenType() </span></strong><span style="font-family:Verdana;font-size:85%;">method to find out if the caller is requesting proxy graphics to your entity. At this time, you can draw a different graphic to make and advertisement of your missing custom entity. The following code shows how to handle the proxy graphics:</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><br /><br /><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// ==================================================================<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// PROXY<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">if (mode-&gt;regenType() == kAcGiSaveWorldDrawForProxy)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Draw dummy text<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">CString strTxt = _T("AU Polyline");<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3d ptTxt = GetPolylineCenter();<br /></span><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">mode-&gt;geometry().text(ptTxt, AcGeVector3d::kZAxis, AcGeVector3d::kXAxis, szRef, 1.0, 0.0, strTxt);<br /></span><span style="font-family:Lucida Console;font-size:85%;">}</span></span></p><span style="font-family:Verdana;font-size:85%;">On this example the proxy graphics will be the standard entity graphic plus a text indicating our class name. You may also add an URL address of your product or company. We will use the center point as this text’s start point.</span><br /><span style="font-family:Verdana;font-size:85%;">Unfortunately this solution is not complete for AcDbPolyline derived entities. There is a problem when a polyline needs to generate its proxy graphics and the worldDraw() method </span><u><span style="font-family:Verdana;font-size:85%;">is not called</span></u><span style="font-family:Verdana;font-size:85%;">. To solve this problem we need to add another method, called </span><strong><span style="font-family:Verdana;font-size:85%;">saveAs()</span></strong><span style="font-family:Verdana;font-size:85%;">, to our class. This method has the following declaration:</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><strong><span style="font-family:Lucida Console;font-size:85%;">virtual void saveAs(AcGiWorldDraw * mode, AcDb::SaveType st);</span></strong><br /><span style="font-family:Verdana;font-size:85%;">The implementation of this method is as follows:</span><br /><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">void AuPolyline::saveAs(AcGiWorldDraw * mode, AcDb::SaveType st)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDbPolyline::saveAs (mode, st) ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">if ((mode-&gt;regenType() == kAcGiSaveWorldDrawForProxy) &&amp;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">(st == AcDb::kR13Save))<br /></span><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">this-&gt;worldDraw(mode);<br /></span><span style="font-family:Lucida Console;font-size:85%;">}</span></span></p><span style="font-family:Verdana;font-size:85%;">This method first forward the call to our base class and then test if the </span><strong><span style="font-family:Verdana;font-size:85%;">regenType() </span></strong><span style="font-family:Verdana;font-size:85%;">and the save type is </span><strong><span style="font-family:Verdana;font-size:85%;">AcDb::kR13Save</span></strong><span style="font-family:Verdana;font-size:85%;">. If they are, we forward the call to our own </span><strong><span style="font-family:Verdana;font-size:85%;">worldDraw() </span></strong><span style="font-family:Verdana;font-size:85%;">method which will draw the custom entity graphic plus the proxy text message.</span><br /><span style="font-family:Verdana;font-size:85%;">To test this behavior create some </span><strong><span style="font-family:Verdana;font-size:85%;">AuPolyline </span></strong><span style="font-family:Verdana;font-size:85%;">entities, save the drawing, close AutoCAD and then open this DWG without loading the application modules. Once the DWG file is opened you will see a proxy warning dialog with some information about the </span><u><span style="font-family:Verdana;font-size:85%;">missing application </span></u><span style="font-family:Verdana;font-size:85%;">(Figure 18). </span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;"><a href="http://photos1.blogger.com/x/blogger/6284/765/640/22770/Figure18.jpg"><img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/6284/765/320/26964/Figure18.jpg" border="0" /></a><br />Figure 18 – Proxy Information dialog.</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">Note on the Figure 18 that our proxy text is displayed and also, at the proxy information dialog, you may find information about the </span><u><span style="font-family:Verdana;font-size:85%;">missing application</span></u><span style="font-family:Verdana;font-size:85%;">. This dialog allows users to choose one of the </span><u><span style="font-family:Verdana;font-size:85%;">3 options </span></u><span style="font-family:Verdana;font-size:85%;">about how AutoCAD will handle its proxy entities. You can also setup the standard proxy behavior accessing </span><strong><span style="font-family:Verdana;font-size:85%;">Tools </span></strong><span style="font-family:Verdana;font-size:85%;">&gt; </span><strong><span style="font-family:Verdana;font-size:85%;">Options </span></strong><span style="font-family:Verdana;font-size:85%;">&gt; </span><strong><span style="font-family:Verdana;font-size:85%;">Open and Save</span></strong><span style="font-family:Verdana;font-size:85%;">.</span><br /><span style="font-family:Verdana;font-size:85%;">Remember that the </span><strong><span style="font-family:Verdana;font-size:85%;">DBX </span></strong><span style="font-family:Verdana;font-size:85%;">module can be loaded to re-enable the custom entity or you can also send your DBX module along with the </span><strong><span style="font-family:Verdana;font-size:85%;">DWG </span></strong><span style="font-family:Verdana;font-size:85%;">file to enable third-party users to see your custom entity with complete information. This way you can provide a full graphical representation without the application interfaces (</span><strong><span style="font-family:Verdana;font-size:85%;">ARX </span></strong><span style="font-family:Verdana;font-size:85%;">module). The third-party users will be able to see it but can’t modify the custom entity.</span><br /><span style="font-family:Verdana;font-size:85%;">AutoCAD allows some basic operations over the proxy entity like erase, change layer, change color and transformations. These operations will act basically over its dummy graphical representation (</span><u><span style="font-family:Verdana;font-size:85%;">they will not affect your custom entity’s data except when it is erased</span></u><span style="font-family:Verdana;font-size:85%;">). It is up to the developer to determine the most adequate flags for each custom entity. This is a compiler-time option and it is defined on the custom entity’s class implementation macro (</span><strong><span style="font-family:Verdana;font-size:85%;">ACRX_DXF_DEFINE_MEMBERS</span></strong><span style="font-family:Verdana;font-size:85%;">). This flags can be combined to build a complete configuration. </span><u><span style="font-family:Verdana;font-size:85%;">Please refer to ObjectARX SDK documentation for further information about proxy flags</span></u><span style="font-family:Verdana;font-size:85%;">.</span>Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-1168648354099497922007-01-12T22:32:00.000-02:002007-01-13T00:48:34.475-02:00Exercise2 - Step4<strong><span style="font-family:Verdana;font-size:85%;">Creating a Custom Entity – Exercise 2 – Step 4</span></strong><br /><br /><span style="font-family:Verdana;font-size:85%;">Now you will learn how to add </span><strong><span style="font-family:Verdana;font-size:85%;">OSNAP </span></strong><span style="font-family:Verdana;font-size:85%;">points to your custom entity. If you run the application before this step you will see that our custom entity already shows some Object Snap points by default (</span><strong><span style="font-family:Verdana;font-size:85%;">ENDPOINT </span></strong><span style="font-family:Verdana;font-size:85%;">and </span><strong><span style="font-family:Verdana;font-size:85%;">MIDPOINT</span></strong><span style="font-family:Verdana;font-size:85%;">). In this example we want to add a </span><strong><span style="font-family:Verdana;font-size:85%;">CENTER </span></strong><span style="font-family:Verdana;font-size:85%;">object snap to our polyline that will allow users to select the exact </span><strong><span style="font-family:Verdana;font-size:85%;">center point</span></strong><span style="font-family:Verdana;font-size:85%;">. To provide this, we need to change the standard behavior of </span><strong><span style="font-family:Verdana;font-size:85%;">getOsnapPoints() </span></strong><span style="font-family:Verdana;font-size:85%;">method. This method has </span><strong><span style="font-family:Verdana;font-size:85%;">4 signatures </span></strong><span style="font-family:Verdana;font-size:85%;">and 2 of them, containing the </span><strong><span style="font-family:Verdana;font-size:85%;">AcGeFastTransform </span></strong><span style="font-family:Verdana;font-size:85%;">parameter, are for future use. We will use the first signature and will handle the </span><strong><span style="font-family:Verdana;font-size:85%;">CENTER </span></strong><span style="font-family:Verdana;font-size:85%;">object snap responding with our center point:</span><br /><br /><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;"></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus AuPolyline::getOsnapPoints (<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDb::OsnapMode osnapMode,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">int gsSelectionMark,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcGePoint3d &pickPoint,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcGePoint3d &amp;lastPoint,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcGeMatrix3d &viewXform,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3dArray &amp;snapPoints,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDbIntArray &geomIds) const<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">assertReadEnabled () ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">switch(osnapMode)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">case AcDb::kOsModeCen:<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">snapPoints.append(GetPolylineCenter());<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">break;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">return (AcDbPolyline::getOsnapPoints (osnapMode, gsSelectionMark, pickPoint, lastPoint, viewXform, snapPoints, geomIds)) ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}</span><br /><span style="font-family:Verdana;font-size:85%;"></span><span style="font-family:Verdana;font-size:85%;">This method receives an Array of points where we need to add the center point whenever the </span><strong><span style="font-family:Verdana;font-size:85%;">OSNAP CENTER </span></strong><span style="font-family:Verdana;font-size:85%;">is requested. On line </span><strong><span style="font-family:Verdana;font-size:85%;">13 </span></strong><span style="font-family:Verdana;font-size:85%;">we handle the </span><strong><span style="font-family:Verdana;font-size:85%;">CENTER </span></strong><span style="font-family:Verdana;font-size:85%;">object snap by adding our </span><strong><span style="font-family:Verdana;font-size:85%;">center point </span></strong><span style="font-family:Verdana;font-size:85%;">to the </span><strong><span style="font-family:Verdana;font-size:85%;">snapPoints </span></strong><span style="font-family:Verdana;font-size:85%;">array (Figure 17). Even handling this particular object snap this method needs to call the polyline class level. The polyline will handle all other possible object snaps for us.</span><br /><br /><a href="http://photos1.blogger.com/x/blogger/6284/765/640/169140/Figure17.jpg"><img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/6284/765/320/854398/Figure17.jpg" border="0" /></a><br /><span style="font-family:Verdana;font-size:85%;">Figure 17 – CENTER object snap.</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><strong><u><span style="font-family:Verdana;font-size:85%;">Note</span></u></strong><span style="font-family:Verdana;font-size:85%;">: </span><em><span style="font-family:Verdana;font-size:85%;">This OSNAP solution handles only simple OSNAP types like CENTER, MIDPOINT and ENDPOINT. Complex OSNAP modes like INTERSECTION require other methods implementations and some additional procedures.</span></em>Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-1168648289374721142007-01-12T22:31:00.001-02:002007-01-13T00:48:11.982-02:00Exercise2 - Step3<strong><span style="font-family:Verdana;font-size:85%;">Creating a Custom Entity – Exercise 2 – Step 3</span></strong><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">Now you will learn how to add </span><strong><span style="font-family:Verdana;font-size:85%;">GRIP </span></strong><span style="font-family:Verdana;font-size:85%;">points to your entity. In fact, as the default implementation of </span><strong><span style="font-family:Verdana;font-size:85%;">AuPolyline </span></strong><span style="font-family:Verdana;font-size:85%;">forward the call to its base class you may already noted that its GRIP points are </span><u><span style="font-family:Verdana;font-size:85%;">visible and working</span></u><span style="font-family:Verdana;font-size:85%;">. The GRIP point behavior is handled by </span><u><span style="font-family:Verdana;font-size:85%;">two methods</span></u><span style="font-family:Verdana;font-size:85%;">. The first method, called </span><strong><span style="font-family:Verdana;font-size:85%;">getGripPoints() </span></strong><span style="font-family:Verdana;font-size:85%;">is responsible for </span><u><span style="font-family:Verdana;font-size:85%;">acquiring </span></u><span style="font-family:Verdana;font-size:85%;">all GRIP points from your entity. The second, called </span><strong><span style="font-family:Verdana;font-size:85%;">moveGripPointsAt()</span></strong><span style="font-family:Verdana;font-size:85%;">, is responsible for the </span><u><span style="font-family:Verdana;font-size:85%;">action </span></u><span style="font-family:Verdana;font-size:85%;">fired by each grip.</span><br /><span style="font-family:Verdana;font-size:85%;">Each default polyline GRIP action is to move the related vertex. In this example we want to add </span><strong><span style="font-family:Verdana;font-size:85%;">one extra grip </span></strong><span style="font-family:Verdana;font-size:85%;">positioned at our </span><strong><span style="font-family:Verdana;font-size:85%;">polygon’s center</span></strong><span style="font-family:Verdana;font-size:85%;">. To do that we first need to create a helper method to calculate this point. We will walk through all polygon points and will sum the coordinates dividing the result by </span><strong><span style="font-family:Verdana;font-size:85%;">numVerts()</span></strong><span style="font-family:Verdana;font-size:85%;">. This method will not change our entity data so it is recommended to be </span><strong><span style="font-family:Verdana;font-size:85%;">CONST </span></strong><span style="font-family:Verdana;font-size:85%;">and will require only the </span><strong><span style="font-family:Verdana;font-size:85%;">assertReadEnabled() </span></strong><span style="font-family:Verdana;font-size:85%;">call:</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3d AuPolyline::GetPolylineCenter() const<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">assertReadEnabled();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3d ptC,pti;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">double cx = 0.0, cy = 0.0, cz = 0.0;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">for (int i=0; i&lt;numVerts(); i++)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">this-&gt;getPointAt(i,pti);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">cx += pti[X];<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">cy += pti[Y];<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">cz += pti[Z];<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">cx = cx / numVerts();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">cy = cy / numVerts();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">cz = cz / numVerts();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">ptC.set(cx, cy, cz);<br /></span><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">return ptC;<br /></span><span style="font-family:Lucida Console;font-size:85%;">}</span></span><br /><span style="font-family:Lucida Console;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">Lines </span><strong><span style="font-family:Verdana;font-size:85%;">04-15 </span></strong><span style="font-family:Verdana;font-size:85%;">apply the </span><strong><span style="font-family:Verdana;font-size:85%;">center formula </span></strong><span style="font-family:Verdana;font-size:85%;">and at line </span><strong><span style="font-family:Verdana;font-size:85%;">16 </span></strong><span style="font-family:Verdana;font-size:85%;">we build the point using cx, cy and cz as the point’s X, Y and Z coordinates respectively.</span><br /><span style="font-family:Verdana;font-size:85%;">Next we need to change the default implementation of the both GRIP point methods. First we will redefine the </span><strong><span style="font-family:Verdana;font-size:85%;">getGripPoints() </span></strong><span style="font-family:Verdana;font-size:85%;">method. This method has </span><u><span style="font-family:Verdana;font-size:85%;">2 signatures </span></u><span style="font-family:Verdana;font-size:85%;">and we will use the new </span><strong><span style="font-family:Verdana;font-size:85%;">AcDbGripData </span></strong><span style="font-family:Verdana;font-size:85%;">method instead of the “old style” method.</span><br /><span style="font-family:Verdana;font-size:85%;">This method receives an array of </span><strong><span style="font-family:Verdana;font-size:85%;">AcDbGripData </span></strong><span style="font-family:Verdana;font-size:85%;">pointers. These objects represent the </span><strong><span style="font-family:Verdana;font-size:85%;">GRIP </span></strong><span style="font-family:Verdana;font-size:85%;">point information. We need to inform at least the point and an arbitrary data (</span><strong><span style="font-family:Verdana;font-size:85%;">void*</span></strong><span style="font-family:Verdana;font-size:85%;">). This arbitrary data can be used later to get back information from each </span><strong><span style="font-family:Verdana;font-size:85%;">GRIP </span></strong><span style="font-family:Verdana;font-size:85%;">point allowing the </span><strong><span style="font-family:Verdana;font-size:85%;">moveGripPointsAt() </span></strong><span style="font-family:Verdana;font-size:85%;">method to perform the custom actions:</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus AuPolyline::getGripPoints (<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDbGripDataPtrArray &grips,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const double curViewUnitSize,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const int gripSize,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcGeVector3d &amp;curViewDir,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const int bitflags) const<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">assertReadEnabled () ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDbGripData* gpd = new AcDbGripData();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">gpd-&gt;setAppData((void*)9999); // Center Grip code<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">gpd-&gt;setGripPoint(GetPolylineCenter());<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">grips.append(gpd);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDbPolyline::getGripPoints (grips, curViewUnitSize, gripSize, curViewDir, bitflags);<br /></span><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">return (Acad::eOk);<br /></span><span style="font-family:Lucida Console;font-size:85%;">}</span></span><br /><span style="font-family:Lucida Console;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">This method will not change our entity’s data so it is also a </span><strong><span style="font-family:Verdana;font-size:85%;">CONST </span></strong><span style="font-family:Verdana;font-size:85%;">method and calls </span><strong><span style="font-family:Verdana;font-size:85%;">assertReadEnabled() </span></strong><span style="font-family:Verdana;font-size:85%;">method. On lines </span><strong><span style="font-family:Verdana;font-size:85%;">09-12 </span></strong><span style="font-family:Verdana;font-size:85%;">we instantiate an </span><strong><span style="font-family:Verdana;font-size:85%;">AcDbGripData </span></strong><span style="font-family:Verdana;font-size:85%;">pointer and set its application data (</span><strong><span style="font-family:Verdana;font-size:85%;">9999 </span></strong><span style="font-family:Verdana;font-size:85%;">in this case) and the grip point which is calculated by the </span><strong><span style="font-family:Verdana;font-size:85%;">GetPolylineCenter() </span></strong><span style="font-family:Verdana;font-size:85%;">method. Next, on line </span><strong><span style="font-family:Verdana;font-size:85%;">13 </span></strong><span style="font-family:Verdana;font-size:85%;">we forward the call to AcDbPolyline’s grip point method so it is able to add </span><u><span style="font-family:Verdana;font-size:85%;">its own GRIP points </span></u><span style="font-family:Verdana;font-size:85%;">at last. These GRIP points are those vertexes points we have mentioned before. The next step is to change the </span><strong><span style="font-family:Verdana;font-size:85%;">moveGripPointsAt() </span></strong><span style="font-family:Verdana;font-size:85%;">method so when the user clicks on this center GRIP it will </span><u><span style="font-family:Verdana;font-size:85%;">reflect a custom action</span></u><span style="font-family:Verdana;font-size:85%;">. In this example, our custom action will </span><strong><span style="font-family:Verdana;font-size:85%;">move the entire polyline</span></strong><span style="font-family:Verdana;font-size:85%;">. The following code shows how to do that:</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Acad::ErrorStatus AuPolyline::moveGripPointsAt (<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcDbVoidPtrArray &gripAppData,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const AcGeVector3d &amp;offset,<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">const int bitflags)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">assertWriteEnabled () ;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">for (int g=0; g&lt;gripAppData.length(); g++)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Get grip data back and see if it is our 0 Grip<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">int i = (int)gripAppData.at(g);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// If it is our grip, move the entire entity. If not, forward the call<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">if (i == 9999)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">this-&gt;transformBy(offset);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">else<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDbCurve::moveGripPointsAt (gripAppData, offset, bitflags);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}<br /></span><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">return (Acad::eOk);<br /></span><span style="font-family:Lucida Console;font-size:85%;">}</span></span><br /><span style="font-family:Lucida Console;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">This time, our method cannot be </span><strong><span style="font-family:Verdana;font-size:85%;">CONST </span></strong><span style="font-family:Verdana;font-size:85%;">once we will change our entity’s data. Due that, we need to call </span><strong><span style="font-family:Verdana;font-size:85%;">assertWriteEnabled() </span></strong><span style="font-family:Verdana;font-size:85%;">at it’s beginning. On line </span><strong><span style="font-family:Verdana;font-size:85%;">07 </span></strong><span style="font-family:Verdana;font-size:85%;">we start to inspect the </span><strong><span style="font-family:Verdana;font-size:85%;">AcDbVoidPtrArray </span></strong><span style="font-family:Verdana;font-size:85%;">(an array of </span><strong><span style="font-family:Verdana;font-size:85%;">void*</span></strong><span style="font-family:Verdana;font-size:85%;">) looking for our application data (</span><strong><span style="font-family:Verdana;font-size:85%;">9999</span></strong><span style="font-family:Verdana;font-size:85%;">). This method also receives a </span><strong><span style="font-family:Verdana;font-size:85%;">3D vector </span></strong><span style="font-family:Verdana;font-size:85%;">which represents the transformation being applied to the GRIP. If the GRIP being modified is our </span><strong><span style="font-family:Verdana;font-size:85%;">9999 </span></strong><span style="font-family:Verdana;font-size:85%;">we will apply this vector transformation to the </span><u><span style="font-family:Verdana;font-size:85%;">entire polyline</span></u><span style="font-family:Verdana;font-size:85%;">. This can be done through the </span><strong><span style="font-family:Verdana;font-size:85%;">transformBy() </span></strong><span style="font-family:Verdana;font-size:85%;">method passing the same vector (Figure 16).</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;"><a href="http://photos1.blogger.com/x/blogger/6284/765/640/79041/Figure16.jpg"><img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/6284/765/320/379296/Figure16.jpg" border="0" /></a><br />Figure 16 – Center GRIP in action.</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">If the fired </span><strong><span style="font-family:Verdana;font-size:85%;">GRIP </span></strong><span style="font-family:Verdana;font-size:85%;">is not our </span><strong><span style="font-family:Verdana;font-size:85%;">9999 </span></strong><span style="font-family:Verdana;font-size:85%;">code we will forward the call to </span><strong><span style="font-family:Verdana;font-size:85%;">AcDbCurve </span></strong><span style="font-family:Verdana;font-size:85%;">class (AcDbPolylin’s base class) which will handle it for us. The resulting behavior is when you select a GRIP over the polyline boundary the entity </span><u><span style="font-family:Verdana;font-size:85%;">stretches </span></u><span style="font-family:Verdana;font-size:85%;">and when you select the center GRIP the entity </span><u><span style="font-family:Verdana;font-size:85%;">moves</span></u><span style="font-family:Verdana;font-size:85%;">.</span>Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-1168648265636487252007-01-12T22:31:00.000-02:002007-01-13T00:47:45.447-02:00Exercise2 - Step2<span style="color:#000000;"><strong><span style="font-family:Verdana;font-size:85%;">Creating a Custom Entity – Exercise 2 – Step 2</span></strong> </span><br /><span style="color:#000000;"><br /><span style="font-family:Verdana;font-size:85%;">Now after you have created a basic custom entity you will learn how to add custom graphics to it. The custom entity’s graphics is generated primarily by the </span><strong><span style="font-family:Verdana;font-size:85%;">worldDraw() </span></strong><span style="font-family:Verdana;font-size:85%;">method and optionally by the </span><strong><span style="font-family:Verdana;font-size:85%;">viewportDraw() </span></strong><span style="font-family:Verdana;font-size:85%;">method.</span><br /><span style="font-family:Verdana;font-size:85%;">As this entity’s base class already generates a </span><u><span style="font-family:Verdana;font-size:85%;">polyline graphic </span></u><span style="font-family:Verdana;font-size:85%;">we will add some nice extra graphics to it. Each vertex will receive an </span><strong><span style="font-family:Verdana;font-size:85%;">index number and an arrow </span></strong><span style="font-family:Verdana;font-size:85%;">indicating the polyline construction direction (Figure 14). </span><br /><span style="font-family:Verdana;font-size:85%;">We will use different colors for each graphic type. The index number will use the </span><strong><span style="font-family:Verdana;font-size:85%;">256 </span></strong><span style="font-family:Verdana;font-size:85%;">color code which is the </span><strong><span style="font-family:Verdana;font-size:85%;">ByLayer </span></strong><span style="font-family:Verdana;font-size:85%;">color and the arrows will use a fixed </span><strong><span style="font-family:Verdana;font-size:85%;">1 </span></strong><span style="font-family:Verdana;font-size:85%;">color code which is </span><strong><span style="font-family:Verdana;font-size:85%;">red</span></strong><span style="font-family:Verdana;font-size:85%;">. If you change the color of this entity’s layer it will change except on the arrows that will stay red. Further, all arrows will be filled. </span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;"><a href="http://photos1.blogger.com/x/blogger/6284/765/640/744992/Figure14.jpg"><img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/6284/765/320/418219/Figure14.jpg" border="0" /></a><br />Figure 14 – Custom Entity with vertex numbers and arrows</span></span><br /><span style="color:#000000;"><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">To create these graphics you will need to use some trigonometric methods. The following code demonstrates what you can reach this:</span><br /><br /><br /></span><span style="color:#000000;"></span><span style="color:#000000;"></span><p><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">Adesk::Boolean AuPolyline::worldDraw (AcGiWorldDraw *mode)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">assertReadEnabled();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Call base class first<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcDbPolyline::worldDraw(mode);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">double szRef = 5.0;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// ================================================================<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// DIRECTION AND VERTEX NUMBERING<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">int signal = 1;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">double ht2 = szRef/4.0;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">for(int i=0; i&lt;numVerts(); i++)<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">{<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3d pti;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">this-&gt;getPointAt(i,pti);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Draw vertex text<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">CString strNum;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">strNum.Format(_T("%d"),i);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3d ptTxt = pti + (AcGeVector3d::kXAxis*ht2) + (AcGeVector3d::kYAxis*ht2);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">mode-&gt;subEntityTraits().setColor(256); // ByLayer<br /></span><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">mode-&gt;geometry().text(ptTxt, AcGeVector3d::kZAxis, AcGeVector3d::kXAxis, ht2, 1.0, 0.0, strNum);<br /></span><span style="font-family:Lucida Console;font-size:85%;">/</span></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">/ Arrow direction<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3d ptj;<br /></span><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">this-&gt;getPointAt(i&lt;(numVerts()-1) ? (i+1) : 0, ptj);<br /></span><span style="font-family:Lucida Console;font-size:85%;">A</span></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">cGeVector3d dir = (ptj - pti).normalize();<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Side perpendicular vectors<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGeVector3d perp = dir;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">perp.rotateBy(3.141592/2.0,AcGeVector3d::kZAxis);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3d pt1 = ptj - (dir*ht2) + (perp*(ht2/4.0));<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3d pt2 = ptj - (dir*ht2) - (perp*(ht2/4.0));<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">AcGePoint3d pts[3];<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">pts[0] = ptj;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">pts[1] = pt1;<br />p</span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">ts[2] = pt2;<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">// Draw arrow polygon<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">mode-&gt;subEntityTraits().setFillType(kAcGiFillAlways);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">mode-&gt;subEntityTraits().setColor(1); // red<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">mode-&gt;geometry().polygon(3,pts);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">mode-&gt;subEntityTraits().setFillType(kAcGiFillNever);<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">}<br /></span><span style="font-family:Lucida Console;font-size:85%;color:#3333ff;">//------ Returning Adesk::kFalse here will force viewportDraw() call<br /></span><span style="color:#3333ff;"><span style="font-family:Lucida Console;font-size:85%;">return (Adesk::kTrue) ;<br /></span><span style="font-family:Lucida Console;font-size:85%;">}</span></span></p><span style="color:#000000;"><span style="font-family:Verdana;font-size:85%;">On line </span><strong><span style="font-family:Verdana;font-size:85%;">03 </span></strong><span style="font-family:Verdana;font-size:85%;">we call the proper assert method which inform what type of access we are executing on this method. As we are not changing any data we need only to </span><strong><span style="font-family:Verdana;font-size:85%;">READ </span></strong><span style="font-family:Verdana;font-size:85%;">the entity so we call </span><strong><span style="font-family:Verdana;font-size:85%;">assertReadEnabled() </span></strong><span style="font-family:Verdana;font-size:85%;">method. On line </span><strong><span style="font-family:Verdana;font-size:85%;">05 </span></strong><span style="font-family:Verdana;font-size:85%;">we forward up the call to its base class method which will draw the polyline curves. On lines </span><strong><span style="font-family:Verdana;font-size:85%;">06-10 </span></strong><span style="font-family:Verdana;font-size:85%;">we initialize some local variables. </span><br /><span style="font-family:Verdana;font-size:85%;">Next, from line </span><strong><span style="font-family:Verdana;font-size:85%;">11-39 </span></strong><span style="font-family:Verdana;font-size:85%;">we perform a loop on each polyline vertex to draw our custom graphics. On lines </span><strong><span style="font-family:Verdana;font-size:85%;">13-14 </span></strong><span style="font-family:Verdana;font-size:85%;">we get the current vertex point. On line range </span><strong><span style="font-family:Verdana;font-size:85%;">16-20 </span></strong><span style="font-family:Verdana;font-size:85%;">we draw the vertex text using the </span><strong><span style="font-family:Verdana;font-size:85%;">text() </span></strong><span style="font-family:Verdana;font-size:85%;">geometry primitive at a point with a small displacement related to the vertex point. On lines </span><strong><span style="font-family:Verdana;font-size:85%;">22-24 </span></strong><span style="font-family:Verdana;font-size:85%;">we calculate the end point (</span><strong><span style="font-family:Verdana;font-size:85%;">ptj</span></strong><span style="font-family:Verdana;font-size:85%;">) of each polyline segment and its unitary direction vector (</span><strong><span style="font-family:Verdana;font-size:85%;">dir</span></strong><span style="font-family:Verdana;font-size:85%;">). Next, on lines </span><strong><span style="font-family:Verdana;font-size:85%;">26-33 </span></strong><span style="font-family:Verdana;font-size:85%;">we calculate the </span><u><span style="font-family:Verdana;font-size:85%;">3 points </span></u><span style="font-family:Verdana;font-size:85%;">which will build an arrow head graphic. The </span><strong><span style="font-family:Verdana;font-size:85%;">perp </span></strong><span style="font-family:Verdana;font-size:85%;">vector will allow us to draw each side of the arrow head according to the Figure 15. On lines </span><strong><span style="font-family:Verdana;font-size:85%;">35-38 </span></strong><span style="font-family:Verdana;font-size:85%;">we draw the filled arrow head using the </span><strong><span style="font-family:Verdana;font-size:85%;">polygon() </span></strong><span style="font-family:Verdana;font-size:85%;">primitive with </span><strong><span style="font-family:Verdana;font-size:85%;">color red </span></strong><span style="font-family:Verdana;font-size:85%;">and with the fill type always.</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;">Finally, on line </span><strong><span style="font-family:Verdana;font-size:85%;">41</span></strong><span style="font-family:Verdana;font-size:85%;">, we return </span><strong><span style="font-family:Verdana;font-size:85%;">Adesk::kTrue </span></strong><span style="font-family:Verdana;font-size:85%;">to avoid the graphics to be made by the </span><strong><span style="font-family:Verdana;font-size:85%;">viewportDraw() </span></strong><span style="font-family:Verdana;font-size:85%;">method.</span><br /><span style="font-family:Verdana;font-size:85%;">These classes we have used, with </span><strong><span style="font-family:Verdana;font-size:85%;">AcGe </span></strong><span style="font-family:Verdana;font-size:85%;">prefix, are part of the AcGe library which contains several </span><u><span style="font-family:Verdana;font-size:85%;">utility classes and methods </span></u><span style="font-family:Verdana;font-size:85%;">to help us to deal with </span><strong><span style="font-family:Verdana;font-size:85%;">geometric calculations</span></strong><span style="font-family:Verdana;font-size:85%;">. This really helps a lot once most of these calculations are a little bit complex.</span><br /><span style="font-family:Verdana;font-size:85%;"></span><br /><span style="font-family:Verdana;font-size:85%;"></span><a href="http://photos1.blogger.com/x/blogger/6284/765/640/233570/Figure15.jpg"><img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/x/blogger/6284/765/320/236941/Figure15.jpg" border="0" /></a><br /><span style="font-family:Verdana;font-size:85%;">Figure 15 – AuPolyline side graphics.</span></span>Fernando Malardhttp://www.blogger.com/profile/09852061806995998594noreply@blogger.comtag:blogger.com,1999:blog-10425945.post-1168648229869560762007-01-12T22:30:00.000-02:002007-01-13T00:45:06.456-02:00Exercise2 - Step1<strong><span style="font-family:Verdana;font-size:85%;color:#000099;">Hello,</span></strong><br /><strong><span style="font-family:Verdana;font-size:85%;color:#000099;"></span></strong><br /><strong><span style="font-family:Verdana;font-size:85%;color:#000099;">I will post a sequence of 6 steps of my Exercise 2 provided at last year's AU. It will show you how to create a custom entity inside AutoCAD 2007 using ObjectARX 2007 and Visual Studio 2005.</span></strong><br /><strong><span style="font-family:Verdana;font-size:85%;color:#000099;"></span></strong><br /><strong><span style="font-family:Verdana;font-size:85%;color:#000099;">Hope you enjoy these posts!</span></strong><br /><span style="color:#000000;"><strong><span style="font-family:Verdana;font-size:85%;"></span></strong></span><br /><span style="color:#000000;"><strong><span style="font-family:Verdana;font-size:85%;">Creating a Custom Entity – Exercise 2 – Step 1</span></strong> </span><br /><span style="color:#000000;"><br /><span style="font-family:Verdana;font-size:85%;">You will learn in this exercise how to create a </span><strong><span style="font-family:Verdana;font-size:85%;">simple custom entity</span></strong><span style="font-family:Verdana;font-size:85%;">. I will keep it simple as much as I can to reinforce the basic concepts involved. On the next steps we will improve this custom entity by adding great features step by step.</span><br /><span style="font-family:Verdana;font-size:85%;">The first step is to name our entity and choose from which base class it will derive. Remember we have to split our application into two modules, an </span><strong><span style="font-family:Verdana;font-size:85%;">ARX </span></strong><span style="font-family:Verdana;font-size:85%;">(user interfaces) and a </span><strong><span style="font-family:Verdana;font-size:85%;">DBX </span></strong><span style="font-family:Verdana;font-size:85%;">(the custom entity class itself). These two projects will be placed into the same Visual Studio Solution and the </span><u><span style="font-family:Verdana;font-size:85%;">ARX module will depend on DBX module</span></u><span style="font-family:Verdana;font-size:85%;">. The names will be:</span><br /><br /><br /><br /><br /><br /></span><span style="color:#000000;"></span><span style="color:#000000;"></span><span style="color:#000000;"></span><span style="color:#000000;"></span><ul><li><span style="color:#000000;"><strong><u><span style="font-family:Verdana;font-size:85%;">Solution</span></u></strong><span style="font-family:Verdana;font-size:85%;">: </span><strong><span style="font-family:Verdana;font-size:85%;">Exercis