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

Responding to the Properties Palette

14 REPLIES 14
Reply
Message 1 of 15
Mathew.webber
989 Views, 14 Replies

Responding to the Properties Palette

Hi all,


Its my first post so go easy on me  😮

I am writing in the process of writing a AutoCAD/Civil3D plug-in (in VB.Net) product that needs current detects all of the updates (modified, erased , Unmodified, etc) on my own Entities and then only act on these once. So to this end I am maintaining a list of the affect entities and then processing the 'queue' on Document.CommandEnded.

This worked perfectly for me until I realised that the Properties Palette (and probably others) do not actually perform a command so the command end event is never caught. Obviously the queue will be processed on the next command but it looks sloppy that my data is not updated straight away.

I have seen various blog posts and a similar post on here that suggest using DocumentManager.DocumentLockModeWillChange or Editor.EnteringQuiescentState as the event to detect the end of the edit. However I am finding that no matter which of there I use I am unable to apply my Document Lock and this leads to Access Violations no matter what checks I do passed on the EventArgs.

I believe I have all the right Document locks in place, all in Using Statements so they should be disposed of correctly.

Can anyone point me in the right direction or correct the error of my ways?

Many Thanks!

Mat

14 REPLIES 14
Message 2 of 15

Hi,

 

Instead of processing them on CommandEnd, consider Database.ObjectAppended/Modified/Erased events, it works fine on Palette.

 

When you try change the database from palette, or any other modeless dialog, you need to do it through command or lock the database yourself.

 

Regards,

Augusto Goncalves

Autodesk Developer Network

Regards,



Augusto Goncalves
Twitter @augustomaia
Autodesk Developer Network
Message 3 of 15

Hi Augusto,

 

Thank you for getting back to me. Smiley Happy

 

Is there away to tell that the event has been thrown as a result of the properties box or that no other changes will occur after the current one? I have looked for this but so far no joy.

 

My issue is that I need to perfom a large number of calculations following any update to my entities. So as a normal command could lead to many of my entities being editted I need to only process them all at the end rather than as they occur, hence why i am storing them in the handlers and then processing the list in CommandEnded.

 

Thanks

 

 

Message 4 of 15

 

Does anyone have any further thoughts on this?

 

I have been looking into Overrules, but so far have been unable to find away of making them work for this problem.

Message 5 of 15
norman.yuan
in reply to: Mathew.webber

I amy understand your question wrong, but give it a try.

 

Your question is, if a user edit an entity in Propertie Window (as apposed to do it in AutoCAD editor manually, or run a command), is it possible for your application to know that one or more entities have been changed (due to the changes user made in Properties Window)?

 

If this is you want to know, read on.

 

Properties Window is just a UI tool for user to make changes to entities in drawing database. Once the changes in the properties Windows are committed, the user input will to applied to drawing database and Database.ObjectModified event will occur. This is no different from the situation when entities being modified by a command, or manully directly on Acad editor, or by your code.

 

So, simply handling Database.ObjectModified event would give you the opportunity to track which entities have been modified, regardless it is from command, or from Properties Window. Once you are able to ALWAYS know some objects are modified, then it is up to you to decide how to keep track of them and at what point after the changes your code start doing something (Make sure you are not paint yourself into corner of endless loop of Database.ObjectModified->Your code modify some entities->database.ObjectModified->Your ode modify entities->...).

 

Here code sample:

 

using aApp = Autodesk.AutoCAD.ApplicationServices.Application;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace PropWinDBObjectChange
{
    public class MyCommands
    {
        private Document _dwg = null;
        private Editor _ed = null;
        private bool _watched = false;

        [CommandMethod("WatchDB")]
        public void WatchDBChange()
        {
            if (!_watched)
            {
                if (_dwg == null)
                {
                    _dwg = aApp.DocumentManager.MdiActiveDocument;
                    _ed = _dwg.Editor;
                }

                _dwg.Database.ObjectModified += 
                    new ObjectEventHandler(Database_ObjectModified);
                _watched = true;
                _ed.WriteMessage(
                    "\nStart watching modified objects in current drawing...\n");
            }
            else
            {
                if (_dwg == null) return;

                _dwg.Database.ObjectModified -= 
                    Database_ObjectModified;
                _watched = false;
                _ed.WriteMessage(
                    "\nWatching modified objects in current drawing stopped\n");
            }
        }

        private void Database_ObjectModified(object sender, ObjectEventArgs e)
        {
            _ed.WriteMessage(
                "\nObject modified: ObjectID={0}", e.DBObject.ObjectId.ToString());
        }
    }
}

 

