.NET

Reply
Distinguished Contributor
HJohn1
Posts: 169
Registered: ‎09-26-2008
Message 1 of 7 (381 Views)

PointMonitorEventHandler Help

381 Views, 6 Replies
09-20-2013 01:32 PM

I have created a PointMonitorEventHandler to add additional info whenever the cursor is over a BlockReference, the Name, the number of inserts and also identify it when it is a dynamic block.  The code works most of the time, however sometimes is crashes as a lead balloon. I have no idia what is causing it to fail.  Someone please take a look at the code and see if you can help me find out where is the error or how to implement this handler properly.  I will really appreciate any help.  Thanks.  I am using AutoCAD 2012 Mechanical <Vanilla> on 64bit Windows 7.

 

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime

<Assembly: ExtensionApplication(GetType(AutoCADPlugin.AppEventClass))> 
Public Class AppEventClass

    Implements Autodesk.AutoCAD.Runtime.IExtensionApplication
	
Public Sub Initialize() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Initialize

	AddHandler Application.DocumentManager.DocumentCreated, AddressOf Me.DocumentCreated_Handler
	
End Sub
	
Private Sub DocumentCreated_Handler(ByVal sender As Object, ByVal e As DocumentCollectionEventArgs)

	AddHandler Application.DocumentManager.MdiActiveDocument.Editor.PointMonitor, New PointMonitorEventHandler(AddressOf Me.EditorPointMonitor_Handler)

End Sub
	
 Private Sub EditorPointMonitor_Handler(ByVal sender As Object, ByVal e As Autodesk.AutoCAD.EditorInput.PointMonitorEventArgs)
        Dim anonymousIds As ObjectIdCollection
        Dim BlkRefs As ObjectIdCollection
        Dim fullpaths() As FullSubentityPath
        Dim BlkTblRec As BlockTableRecord
        Dim BlkName As String = ""
        Dim Blk As BlockReference
        Dim msg As String = ""
        Dim Total As Integer
        Dim value As Integer
        Dim Ent As Entity
        Dim id As ObjectId
        Dim idd As ObjectId

        Try

            Using trans = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction

                Using dlock = Application.DocumentManager.MdiActiveDocument.LockDocument

                    If Application.DocumentManager.MdiActiveDocument.Editor.IsQuiescent = False Then

                        Exit Sub

                    End If

                    Application.DocumentManager.MdiActiveDocument.Editor.TurnForcedPickOn()

                    fullpaths = e.Context.GetPickedEntities

                    If fullpaths.Length = 0 Then

                        Exit Sub

                    End If

                    Ent = trans.GetObject(fullpaths(0).GetObjectIds(0), OpenMode.ForRead)

                    If TypeOf Ent Is BlockReference Then

                        Blk = CType(Ent, BlockReference)

                        If Blk.IsDynamicBlock = True Then

                            BlkTblRec = CType(trans.GetObject(Blk.DynamicBlockTableRecord, OpenMode.ForRead), BlockTableRecord)

                            BlkName = BlkTblRec.Name

                            anonymousIds = BlkTblRec.GetAnonymousBlockIds

                            For Each id In anonymousIds

                                BlkTblRec = CType(trans.GetObject(id, OpenMode.ForRead), BlockTableRecord)

                                BlkRefs = BlkTblRec.GetBlockReferenceIds(False, False)

                                For Each idd In BlkRefs

                                    Total = Total + 1

                                Next

                            Next

                            msg = "Dynamic Block" & vbCrLf

                        Else

                            BlkName = Blk.Name

                            BlkTblRec = CType(trans.GetObject(Blk.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)

                            BlkRefs = BlkTblRec.GetBlockReferenceIds(False, False)

                            Total = BlkRefs.Count

                        End If

                        value = CShort(Application.GetSystemVariable("ROLLOVERTIPS"))

                        If Not value = 0 Then

                            Application.SetSystemVariable("ROLLOVERTIPS", 0)

                        End If

                        msg = msg & String.Format("Block Name: {0}", BlkName) & vbCrLf

                        msg = msg & String.Format("Block Inserts: {0}", Total) & vbCrLf

                        e.AppendToolTipText(msg)

                        If Not value = 0 Then

                            Application.SetSystemVariable("ROLLOVERTIPS", value)

                        End If

                    End If

                    trans.Commit()

                End Using

            End Using

        Catch ex As Exception

            System.Windows.Forms.MessageBox.Show(ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Error)

        End Try

    End Sub
	
End Class

 

 

Here are the error message I am getting

 

PM_Error1.png

 

PM_Error2.png

 

*Expert Elite*
Jeff_M
Posts: 4,194
Registered: ‎07-22-2003
Message 2 of 7 (349 Views)

Re: PointMonitorEventHandler Help

09-21-2013 09:33 AM in reply to: HJohn1

Not much help, but I can't seem to get it to crash inside Civi3d 2012. Works with dynamic blocks, regular blocks, xrefs. I will leave it running to see if it will finally fail, but for now I have no idea why it crashes for you.

Jeff_M, also a frequent Swamper
*Expert Elite*
_gile
Posts: 2,077
Registered: ‎04-29-2006
Message 3 of 7 (326 Views)

Re : PointMonitorEventHandler Help

09-22-2013 10:19 AM in reply to: HJohn1

Hi,

 

I tried to rewrite it my way, it worked fine for all the test I made.

Main changes are:

  • Adding the handler to all already opened documents when the app is loaded.
  • Checking the object type before opening it with ObjectId.ObjectClass.
  • Removing the document locking wich is not mandatory in this case.
  • Using StartOpenCloseTransaction which is cheaper and recommended within event handlers.
  • Checking if the block reference is inserted in the current space to avoid counting nestied blocks.

C# code

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

[assembly: ExtensionApplication(typeof(PointMonitorExtensionApplication.AppEventClass))]

namespace PointMonitorExtensionApplication
{
    public class AppEventClass : IExtensionApplication
    {
        DocumentCollection docMan = Application.DocumentManager;

        public void Initialize()
        {
            foreach (Document doc in docMan) doc.Editor.PointMonitor += OnPointMonitor;
            docMan.DocumentCreated += OnDocumentCreated;
        }

        void OnDocumentCreated(object sender, DocumentCollectionEventArgs e)
        {
            e.Document.Editor.PointMonitor += OnPointMonitor;
        }

        void OnPointMonitor(object sender, PointMonitorEventArgs e)
        {
            short tips = (short)Application.GetSystemVariable("ROLLOVERTIPS");
            try
            {
                Document doc = Application.DocumentManager.MdiActiveDocument;
                Database db = doc.Database;
                Editor ed = doc.Editor;
                if (!ed.IsQuiescent)
                    return;
                ed.TurnForcedPickOn();
                FullSubentityPath[] paths = e.Context.GetPickedEntities();
                if (paths.Length == 0)
                    return;
                ObjectId id = paths[0].GetObjectIds()[0];
                if (id.ObjectClass != RXClass.GetClass(typeof(BlockReference)))
                    return;
                int cnt = 0;
                string name;
                bool isDyn;
                using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
                {
                    BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
                    isDyn = br.IsDynamicBlock;
                    BlockTableRecord btr = isDyn ?
                        (BlockTableRecord)tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead) :
                        (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead);
                    name = btr.Name;
                    ObjectId cSpaceId = db.CurrentSpaceId;
                    foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false))
                    {
                        BlockReference insert = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
                        if (insert.OwnerId == cSpaceId) cnt++;
                    }
                    if (isDyn)
                    {
                        foreach (ObjectId anonId in btr.GetAnonymousBlockIds())
                        {
                            BlockTableRecord anonBtr = (BlockTableRecord)tr.GetObject(anonId, OpenMode.ForRead);
                            foreach (ObjectId brId in anonBtr.GetBlockReferenceIds(true, false))
                            {
                                BlockReference insert = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
                                if (insert.OwnerId == cSpaceId) cnt++;
                            }
                        }
                    }
                    tr.Commit();
                }
                Application.SetSystemVariable("ROLLOVERTIPS", 1);
                e.AppendToolTipText(string.Format("{0}Block Name: {1}\nBlock Inserts: {2}",
                    isDyn ? "Dynamic Block\n" : "",
                    name,
                    cnt));
            }
            catch (System.Exception exn)
            {
                Application.ShowAlertDialog(exn.Message);
            }
            finally
            {
                Application.SetSystemVariable("ROLLOVERTIPS", tips);
            }
        }

        public void Terminate() { }
    }
}

 

