I code in VB
I want to trap the ObjectModified event.
If I do AutoCad crashes when I close it down.
What I first did was to
Dim WithEvents CurDb as Database
but I realised that CurDb only related to the Active Document, so I removed the WithEvents and used a AddHandler, and so
In my New event (which seems to be fired the first time a execute one of my commands) I entered:-
DocMan = Application.DocumentManager
AddHandler DocMan.DocumentActivated, AddressOf DocumentActivated
AcadDoc = DocMan.MdiActiveDocument
CurDb = AcadDoc.Database
and so in my DocumentActivated I entered this code.
RemoveHandler CurDb.ObjectModified, AddressOf ObjectModified ' assuming previous CurDb
AcadDoc = DocMan.MdiActiveDocument
CurDb = AcadDoc.Database
AddHandler CurDb.ObjectModified, AddressOf ObjectModified
when I debug, I can step through this code without a problem.
but I crash exiting AutoCad
I've looked everywhere for a solution before asking you lot. Please help me again and thanks.
HI,
first idea: your EventHandler (that you create at "DocumentActivated") is not released when AutoCAD closes the document?
You should release the EventHandler for each Document when it's closing.
HTH, - alfred -
I found the problem!
FriendSub ObjectModified(ByVal sender AsObject, ByVal e As Autodesk.AutoCAD.DatabaseServices.ObjectEventArgs)
If e.DBObject.IsWriteEnabled ThenExitSub
Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbLf & e.DBObject.Id.ObjectClass.Name &
" modified")
End Sub
Application.DocumentManager.MdiActiveDocument.Editor doesn't exist when closing drawing.
please help
Now i have a new question. i wanna make a event,
when i change the start point of line in cad screen then raise event startPointChange. help me raise event.
thank you!!!
So you want to raise your own custom events. That's not an AutoCAD specific question - its generic .NET programming. I recommend searching for 'raise event' on MSDN or other Microsoft forums. For example, here is an VB.NET example from MSDN - http://msdn.microsoft.com/en-us/library/h7a2kh64%28v=vs.90%29.aspx
No, i knew how to raise event, now i wanna know where is the sub to put raise event?
in autocad drawing, when i move a object then location of it changed so i wanna know code to get the event objectLocationChange.
Basically, you can handle Database.ObjectModified event and in the event handler, you test if the modified entity is an Line type (or other type of your interest). If it is Line, then you raise your own custom event.
However, in ObjectModified event, you only know the entity was modified, but you do not know what change was made (moving/stretching, rotating...). if you want to riase your own event only when specific action (say, moving), then you need to handle other events that happen before ObjectModified, such as CommandWillStart and try to find the targeting entity (Line, in your case) and save its "before-change" state (start point/endpoint). so that in ObjectModified event handler, you can compare how the entity is changed. Man, it is quite complicated and could add huge overhead to AutoCAD, if the drawing has tons of Line entities.
Another possible approach might be to use TransformOverrule and override its TransformedBy virtue method (e.g raise your custom event from there). I have not tried as your requirement, but thought worth look into.
Norman Yuan
can you help me?
I have a line, i want if i select the line then my palette is visible. You can show me where i have register or raise event selected object?
Hi Norman!
I think it is possible to compare state of entity in two events:
1) Database.ObjectOpenedForModify - before modification
2) Database.ObjectModified - after modification
Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"
Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
you might try the below code to show palette while a line is selected.
Dim m_ps As Autodesk.AutoCAD.Windows.PaletteSet = Nothing
<CommandMethod("PS")> Public Sub PaletteShowforLine() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor 'select a line Dim peo As PromptEntityOptions = New PromptEntityOptions(vbLf & "Select a Line:") Dim per As PromptEntityResult = ed.GetEntity(peo) If per.Status <> PromptStatus.OK Then Return End If 'start transaction Using tx As Transaction = db.TransactionManager.StartTransaction() 'get the entity Dim ent As Entity = tx.GetObject(per.ObjectId, OpenMode.ForRead) 'if entity type is line the raise the palette event If TypeOf ent Is Line Then PaletteShow() End If tx.Commit() End Using End Sub Public Sub PaletteShow() 'palette show event If m_ps Is Nothing Then m_ps = New Autodesk.AutoCAD.Windows.PaletteSet("My Palette") Dim userCtrl As UserControl1 = New UserControl1() m_ps.Add("My Palette", userCtrl) End If m_ps.Visible = True End Sub
no. I mean i don't wanna to use editor.prompt. In the drawing, i click a random object then my palette will show although i don't send command to command line.
In that case you have to add editor event handler. you can start with below code:
Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor 'add handler for selection added AddHandler ed.SelectionAdded, AddressOf LineSelection Public Sub LineSelection(sender As Object, e As SelectionAddedEventArgs) For Each id As ObjectId In e.AddedObjects.GetObjectIds Using tx As Transaction = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction() Dim ent As Entity = tx.GetObject(id, OpenMode.ForRead) If TypeOf ent Is Line Then 'add palette show up event End If End Using Next End Sub
Thank you Alex for prompting me the ObjectOpenedForModify event. Yes, it can be used in conjunction with ObjectModified to watch specific entities being changed.
To 01688686718:
I put together some code quickly that watches Line entitiy or entities being changed:
using System.Collections.Generic; using System.Linq; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; [assembly: CommandClass(typeof(ObjectModifiedTest.MyCommands))] namespace ObjectModifiedTest { public class LineInfo { public ObjectId LineId { private set; get; } public Point3d StartPoint { private set; get; } public Point3d EndPoint { private set; get; } public bool Changed { private set; get; } public LineInfo(Line line) { LineId = line.ObjectId; StartPoint = line.StartPoint; EndPoint = line.EndPoint; Changed = false; } public void TestChange(Line line) { if (line.ObjectId == this.LineId && (line.StartPoint != this.StartPoint && line.EndPoint != this.EndPoint)) Changed = true; else Changed = false; } } public class MyCommands { private Dictionary<ObjectId, LineInfo> _modifiedLines = null; private bool _watch = false; [CommandMethod("WatchLine")] public void RunMyCommand() { Document dwg = Application.DocumentManager.MdiActiveDocument; Editor ed = dwg.Editor; if (!_watch) { StartWatchLineChange(dwg); _watch = true; } else { _watch = false; StopWatchLineChange(dwg); } Autodesk.AutoCAD.Internal.Utils.PostCommandPrompt(); } private void StartWatchLineChange(Document dwg) { dwg.CommandWillStart += dwg_CommandWillStart; dwg.CommandEnded += dwg_CommandEnded; dwg.Editor.WriteMessage("\nLine change watching is on."); } private void dwg_CommandWillStart(object sender, CommandEventArgs e) { Database db = HostApplicationServices.WorkingDatabase; _modifiedLines = new Dictionary<ObjectId, LineInfo>(); db.ObjectOpenedForModify += Database_ObjectOpenedForModify; db.ObjectModified += Database_ObjectModified; } private void dwg_CommandEnded(object sender, CommandEventArgs e) { if (e.GlobalCommandName.ToUpper().Contains("WATCHLINE")) return; Database db = HostApplicationServices.WorkingDatabase; db.ObjectOpenedForModify -= Database_ObjectOpenedForModify; db.ObjectModified -= Database_ObjectModified; ShowChangedLines(); } private void Database_ObjectModified(object sender, ObjectEventArgs e) { if (e.DBObject is Line) { if (_modifiedLines.ContainsKey(e.DBObject.ObjectId)) { _modifiedLines[e.DBObject.ObjectId].TestChange(e.DBObject as Line); } } } private void Database_ObjectOpenedForModify(object sender, ObjectEventArgs e) { if (e.DBObject is Line) { if (!_modifiedLines.ContainsKey(e.DBObject.ObjectId)) { _modifiedLines.Add( e.DBObject.ObjectId, new LineInfo(e.DBObject as Line)); } } } private void ShowChangedLines() { Document dwg = Application.DocumentManager.MdiActiveDocument; Editor ed = dwg.Editor; foreach (var info in (from item in _modifiedLines select item.Value)) { ed.WriteMessage( "\nLine {0} changed: {1}", info.LineId.ToString(), info.Changed.ToString()); } } private void StopWatchLineChange(Document dwg) { dwg.CommandWillStart -= dwg_CommandWillStart; dwg.CommandEnded -= dwg_CommandEnded; dwg.Editor.WriteMessage("\nLine change watching is off."); } } }
Please note the command method is NOT a static method, so that the _modifiedLines Dictionary is instantiated by "per document". That is, the event halders are added/removed "per document" when "WATCHLINE" command is executed.
Norman Yuan
thank you. but my problem don't solve. i do like your post but when i move mouse over my entity, my palette show again. i can't control it. this is my code:
Public Sub show()
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim tran As Transaction = db.TransactionManager.StartTransaction
Dim bt As BlockTable = tran.GetObject(db.BlockTableId, OpenMode.ForRead)
Dim btr As BlockTableRecord = tran.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
objIdCol.Add(btr.AppendEntity(dt))
objIdCol.Add(btr.AppendEntity(ht))
objIdCol.Add(btr.AppendEntity(sh))
'AddHandler HostApplicationServices.WorkingDatabase.ObjectModified, AddressOf HandleEndPointChange
'AddHandler HostApplicationServices.WorkingDatabase.ObjectModified, AddressOf HandleStartPointChange
'AddHandler HostApplicationServices.WorkingDatabase.ObjectModified, AddressOf HandleCircleCenterChange
'AddHandler HostApplicationServices.WorkingDatabase.ObjectModified, AddressOf HandleShLocationChange
AddHandler ed.SelectionAdded, AddressOf LineSelection
tran.AddNewlyCreatedDBObject(dt, True)
tran.AddNewlyCreatedDBObject(ht, True)
tran.AddNewlyCreatedDBObject(sh, True)
tran.Commit()
tran.Dispose()
End Sub
Private Sub LineSelection(ByVal sender As Object, ByVal e As SelectionAddedEventArgs)
For Each id As ObjectId In e.AddedObjects.GetObjectIds
If objIdCol.Contains(id) Then
Using tx As Transaction = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction()
Dim ent As Entity = tx.GetObject(id, OpenMode.ForRead)
If TypeOf ent Is Line Then
'add palette show up event
Dim pl As New Container1
pl.InP = Me
pl.hienthi()
End If
End Using
End If
Next
End Sub
when i wanna unselect a object, what event i must use? Does event is SelectionRemoved?
i hope you can help me handle event deselection such as selectionRemoved