To see the running effect, Netload the code's DLL; draw a few circles/lines...; enter command "WatchDB" to turn the event handler on; then select different entity and make change to it in Properties Window. You can see the Database.ObjectModified event handler shows entity's ObjectID at command line. Of course, you run a command, such as "move", "stretch", the event handler will also be called.

 

Since through Property Window, user can only modify existing entities (i.e. user cannot create new entity or ersae entity from there), handling Database.ObjectModified would cover whatever change to entity user makes from Properties Window.

 

Message 6 of 15
Mathew.webber
in reply to: norman.yuan

Thanks again for your input, I do appreciate you guys taking the time to answer me.

I suspect though that I was not as clear as I could be on what the problem is. Maybe some code would help out here to highlight where I am?

 

I have added some code below below that shows my basic setup, obviously my creation of data is a bit more involved and extra data is appended as XRecords but it demostrates the problem. If you move with the cursor the line (after running DrawData) you will see the two messages (Entity Modified & Command Ended), however Properties Palette changes will only give the 'Entity Modified' message as the commanded ended in not thrown.

Public Class App
    Implements Autodesk.AutoCAD.Runtime.IExtensionApplication

    ''' <summary>
    ''' Start app
    ''' </summary>
    Public Sub Initialize() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Initialize
        'For now we will Greet the user
        ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbNewLine + "Welcome to My Test App!" + vbNewLine)

        'Add handler for CommandEnded
        AddHandler ApplicationServices.Application.DocumentManager.MdiActiveDocument.CommandEnded, AddressOf CommandEnded

    End Sub

    ''' <summary>
    ''' End App
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Terminate() Implements Autodesk.AutoCAD.Runtime.IExtensionApplication.Terminate
        'Do something....
    End Sub

    ''' <summary>
    ''' Entity has been modified
    ''' </summary>
    Public Sub EntityModified(ByVal senderObj As Object, ByVal evtArgs As EventArgs)

        Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbNewLine + "Entity Changed" + vbNewLine)

        'Store the Entity ID

    End Sub

    ''' <summary>
    ''' Command Has Ended
    ''' </summary>
    Public Sub CommandEnded(sender As Object, e As CommandEventArgs)

        Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbNewLine + "Command Ended" + vbNewLine)

        'Process the list of Entity IDs

    End Sub

    ''' <summary>
    ''' Draw my data and add handlers
    ''' </summary>
    <CommandMethod("DrawData")> _
    Public Sub DrawData()

        Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim l As Line

        'Lock the document and start a new transation
        Using dl As DocumentLock = acDoc.LockDocument()
            Using myTrans As Transaction = acDoc.TransactionManager.StartTransaction()
                ' Open Model space for write
                Using acBlkTbl As BlockTable = CType(myTrans.GetObject(acDoc.Database.BlockTableId, OpenMode.ForRead), BlockTable)
                    Using acBlkTblRec As BlockTableRecord = CType(myTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)

                        'Draw the entities in loop (for example)

                        'Just adding a single line here
                        l = New Line(New Geometry.Point3d(1, 1, 0), New Geometry.Point3d(100, 100, 0))

                        'Assign to the layer zero
                        l.LayerId = acDoc.Database.LayerZero

                        'Add handlers (only one added in demo)
                        AddHandler l.Modified, AddressOf EntityModified

                        acBlkTblRec.AppendEntity(l)
                        myTrans.AddNewlyCreatedDBObject(l, True)

                        myTrans.Commit()

                    End Using
                End Using
            End Using
        End Using

    End Sub

End Class

 
As you can see the events are all hooked up so I know exactly what changes are happening and I store these. I then process these chanegs at once in the CommandEnded event handler. However This is NOT thrown when a change is made on the properties box so this is where my code falls down.

What I need to find is another event to handle other than command ended (DocumentManager.DocumentLockModeWillChange & Editor.EnteringQuiescentState are not working for me either). Or some way of telling that an change occur as a result of the Properties box (i.e. not part of a command).

Does that help?

Message 7 of 15

Hi Matt.

I stuck at same page. I don't want to have a objectmodifed  event all the time  control my application for the sake of attribute edit .  I handled attedit command. But now user can change attribute from properties windows.Just let you know I don't think EnteringQuiescentstate will help . If you find any other solution let me know please. I ended up telling users not use properties. I feel bad. 