VB translation

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime

<Assembly: ExtensionApplication(GetType(PointMonitorExtensionApplication.AppEventClass))> 

Namespace PointMonitorExtensionApplication

    Public Class AppEventClass
        Implements IExtensionApplication

        Private docMan As DocumentCollection = Application.DocumentManager

        Public Sub Initialize() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Initialize
            For Each doc As Document In docMan
                AddHandler doc.Editor.PointMonitor, AddressOf EditorPointMonitor_Handler
            Next
            AddHandler docMan.DocumentCreated, AddressOf DocumentCreated_Handler
        End Sub

        Public Sub Terminate() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Terminate
        End Sub

        Private Sub DocumentCreated_Handler(sender As Object, e As DocumentCollectionEventArgs)
            AddHandler e.Document.Editor.PointMonitor, AddressOf EditorPointMonitor_Handler
        End Sub

        Private Sub EditorPointMonitor_Handler(sender As Object, e As PointMonitorEventArgs)
            Dim tips As Short = CShort(Application.GetSystemVariable("ROLLOVERTIPS"))
            Try
                Dim doc As Document = Application.DocumentManager.MdiActiveDocument
                Dim db As Database = doc.Database
                Dim ed As Editor = doc.Editor
                If Not ed.IsQuiescent Then
                    Return
                End If
                ed.TurnForcedPickOn()
                Dim paths As FullSubentityPath() = e.Context.GetPickedEntities()
                If paths.Length = 0 Then
                    Return
                End If
                Dim id As ObjectId = paths(0).GetObjectIds()(0)
                If id.ObjectClass <> RXClass.GetClass(GetType(BlockReference)) Then
                    Return
                End If
                Dim cnt As Integer = 0
                Dim name As String
                Dim isDyn As Boolean
                Using tr As Transaction = db.TransactionManager.StartOpenCloseTransaction()
                    Dim br As BlockReference = DirectCast(tr.GetObject(id, OpenMode.ForRead), BlockReference)
                    isDyn = br.IsDynamicBlock
                    Dim btr As BlockTableRecord = _
                        If(isDyn, _
                           DirectCast(tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead), BlockTableRecord), _
                           DirectCast(tr.GetObject(br.BlockTableRecord, OpenMode.ForRead), BlockTableRecord))
                    name = btr.Name
                    Dim cSpaceId As ObjectId = db.CurrentSpaceId
                    For Each brId As ObjectId In btr.GetBlockReferenceIds(True, False)
                        Dim insert As BlockReference = DirectCast(tr.GetObject(brId, OpenMode.ForRead), BlockReference)
                        If insert.OwnerId = cSpaceId Then
                            cnt += 1
                        End If
                    Next
                    If isDyn Then
                        For Each anonId As ObjectId In btr.GetAnonymousBlockIds()
                            Dim anonBtr As BlockTableRecord = DirectCast(tr.GetObject(anonId, OpenMode.ForRead), BlockTableRecord)
                            For Each brId As ObjectId In anonBtr.GetBlockReferenceIds(True, False)
                                Dim insert As BlockReference = DirectCast(tr.GetObject(brId, OpenMode.ForRead), BlockReference)
                                If insert.OwnerId = cSpaceId Then
                                    cnt += 1
                                End If
                            Next
                        Next
                    End If
                    tr.Commit()
                End Using
                Application.SetSystemVariable("ROLLOVERTIPS", 1)
                e.AppendToolTipText(String.Format("{0}Block Name: {1}" & vbLf & "Block Inserts: {2}", _
                                                  If(isDyn, "Dynamic Block" & vbLf, ""), _
                                                  name, _
                                                  cnt))

            Catch ex As System.Exception
                System.Windows.Forms.MessageBox.Show(ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Error)

            Finally
                Application.SetSystemVariable("ROLLOVERTIPS", tips)
            End Try

        End Sub

    End Class

