Community
Civil 3D Customization
Welcome to Autodesk’s AutoCAD Civil 3D Forums. Share your knowledge, ask questions, and explore popular AutoCAD Civil 3D Customization topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Events and modal form.. Help please.

3 REPLIES 3
SOLVED
Reply
Message 1 of 4
joantopo
360 Views, 3 Replies

Events and modal form.. Help please.

Hi.

I have added 2 event handlers in the main class of my app:

 

  class Start_app : Autodesk.AutoCAD.Runtime.IExtensionApplication
    {
        #region IExtensionApplication Members
        public void Initialize() //hace de constructor sobre la clase.
        {
     
            Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

                acDoc.Database.ObjectModified +=  MainForm.callback_ObjectModified;

                acDoc.Editor.EnteringQuiescentState += new EventHandler(MainForm.Editor_EnteringQuiescentState);
            
        }

Then I have a command in my app to show a modal form  (ShowDialog ( ) ) which has a button called [ADD].

If I press this button, the program modifies 2 points (pass through points) of a fixed line of an alignment.

 

At the end of the event of pressing this button, I have a bool global variable called "Modified_byProgramation" which is in TRUE;

 

Once is fired the last line command: form.ShowDialog(), the ObjectModified event is fired.

 

 

  public  static void callback_ObjectModified(object sender, ObjectEventArgs e)
        {


            if (variables_globales.Alin_Modified_byProgrammation ==false) 
            {

//do............

}

I don´t know to do anything inside the callback_objectModified method when I modify the object by programmation, but, how I put again the variable 

 

variables.gloables.Alin_Modified_byProgrammation= true?

 

I have noticed that Civil 3D fires 3 times the callback_objectModified after I modify an alignment by programmation but I don´t know if it will be more times in another time.

 

I would like to put the variable in true but I don´t know where I could put it.

 

Thanks.

 

 

 

 

 

Autocad C3D 2019 SP3, 2020 & 2021
Intel I9 9900K with frontal watercooler alphacool eisbaer 360 (original fans mounted in pull)- 3 fans Corsair 120 ML PRO in push.
MOBO Gygabyte Z390 Aorus Master- Corsair RGB Vengeance 64GB RAM (4x16) CL16
Nvidia Quadro RTX 4000
Samsung 970 EVO PLUS 1TB (unit C). Samsung 970 PRO 512GB (for data)
Power Supply: Corsair TX850M PLUS


Descubre mi programa VisorNET para Civil 3D:
https://apps.autodesk.com/CIV3D/es/Detail/Index?id=appstore.exchange.autodesk.com%3avisornet_windows32and64%3aes
3 REPLIES 3
Message 2 of 4
joantopo
in reply to: joantopo

Note that I have tried this:

 

Within the load_form, I have removed the event handlers:

 

 acDoc.Database.ObjectModified -=  MainForm.callback_ObjectModified;

                acDoc.Editor.EnteringQuiescentState -= new EventHandler(MainForm.Editor_EnteringQuiescentState);

And at the end of the "command_method", (after the "formulario.ShowDialog( ) ), I add again the event handlers:

 

          Anchored_Align.MainForm formulario = new Anchored_Align.MainForm();
         formulario.ShowDialog();

         acDoc.Database.ObjectModified += MainForm.callback_ObjectModified;

         acDoc.Editor.EnteringQuiescentState += new EventHandler(MainForm.Editor_EnteringQuiescentState);
   
        }

But this doesn´t work  because after that code snippet it is fired the ObjectModified method again at the same time.

Autocad C3D 2019 SP3, 2020 & 2021
Intel I9 9900K with frontal watercooler alphacool eisbaer 360 (original fans mounted in pull)- 3 fans Corsair 120 ML PRO in push.
MOBO Gygabyte Z390 Aorus Master- Corsair RGB Vengeance 64GB RAM (4x16) CL16
Nvidia Quadro RTX 4000
Samsung 970 EVO PLUS 1TB (unit C). Samsung 970 PRO 512GB (for data)
Power Supply: Corsair TX850M PLUS


Descubre mi programa VisorNET para Civil 3D:
https://apps.autodesk.com/CIV3D/es/Detail/Index?id=appstore.exchange.autodesk.com%3avisornet_windows32and64%3aes
Message 3 of 4
norman.yuan
in reply to: joantopo

It is not a good practice to tie AutoCAD process too tight with UI, especially with AutoCAD's event handling.

 

It looks like, you want to know which entity (in your case, Alignment) or entities, being modified (and then do something afterwards). Using Database.ObjectModified would in general give you chance to keep track of entities being modified.

 

In most cases, one would "sandwich" Database.ObjectModified event handler between Document.CommandWillStart (start counting by hooking up ObjectModified event handler) and DocumentCommandEnded.(end counting and remove ObjectModified event handler). After the command ends, if there is target entities changed, do something as needed.

 

If you want to do give user an UI (modal form), the process could be even easier and all the work can be separated from UI and the UI is only for getting user interaction (button clicking).

 

Say, you can have a class like this to do all the work (pseudo code):

 

public class MyClass

{

    private List<ObjectId> _modifiedEnt=new List<ObjectId>();

   

    public void ModifySomeEntities()

    {

        var db =....MdiDocument.Database;

        db.ObjectModified+=DB_ObjectModified;

        _modifiedEnts.Clear();

        

        //Do whatever you need to do with the MdiDocument/database

        try

        {

            .....

        }

        finally

        {

            db.ObjectModified-=DB_ObjectModified;

       }

    }

 

    private void DB_ObjectModified(object sender, ObjectModifiedEventArgs e)

    {       

        //Test if the modified entity is the target entity, for example:

        if (e.DBObject is xxxxxx)

        {

            if (!_modifiedEnts.Contains(e.DBObject.ObjectId) _modifiedEnts.Add(e.DBObject.ObjectId)

        }

    }

 

    public int ModifiedEntityCount

    {

        get { return _modifiedEnts.Count; }

    }

 

    public void DoExtraWork()

    {

        if (_modifiedEnts.Count==0) return;

        //Do something with changed entities

        foreach (var id in _modifiedEnts)

        {

            .....

        }

    }

}

 

Then in the modal form, assume there is a button "Do Work":

 

private btnDoWork_Click(...)

{

    var work=new MyClass();

    work.ModifySomeEntities();

    if (work.ModifiedEntityCount>0)

    {

        //Prompt user, if necessary

       ....

       //Do extra work

       work.DoExtraWork();

    }

}

 

Note, when something is modified in drawing, Database.ObjectModified could fire multiple times, depending on what type of entity being modified, especially when the entity is a complicated one, such as Civil3D entity Alignment, because its change could results in other related object change, which is not exposed to outside. That is why we need some code in the Object|Modified event handler to properly filter out the entity in interest.

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 4 of 4
joantopo
in reply to: joantopo

Great !

Right now works perfect with this code:

 

--->In the class "Start_app" I add again the event handlers for ObjectModified and EnteringQuiescentState

 

--->When I open the form with ShowDialog(), in the  form load event,  I remove these event handlers.

 

-->The last lines in the command_method will be:

 

    Anchored_Align.MainForm formulario = new Anchored_Align.MainForm();
         formulario.ShowDialog();

         variables_globales.Alin_Modified_InDrawing = false;

        
         Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
         acDoc.Database.ObjectModified += MainForm.callback_ObjectModified;
         acDoc.Editor.EnteringQuiescentState += new EventHandler(MainForm.Editor_EnteringQuiescentState);
                
        }

Look at the global variable : variables_globales.Alin_Modified_InDrawing,  must be False and must be located before adding again the event handlers.

 

So, the method for the ObjectModified event will be:

 

 public  static void callback_ObjectModified(object sender, ObjectEventArgs e)
        {
            if (variables_globales.Alin_Modified_InDrawing == true) //quiere decir que se ha modificado desde el dibujo.
            {             
                    if (e.DBObject.GetType() == typeof(Autodesk.Civil.DatabaseServices.Alignment))
                    {

                        //obtenemos el handle de la entidad que se ha modificado al dibujo.
                        ObjectId Id_align_mod = e.DBObject.Id;

                        int pos1 = variables_globales.listaGeneral.FindIndex(x => x.AL1_id == Id_align_mod);
                        int pos2 = variables_globales.listaGeneral.FindIndex(x => x.AL2_id == Id_align_mod);

                        if (pos1 >= 0 || pos2 >= 0)
                        {
                            variables_globales.Coll_IdAlins.Add(e.DBObject.Id); //pasamos el Id del eje a la lista.
                        }
                    }             
            }
        }

This method only will work if the global variable is true

variables_globales.Alin_Modified_InDrawing == true

 And it means that we are modifing an Alignment object in the drawing, not from my form.

 

In the "callback_ObjectModified" method, I check if the modified alignment in the drawing is included in my List (the registers that I add in my form) and if it is true, then I add its ObjectId to the ObjectIdCollection= variables_globales.Coll_IdAlins.Add.

 

After a ObjectModified event is always fired the EnteringQuiescentState event , so the method for the EnteringQuiescentState event is this:

 

public static void Editor_EnteringQuiescentState(object sender, EventArgs e)   //estado inactivo
        {
      
            variables_globales.Alin_Modified_InDrawing = true;


            if (variables_globales.Coll_IdAlins != null && variables_globales.Coll_IdAlins.Count > 0)
            {

                //le quitamos el event handler de objeto modificado para que no salte el evento.
                Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
                acDoc.Database.ObjectModified -= MainForm.callback_ObjectModified;


                for (int i = 0; i <= variables_globales.Coll_IdAlins.Count - 1; i++)
                {

                    for (int k = 0; k <= variables_globales.listaGeneral.Count - 1; k++)  //we check every register in the listaGeneral List
                    {
                        if (variables_globales.listaGeneral[k].AL1_id == variables_globales.Coll_IdAlins[i] || variables_globales.listaGeneral[k].AL2_id == variables_globales.Coll_IdAlins[i])
                        {
                            Proces(k, false);
                        }

                    }

                }
                variables_globales.Coll_IdAlins.Clear();

                acDoc.Database.ObjectModified += MainForm.callback_ObjectModified;

            }
        }

Look at the "Proces(k,false)" is modifying the alignment by programmation" so I have to remove the event handlers before and I have to add them after.

 

If the ObjectIdCollection has at least 1 item, then it do the "Proces(,)" method for each item. 

Due to I can have the same alignment in my List in each Register (row), we can repeat this operation for each register.

 

It is very important this line, to celar the ObjectIdCollection at the end:

variables_globales.Coll_IdAlins.Clear();

 

Autocad C3D 2019 SP3, 2020 & 2021
Intel I9 9900K with frontal watercooler alphacool eisbaer 360 (original fans mounted in pull)- 3 fans Corsair 120 ML PRO in push.
MOBO Gygabyte Z390 Aorus Master- Corsair RGB Vengeance 64GB RAM (4x16) CL16
Nvidia Quadro RTX 4000
Samsung 970 EVO PLUS 1TB (unit C). Samsung 970 PRO 512GB (for data)
Power Supply: Corsair TX850M PLUS


Descubre mi programa VisorNET para Civil 3D:
https://apps.autodesk.com/CIV3D/es/Detail/Index?id=appstore.exchange.autodesk.com%3avisornet_windows32and64%3aes

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

Post to forums  

Rail Community


 

Autodesk Design & Make Report