Janet

 

Message 8 of 15

Hi Janet,

 

I have been in conversation with ADN on the topic as i was getting nowhere. Unfortunately they got nowhere either!

 

They suggested all the things that I had tried and even gave me a break down of the events used. So far though I have found that EnteringQuiescentstateis the best option I can get. The entities updates immediately when the properties are changed, however my application does get told when the user clicks back into the drawing, which is better than nothing. So far I have found it works as per CommandEnded for all other events.

 

I simply wont get away with tell them not to edit via the properties box, so this is the best i can get for now.

 

I have asked ADN to look into a fix for this, along with the fact that the LayLockFadeCtl is not taken into account when you lock/unlock layers from code. Chances are though we are far down their list of priorities as the LayLockFadeCtrl has been an issue since the first release that contained it - 2008!

 

I hope that is of some use to you, let me know if I can help with any pointers.

Message 9 of 15
jeff
in reply to: Mathew.webber

I have not thought this threw at all or about the different scenarios and probably will not be route to take but to throw the idea out there.

 

If you are depending on on CommandEnded event could you check in Modified handler something like Document.CommandInProgress to see if object is being modified via a command and handle it there?

 

It might require setting a flag for first Modified then send command to stack and reset flag in CommandEnded event.

You can also find your answers @ TheSwamp
Message 10 of 15

Thanks for getting back to me Matt. the bad thing about [EnteringQuiescentstateis] is , it fires everytime user enter the properties window, even though nothing changed. basically everytime ,something is written in command prompt make it fires including entring/existing properties window.

Tony T is the man who  could solve these things which been disappeared for almost a year.

Well what can I say? we are stuck.

Please update if you found a trick .

All the best,

Janet.

 

Message 11 of 15
JanetDavidson
in reply to: jeff

Hello Jeff. I am not quite following . I am not a Pro

I will  rephrase the problem. Not a good writer but I do my best.

1- Matt and I don't want to have a constant object.modified event in our applicaton, because of it's overload.

2- Changing a block attribute or a layer , off the properties window doesn't fire any command. If it did we could've catch the start command event and now we could start the object.modiied event.and find what object's being modifed.

 

Now, how we could catch the entities which have been modified  off the properties window?

Now could you please re-explain what is your suggestion?

Message 12 of 15

Janet/Jeff,

 

My solution is to add three handlers to each entity (Modified, Unmodified and Erased). In each of these I record what has happened by storing the entities ObjectId and an Enum describing what happened. This then gies into a collection of object which i then process later. As you have probably seen the AutoCAD will throw a conbination of those changes at which point I only remember the most important of the events for each entity.

 

At the top of each handler I already do as Jeff suggests and check the CommandName to see if changes need to be process. I.e. 'Save' commands will cause MText objects to refresh however no changes need to be tracked for my data.

 

I then process the collection in the 'EnteringQuiescentstate' handler, which will only lead to updates if some of my object had added to the collection. So far this is working out well for me, obviously there are redudant calls to the handler, but they have minimum overheads. That said there were also redudant calls when I was using CommandEnded as not all commands would affect my entities. i.e. adjusting an entity elsewhere.

 

Ideally CommandEnded (or another event such as 'UpdatesFinished') would be thrown when changes to entities had finished either via the drawing or Properties Palette. This is unlikely to happen anytime soon though 😞

 

Does that help at all Janet?

 

Mat

 

Message 13 of 15

Thanks Mat. I started to write what you are suggesting. I hope it works for me.

Regards,

Janet.

 

Message 14 of 15
jeff
in reply to: JanetDavidson

Can't really add to aything already mentioned but you could look at Stephen Preston's Network example for using overrules.

 

 

 

You can also find your answers @ TheSwamp
Message 15 of 15

Hi Matt,

I found in ObjectArx there is an event  handler named "ModelessOperationWillStart" in Editor objct. This triggers if   Proreties window is being editted  on or no . and if we can check for OPM change properties, it would be good.

But unfortunately this is not available in API. or it is and I don't know how to implement it. in objectarx its being called OPM  ( Guess it stands for Object Properties modelss or something )

 

check here:

http://forums.autodesk.com/t5/forums/forumtopicprintpage/board-id/34/message-id/22395/print-single-m...

 

 

I am not ADN memeber. I already shoot this question here. But maybe you can ask ADN and  those Big guys and they can clarify this for us.

Let me know .

Janet.

 

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