End Namespace

 

Gilles Chanteau
Distinguished Contributor
HJohn1
Posts: 169
Registered: ‎09-26-2008
Message 4 of 7 (290 Views)

Re : PointMonitorEventHandler Help

09-23-2013 06:21 AM in reply to: _gile

Gilles,

Thank you for your help.  I made some modifications based on your code, but I keep on crashing.  I found that the crash occurs on the call to e.AppendToolTipText() method.  I also found the following message on the immediate window:

 

System.Windows.Media.Animation 
Warning: 6 : Unable to perform action because the specified Storyboard was never applied to this object for interactive control.; 
Action='Stop'; 
Storyboard='System.Windows.Media.Animation.Storyboard'; 
Storyboard.HashCode='9191763'; 
Storyboard.Type='System.Windows.Media.Animation.Storyboard'; 
TargetElement='Autodesk.Internal.Windows.ToolTip'; 
TargetElement.HashCode='22042256'; 
TargetElement.Type='Autodesk.Internal.Windows.ToolTip'

 Any suggestiongs?

Distinguished Contributor
HJohn1
Posts: 169
Registered: ‎09-26-2008
Message 5 of 7 (263 Views)

Re: PointMonitorEventHandler Help

09-24-2013 08:49 AM in reply to: HJohn1

Can someone using AutoCAD Mechanical please run the code I posted to see if it crashes?  I have a suspicion that it might be related to the implementation of the tool tip AC M, but I am not sure about it.

ADN Support Specialist
Balaji_Ram
Posts: 663
Registered: ‎03-21-2011
Message 6 of 7 (212 Views)

Re: PointMonitorEventHandler Help

09-29-2013 05:16 AM in reply to: HJohn1

Hi John,

 

Sorry, I havent been able to reproduce the crash during my testing.

 

I have tried the code with vanilla AutoCAD 2012 / 2014 and AutoCAD Mechanical 2014. I do not have AutoCAD Mechanical 2012 installed in my system, so could not test with that setup.

 

A few basic suggestions to narrow down the problem :

 

1) Do you have all the service packs installed ?

2) Can you please try with a sample project that does nothing but append to the tool tip text in the point monitor ?

3) Can you please try on any other system to see if it is reproducible there ?

 

Regards,

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

Distinguished Contributor
HJohn1
Posts: 169
Registered: ‎09-26-2008
Message 7 of 7 (187 Views)

Re: PointMonitorEventHandler Help

10-01-2013 07:10 AM in reply to: Balaji_Ram

Balaji thank you very much for your help.  I ran the code in another machine running AutoCAD 2014 on 64bit Windows 7 and could not get it to crash either.  There most be something on my dev machine that is making it crash.  I will run more tests on other machines.  Thank you again. 

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community