.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

overrule is really confusing ....

25 REPLIES 25
SOLVED
Reply
Message 1 of 26
JanetDavidson
3583 Views, 25 Replies

overrule is really confusing ....

 

Hello,

I have to repost this because people may think, last post was answered, but it wasn't and still I am struggling and need a pro to help me here .

Have a overruled block with attribute in it , I just  registered the attributes in  my overrule class.

I need to overule (make it simple) just lines ( let's say make them circles)  and don't want to show the attributes neither do the rest of objects in block . But if user double click on overruled block I need to show attribute tag input table (Dialog). And don't want to show other objects in block if any exists.

 

Below is my code and I thought solution would be  easy and I have to REM ( or remove the line )

MyBase.WorldDraw(drawable, Wd).

 

But when I do that the block is not selectable and a regen crash the autocad . That was my story and here is the code.

I appreciate any help here. For your convenience a simple  block is attached.

Janet

 

 

 

Public Class toverrule
        Inherits Autodesk.AutoCAD.GraphicsInterface.DrawableOverrule
        Public Overrides Function WorldDraw(ByVal drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, ByVal Wd As Autodesk.AutoCAD.GraphicsInterface.WorldDraw) As Boolean
            Dim myBlock As BlockReference = CType(drawable, BlockReference)

            If Not myBlock.Database Is Nothing Then

                Dim ListEnts As New List(Of Entity)
                Dim MyDBObjColl As DBObjectCollection = New DBObjectCollection()

                myBlock.Explode(MyDBObjColl)

                Dim myline As New Line

                For Each mydbobj As DBObject In MyDBObjColl
                    If TypeOf mydbobj Is Line Then
                        myline = TryCast(mydbobj, Line)
                        Dim mycircle As New Circle
                        mycircle.Radius = myline.Length
                        mycircle.Center = myline.StartPoint
                        ListEnts.Add(mycircle)
                    ElseIf TypeOf mydbobj Is AttributeDefinition Then
                        Dim mycircle As New Circle
                        mycircle.Radius = myline.Length / 2
                        mycircle.Center = myline.StartPoint
                        ListEnts.Add(mycircle)
                    End If
                Next
                For Each Ent As Entity In ListEnts
                    Ent.WorldDraw(Wd)
                    Ent.Dispose()
                Next
                MyBase.WorldDraw(drawable, Wd)
            End If
            Return True
        End Function
    End Class

 

 

 

 

 

 

 

25 REPLIES 25
Message 2 of 26

Hi janet,

 

Hopefully the sample code I posted in the other thread on this topic gives you what yuo need to fix your problem.

 

Cheers,

Stephen Preston
Autodesk Developer Network
Message 3 of 26

Mine is working great now. 

 

This is the important bit of Stephens code that you are still missing.

 

Public Overrides Function SetAttributes(ByVal drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, ByVal traits As Autodesk.AutoCAD.GraphicsInterface.DrawableTraits) As Integer
        Dim res As Integer = MyBase.SetAttributes(drawable, traits)
        'See ARX ref guide entry for "AcGiDrawable::smileyfrustrated:etAttributesFlags Enumeration"
        'Bit 32 indicates entity has attributes. If we unset that bit,
        ' then overruling blockref with attributes works fine. We do
        ' this because we're drawing the attributes ourself.
        Dim test As Integer = res And 32
        If test Then
          res = res - 32
        End If
        Return res
      End Function

Dave O.                                                                  Sig-Logos32.png
Message 4 of 26

That was great-everything is working now  , Are you Tony? hehehehhe.

Thanks chief . The other thread screwed.

 

 

Message 5 of 26

The credit belongs to Stephen Preston.  I was already overriding the SetAttributes function in my code, but I did not know that I needed to remove the 32 bit for blocks with attributes.  That part came from Stephen, and that is the only part that was missing from my original code, to make it work.

Dave O.                                                                  Sig-Logos32.png
Message 6 of 26

Chief I am facing a new problem again with  same overrule.

I have osnaps overrule and it works fine. But when I used distannce command and sanps to overrule block with attribute  it crashes. everything else works fine while snapping to overrule block but this is something . 

Do you mind to take a look at it if you have time? I can make it simple for your convenience .

Janet.

 

Message 7 of 26

Maybe it'll never happen in your circumstance, but you should at least know that if you use the overrule Stephen posted (or any overrule targeting BlockReference for that matter), in a drawing that contains a table that has blocks containing text inserted into the table's cells, AutoCAD will crash when you save the drawing.

Message 8 of 26

Hello, DP.

Thanks for all support

I did use SP's  Attribute Overrides Function. It solved most of my problems. And I realized Geometry Draw acting goofy.

So  I used word draw , even though  Geometry draw is  faster on regen.

Right now everything works fine except for Autocad Distance command. It crashes.

If you or CB can help me,  I would be very grateful. Attached is block drawing file and code. Basically I replaced the lines in block  with 2 polylines, the same length. Try to do a Distance between polylines. It crashes the machine.

Hope I can get help from you gentlemen again.

Thanks Janet 

 

Message 9 of 26

Janet, I don't code in VB.NET unfortunately, and can't easily test your code.

 

What I will tell you, is that overrules are one of the most complicated aspects of AutoCAD .NET programming, and certainly not a good vehicle for an introductory tutorial, so perhaps you've gotten the wrong impression that overrules are relatively-simple to write and debug when in fact, they are a challenge for even highly experienced AutoCAD .NET programmers.

 

About your code, one major problem I see by just looking at it, is that it calls Explode() on a block reference, and then returns a subset of the entities produced by Expode(), but fails to call Dispose() on the entities that aren't returned to the caller, which will likely cause AutoCAD to crash at some later point, and may very likely be what's happening to you.

 

Message 10 of 26

Woman Sad

 

Thanks. I thought you are Tony.

Spoiler
Woman Sad

 

 

 But thanks at least you looked at it. In my original code I disposed all entities and still the same.

Just distance command make this crash.

If I convert it in C# would you please look at it ?

Janet

Message 11 of 26

Yes, I am he.

 

Sure, if you post a .cs file that compiles without errors I'll try it.

Message 12 of 26

Hello Again DP.

After 14 hours struggling I finally converted it to C#. Now behavior is completely different. Before in VB I just had crash

on Distance Command. Now I have crash whenever I snap to block. I really hope and beg for your help Tony.

I know you always have a trick in your sleeve.

Woman Wink

Thanks

Janet

 P.S. I renamed file  extension to .txt , website  doens't allow extension .cs to be uploaded.

 

Message 13 of 26

Hi Janet.

 

Before I even look at that code, I would ask that you fix the obvious bug and try it again.

 

The bug I'm referring to is the line shown in red below (I renamed the function from Go_Get_blahblahblah...). In that line of code, you're creating a new Line object, but not doing anything with it, and not disposing it, which will probably crash AutoCAD.

 

public static bool GetExplodedEnts( BlockReference myBlock, ref List<Entity> ListEnts )
{
   DBObjectCollection MyDBObjColl = new DBObjectCollection();
   {
      myBlock.Explode( MyDBObjColl );
      Line Line1 = new Line();
      foreach( DBObject mydbobj in MyDBObjColl )
      {
         if( mydbobj is Line )
         {
            Line1 = mydbobj as Line;
            Autodesk.AutoCAD.DatabaseServices.Polyline MyPolyLine1 = new Autodesk.AutoCAD.DatabaseServices.Polyline();
            MyPolyLine1.SetDatabaseDefaults();
            MyPolyLine1.AddVertexAt( 0, new Point2d( Line1.StartPoint.X, Line1.StartPoint.Y ), 0, 200, 200 );
            MyPolyLine1.AddVertexAt( 1, new Point2d( Line1.EndPoint.X + 3000, Line1.EndPoint.Y + 3000 ), 0, 200, 200 );
            MyPolyLine1.Closed = true;
            ListEnts.Add( MyPolyLine1 );
         }
         else
         {
            mydbobj.Dispose();
         }
      }
   }
   return true;
}

 That bug is almost certain to crash AutoCAD.

Message 14 of 26

Hi Janet - There's a few more problems with the code you posted, and they are also in the original VB code as well. 

 

First, have a look at the documentation for AcGiDrawable::worldDraw() (In the native ObjectARX docs) and make note of what the return value means. Why does your WorldDraw() return false?

 

public override bool WorldDraw( Drawable drawable, WorldDraw Wd )
{
   BlockReference myBlock = drawable as BlockReference;
   if( ( myBlock.Database != null ) )
   {
      List<Entity> ListEnts = new List<Entity>();
      if( !GetExplodedEnts( myBlock, ListEnts ) )
      {
         return false;
      }
      foreach( Entity Ent in ListEnts )
      {
         Ent.WorldDraw( Wd );
         Ent.Dispose();
      }
   }
   // base.WorldDraw(drawable, Wd);
   return true;
}

Next, your Go_Get_Overruled_exploded_entities_from_this_block() method misuses Try/Catch, by catching any exception that's raised, and without regards for what the exception is or what caused it, your method simply returns False. That's kind of like saying 'I don't care what went wrong, I just want it to work', but it will never work until you find out what went wrong, which that kind of mis-use of Try/Catch prevents. If there's no exception, then that same method always returns True, regardless of whether it added anything to the list or not, which is also not correct.

 

Lastly, your GetObjectSnapPoints() overload uses Try/Catch with an empty catch block Man Mad. That's the same as using On Error Resume Next in VBA, and is something you should never do, because it simply hides exceptions from you, making it nearly impossible to debug your code. When you are writing/testing/debugging code, you can put a statement in an otherwise-empty Catch block that displays the exception that was caught, but you should never use Try/Catch with an empty catch block in production code, without being completely sure what exception will be caught.

 

So, as it stands your code has quite a few problems that you need to fix before I would try to run it,.

Message 15 of 26

Hello  DP, I really appreciate all these time you spent for teaching me(us). What you are doing here for us is like a father doing for their kids. I am/was you fan alwasy.

I did what you asked and thanks for tips. I had all those catches in my original code but they never been hit. I just removed them from this sample code to make it shorter. I put them back but they never been catch.

Regard with New LIne. You are winner . I forgot it totally. But still doesn't change anything.

I checked document and this is what it says :

 

A return value of Adesk::kFalse indicates that the 3D GS must
call viewportDraw() in order to obtain the complete geometry
and attribute set for this drawable.

 

Frankly, don't understand it . But I changed it to True as you mentioned . Nothing changed.

By the way If you want to yell at me . It is OK. I know you yell to make students learn better. I am ready.

( Reminds me those Chinese KungFu movies when the master kicks  student Woman LOL )

 

So HELP

Janet.

 

 

 

Message 16 of 26
jeff
in reply to: JanetDavidson

Hi Janet,

 

I only looked quickly but a IntPtr has a method ToInt32().

Not sure you can use Convert.ToInt32(gsSelectionMark) try gsSelectionMark.ToInt32() instead.

 

 

You can also find your answers @ TheSwamp
Message 17 of 26
JanetDavidson
in reply to: jeff

Jeff,

Thanks. After I applied your advice now it acts like my VB version.

Thanks for your time to look into my problem .Still when I do a distance command it crashes.

Tony is on this as well .We are lucky. Huh!

Cheers,

Janet.

 

 

Message 18 of 26

Jeff already dropped a hint about what the problem is, but I think it's better for you to learn how to find the problem yourself. So, I'll try to show you how to to do that.

One major problem with developing AutoCAD plugins in .NET is that AutoCAD does not always catch exceptions that are thrown by managed code when the managed code is called from lower-level native APIs, overrules being one such case. So, to find out if AutoCAD is crashing as a result of an exception being raised by your overridden overrule methods, you need to wrap them in a try/catch block, and display a message in the catch block, like this:

 

public override void GetObjectSnapPoints( Entity e, ObjectSnapModes snapMode, System.IntPtr gsSelectionMark, 
            Point3d pickPoint, Point3d lastPoint, Matrix3d viewTransform, Point3dCollection snapPoints, 
            IntegerCollection geometryIds, Matrix3d insertionMat )
{
   try
   {
      BlockReference myBlock = e as BlockReference;
      List<Entity> ListEnts = new List<Entity>();
      if( !toverrule.GetExplodedEnts( myBlock, ListEnts ) )
      {
         return;
      }
      foreach( Entity SubEnt in ListEnts )
      {
         SubEnt.GetObjectSnapPoints( snapMode, gsSelectionMark.ToInt32(), pickPoint, lastPoint, viewTransform, snapPoints, geometryIds, insertionMat );
         SubEnt.Dispose();
      }
   }
   catch( System.Exception ex )
   {
      Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage( 
         "\n****** Exception: {0}\n\n\n", ex.ToString() 
      );
   }
}

// The same method, except using the try/catch diagnostics in debug builds only:

public override void GetObjectSnapPoints( Entity e, ObjectSnapModes snapMode, System.IntPtr gsSelectionMark, Point3d pickPoint, 
               Point3d lastPoint, Matrix3d viewTransform, Point3dCollection snapPoints, 
               IntegerCollection geometryIds, Matrix3d insertionMat )
{
#if DEBUG
   try
   {
#endif
      BlockReference myBlock = e as BlockReference;
      List<Entity> ListEnts = new List<Entity>();
      if( !toverrule.GetExplodedEnts( myBlock, ListEnts ) )
      {
         return;
      }
      foreach( Entity SubEnt in ListEnts )
      {
         SubEnt.GetObjectSnapPoints( snapMode, gsSelectionMark.ToInt32(), pickPoint, lastPoint, viewTransform, snapPoints, geometryIds, insertionMat );
         SubEnt.Dispose();
      }
#if DEBUG
   }
   catch( System.Exception ex )
   {
      Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage( 
            "\n****** Exception: {0}\n\n\n", ex.ToString() 
      );
   }
#endif
}

 

If you replace your GetOsnapPoints() override with one of the two shown above, then you will see why your code is crashing. Jeff already suggested the remedy, so I'll leave the rest to you.

 

Message 19 of 26

Tony, Thank you again for your time. VB version had only Distance Command problem. That is why I continued this thread and asked for help ,when I converted it to C# for your consideration the new bug happened ( because of my low experience in c# ,  and Jeff remedy put it back to  state, which Distance command crashes the program ,now it behaves  like VB version.

 

I used your suggested Function to see, if it shows the reason it crashes, when we do distance command , but still it doesn't show what is the problem is . You can try it , use the block,submitted  and apply overule and try to make a distance between two  new thick polylines.

 

originally in my code had a [ ref ] for ListEnts, which in your revised version it was removed.

 Below is what I had originally

if (!toverrule.GetExplodedEnts(myBlock,ref ListEnts))

and this is your revised one

if (!toverrule.GetExplodedEnts(myBlock,ref ListEnts))

 

I had to put ref back to make the code work properly

 

Attached please find latest version including  your funciton and Jeff remedy. But still crashes on Distance command between two overruled Polylines, and doesn't show what the reason is.

 

Thanks

Janet.

 

 

 

Message 20 of 26

HI Janet. 

 

You'll need to provide some details on your config where the code crashes.

 

First, what release of AutoCAD are you using?

 

Second, what running osnap modes are set, and if you're using immediate osnap, which ones are they for the first and second points?

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost