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
Hi,
I tried to rewrite it my way, it worked fine for all the test I made.
Main changes are:
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,
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?
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.
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 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.