Author Topic: Need event handler help  (Read 7495 times)

0 Members and 1 Guest are viewing this topic.

BillZndl

  • Guest
Need event handler help
« on: July 06, 2010, 04:39:42 PM »
VS2008 AcadR2006 Net2.0

I'm adding a CommandWillStart event handler in the DocumentCreated event and removing it on the Document to be destroyed event.

Code: [Select]
void DocumentManager_DocumentCreated(object sender, DocumentCollectionEventArgs e)
        {
            MessageBox.Show("Added.");
            e.Document.CommandWillStart += new CommandEventHandler(Document_CommandWillStart);           
        }

        void DocumentManager_DocumentToBeDestroyed(object sender, DocumentCollectionEventArgs e)
        {
            MessageBox.Show("Removed.");
            if (e.Document != null)
                e.Document.CommandWillStart -= new CommandEventHandler(Document_CommandWillStart);               
        }

Then in the CommandWillStart handler, I add some command ended event handlers if the command name is "GROUP"

Code: [Select]
void Document_CommandWillStart(object sender, CommandEventArgs e)
        {
            MessageBox.Show(e.GlobalCommandName);
           
            if (e.GlobalCommandName == "GROUP")
            {
                MessageBox.Show("Load reactors.");
                AcadApp.DocumentManager.MdiActiveDocument.CommandCancelled += new CommandEventHandler(MdiActiveDocument_CommandEnded);
                AcadApp.DocumentManager.MdiActiveDocument.CommandEnded += new CommandEventHandler(MdiActiveDocument_CommandEnded);
                AcadApp.DocumentManager.MdiActiveDocument.CommandFailed += new CommandEventHandler(MdiActiveDocument_CommandEnded);
                AcadApp.DocumentManager.MdiActiveDocument.Database.ObjectAppended += new ObjectEventHandler(Database_ObjectAppended);
            }

        }

Then in the command ended event handler I remove the command events and add a date to the list of new groups:
Code: [Select]
void MdiActiveDocument_CommandEnded(object sender, CommandEventArgs e)
        {
            removeEventHandlers();
            GroupDate GRD = new GroupDate();             
           
            foreach (ObjectId oid in Module.GrpInfoTbl)
            {
                GRD.NewDate(oid);
                Module.GrpInfoTbl.Remove(oid);
            }                       
        }

I am only removing the command events and database append events here:
Code: [Select]
void removeEventHandlers()
        {
            MessageBox.Show("Remove reactors.");

            AcadApp.DocumentManager.MdiActiveDocument.CommandCancelled -= new CommandEventHandler(MdiActiveDocument_CommandEnded);
            AcadApp.DocumentManager.MdiActiveDocument.CommandEnded -= new CommandEventHandler(MdiActiveDocument_CommandEnded);
            AcadApp.DocumentManager.MdiActiveDocument.CommandFailed -= new CommandEventHandler(MdiActiveDocument_CommandEnded);
            AcadApp.DocumentManager.MdiActiveDocument.Database.ObjectAppended -= new ObjectEventHandler(Database_ObjectAppended);
        }


This all works as expected on the first time around, but on a second try, the CommandWillStart event handler doesn't respond.  :ugly:

When I leave the drawing, the doc to be destroyed event removes the CommandWillStart event handler as expected.
Shouldn't the Command Will Start event still work after the removeEventHandlers(); removes the command ended events?
What am I missing?

TIA






Glenn R

  • Guest
Re: Need event handler help
« Reply #1 on: July 06, 2010, 04:58:32 PM »
You need to show the code where you are setting the DocumentCreated and DocumentDestroyed event handlers.

Glenn R

  • Guest
Re: Need event handler help
« Reply #2 on: July 06, 2010, 05:01:28 PM »
Also, what do you mean by, 'second try'?

BillZndl

  • Guest
Re: Need event handler help
« Reply #3 on: July 06, 2010, 05:06:38 PM »
Okay,

This is in a modeless form.

Code: [Select]
private void AddEventHandlersToActiveDoc()
        {
            try
            {
                DocumentCollection documents = AcadApp.DocumentManager;

                foreach (Document Document in documents)
                {
                    Document.CommandWillStart += new CommandEventHandler(Document_CommandWillStart);                   
                }

                AcadApp.DocumentManager.DocumentActivated += new DocumentCollectionEventHandler(DocumentManager_DocumentActivated);               
                AcadApp.DocumentManager.DocumentCreated += new DocumentCollectionEventHandler(DocumentManager_DocumentCreated);
                AcadApp.DocumentManager.DocumentToBeDestroyed += new DocumentCollectionEventHandler(DocumentManager_DocumentToBeDestroyed);
            }
            catch (Exception exception)
            {
                MessageBox.Show(" EventHandlers kaputt! " + exception);
            }
        }

And:

Code: [Select]
protected override void OnLoad(EventArgs e)
        {
            try
            {
                base.OnLoad(e);
                AcadApp.SetSystemVariable("PickStyle", 3);
                button10.BackColor = System.Drawing.Color.Honeydew;
                button10.Text = "Toggle PickStyle: 3";
                AddEventHandlersToActiveDoc();               
            }
            catch (Exception ex)
            {
                MessageBox.Show("OnLoad: " + ex.StackTrace);
            }
        }   


Second try means the first time I start the group command (or any other command) the commandWillStart reponds and if "GROUP",
adds the commandEnded events,
and the command ended event handler removes the command ended events and adds the dates to the groups.

After that, no matter what command I start, there is no more adding events or any things that tells me that the commandWillStart event handler
is doing anything at all.

Make sense?



Bryco

  • Water Moccasin
  • Posts: 1882
Re: Need event handler help
« Reply #4 on: July 06, 2010, 05:19:05 PM »
removeEventHandlers(); shouldn't this only be called if the command name was Group

Glenn R

  • Guest
Re: Need event handler help
« Reply #5 on: July 06, 2010, 05:29:41 PM »
Bryco, I think it's implicit in that they only get added when the 'group' command is triggered, therefore they are only removed because the 'group' command was called.

I'm very sceptical of using a modeless form, as well as using its Onload event to add acad events, especially the higher ones like created and destroyed. these are usually done in IExTensionApplication's initialise and terminate events.

BillZndl

  • Guest
Re: Need event handler help
« Reply #6 on: July 06, 2010, 09:19:35 PM »
I'm very sceptical of using a modeless form, as well as using its Onload event to add acad events, especially the higher ones like created and destroyed. these are usually done in IExTensionApplication's initialise and terminate events.

Hmmm, so this could be just a modeless form issue?  :oops:

Now that you mention it,
I remember reading about using the IExtensionApplication's initialise to load the event monitors
and there is one in this project so I'll try that next.

My previous crashing problems boiled down to not using the event handlers correctly,
so been working on adding and removing them as suggested on some web search results.

Would a pallet set be a better choice than a modeless dialog?
The need is to have a listview "up" and visible along with the visual display (picture box),
as we create new "groups" in AutoCAD so we can update things dynamically.

Oh and any comments on what, if anything, should be done in the terminate event would be appreciated.

Thanks.



It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8659
  • AKA Daniel
Re: Need event handler help
« Reply #7 on: July 06, 2010, 10:34:55 PM »
have a look here.. its been a long time since I've done c# soooo ...

command
Code: [Select]

using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
[assembly: CommandClass(typeof(CsMgdAcad1.Commands))]
[assembly: ExtensionApplication(typeof(CsMgdAcad1.ExtensionApp))]

namespace CsMgdAcad1
{

  public class ExtensionApp : Autodesk.AutoCAD.Runtime.IExtensionApplication
  {
    static DocEvents loader = new DocEvents();
    public void Initialize()
    {
      try
      {
        loader.Do();
      }
      catch(System.Exception ex)
      {
        Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.
          MdiActiveDocument.Editor.WriteMessage(ex.Message);
      }
    }

    public void Terminate()
    {
      loader.Undo();
    }
  }

  //
  public static class Commands
  {
    [CommandMethod("addstart", CommandFlags.Modal)]
    public static void naddstart()
    {
      foreach(KeyValuePair<Document,CmdEvents> item in DocEvents.docs)
      {
        item.Value.DoStart();
        Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.
          MdiActiveDocument.Editor.WriteMessage(item.Key.Name);
      }
    }

    [CommandMethod("killstart", CommandFlags.Modal)]
    public static void nkillstart()
    {
      foreach (KeyValuePair<Document, CmdEvents> item in DocEvents.docs)
      {
        item.Value.UndoStart();
        Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.
          MdiActiveDocument.Editor.WriteMessage(item.Key.Name);
      }
    }

    [CommandMethod("addend", CommandFlags.Modal)]
    public static void naddend()
    {
      foreach(KeyValuePair<Document,CmdEvents> item in DocEvents.docs)
      {
        item.Value.DoEnd();
        Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.
          MdiActiveDocument.Editor.WriteMessage(item.Key.Name);
      }
    }

    [CommandMethod("killend", CommandFlags.Modal)]
    public static void nkillend()
    {
      foreach (KeyValuePair<Document, CmdEvents> item in DocEvents.docs)
      {
        item.Value.UndoEnd();
        Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.
          MdiActiveDocument.Editor.WriteMessage(item.Key.Name);
      }
    }
  }
}

doc reactor
Code: [Select]
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace CsMgdAcad1
{
  public class DocEvents
  {
    public static Dictionary<Document, CmdEvents> docs = new Dictionary<Document, CmdEvents>();
    private bool m_bDone;
    //
    public DocEvents()
    {
      m_bDone = false;
    }

    public void Do()
    {
      if (m_bDone)
        return;
      m_bDone = true;
      try
      {
        foreach (Document doc in acadApp.DocumentManager)
        {
          if (!docs.ContainsKey(doc))
          {
            CmdEvents evnt = new CmdEvents(doc);
            evnt.DoStart();
            evnt.DoEnd();
            evnt.DoCancel();
            docs.Add(doc, evnt);
          }
        }
        acadApp.DocumentManager.DocumentCreated +=
        new DocumentCollectionEventHandler(onDocumentCreated);

        acadApp.DocumentManager.DocumentToBeDestroyed +=
          new DocumentCollectionEventHandler(onDocumentToBeDestroyed);
      }
      catch (System.Exception ex)
      {
        acadApp.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message);
      }
    }
    public void Undo()
    {
      if (!m_bDone)
        return;
      try
      {
        foreach (Document doc in acadApp.DocumentManager)
        {
          if (docs.ContainsKey(doc))
          {
            docs[doc].UndoStart();
            docs[doc].UndoEnd();
            docs[doc].UndoCancel();
            docs.Remove(doc);
          }
        }
        acadApp.DocumentManager.DocumentCreated -=
        new DocumentCollectionEventHandler(onDocumentCreated);

        acadApp.DocumentManager.DocumentToBeDestroyed -=
          new DocumentCollectionEventHandler(onDocumentToBeDestroyed);
      }
      catch (System.Exception ex)
      {
        acadApp.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message);
      }

      m_bDone = false;
    }

    static void onDocumentCreated(object sender, DocumentCollectionEventArgs e)
    {
      if (!docs.ContainsKey(e.Document))
      {
        CmdEvents evnt = new CmdEvents(e.Document);
        evnt.DoStart();
        evnt.DoEnd();
        evnt.DoCancel();
        docs.Add(e.Document, evnt);
      }
    }

    static void onDocumentToBeDestroyed(object sender, DocumentCollectionEventArgs e)
    {
      if (docs.ContainsKey(e.Document))
      {
        docs[e.Document].UndoStart();
        docs[e.Document].UndoEnd();
        docs[e.Document].UndoCancel();
        docs.Remove(e.Document);
      }
    }
  }
}

command reactor
Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace CsMgdAcad1
{
  public class CmdEvents
  {
    private bool m_Start;
    private bool m_End;
    private bool m_Cancel;
    private Document m_doc;
    //
    public CmdEvents(Document doc)
    {
      m_Start = false;
      m_End = false;
      m_Cancel = false;
      m_doc = doc;
    }

    public void DoStart()
    {
      if (m_Start)
        return;
      m_Start = true;
      m_doc.CommandWillStart +=
        new CommandEventHandler(MdiActiveDocument_CommandWillStart);
    }

    public void DoEnd()
    {
      if (m_End)
        return;
      m_End = true;
      m_doc.CommandEnded +=
        new CommandEventHandler(MdiActiveDocument_CommandEnded);
    }

    public void DoCancel()
    {
      if (m_Cancel)
        return;
      m_Cancel = true;
      m_doc.CommandCancelled +=
        new CommandEventHandler(MdiActiveDocument_CommandCancelled);

    }

    public void UndoStart()
    {
      if (!m_Start)
        return;
      m_doc.CommandWillStart -=
        new CommandEventHandler(MdiActiveDocument_CommandWillStart);
      m_Start = false;
    }

    public void UndoEnd()
    {
      if (!m_End)
        return;
      m_doc.CommandEnded -=
        new CommandEventHandler(MdiActiveDocument_CommandEnded);
      m_End = false;
    }

    public void UndoCancel()
    {
      if (!m_Cancel)
        return;
      m_doc.CommandCancelled -=
        new CommandEventHandler(MdiActiveDocument_CommandCancelled);
      m_Cancel = false;
    }

    private void MdiActiveDocument_CommandWillStart(object sender, CommandEventArgs e)
    {
      m_doc.Editor.WriteMessage("\n*start*\n");
    }
    private void MdiActiveDocument_CommandEnded(object sender, CommandEventArgs e)
    {
      m_doc.Editor.WriteMessage("\n*nend*\n");
    }
    private void MdiActiveDocument_CommandCancelled(object sender, CommandEventArgs e)
    {
      m_doc.Editor.WriteMessage("\n*ncancel*\n");
    }
  }
}
« Last Edit: July 08, 2010, 12:00:05 AM by Daniel »

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8659
  • AKA Daniel
Re: Need event handler help
« Reply #8 on: July 06, 2010, 10:48:58 PM »
BTY this "should" work from  a modeless dialog or palette as well,  load/unload using IExtensionApplication

BillZndl

  • Guest
Re: Need event handler help
« Reply #9 on: July 07, 2010, 01:17:43 PM »
BTY this "should" work from  a modeless dialog or palette as well,  load/unload using IExtensionApplication

Thanks. I'm just not sure how to handle this with "command methods".
Presently, I netload the dll for the form and use a command method to display it,
then in the calling class I add the event handlers.
Code: [Select]
public class Initialization : Autodesk.AutoCAD.Runtime.IExtensionApplication
    {
        public void Initialize()
        {
            try
            {
                PartMonitor.Instance.AddEventHandlersToActiveDocs();               
                Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
                ed.WriteMessage(" PartMon .... Loaded.");
                Utils.PostCommandPrompt();
            }
            catch (System.Exception ex)
            {
                Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
                ed.WriteMessage(" PartMon - Failed: " + ex.ToString());
                throw;
            }
        }
        public void Terminate()
        {
        }
    }

I didn't try your code posting yet as I'm still a bit of a newbie and will have to work through it over time.

Everything I did works as advertised except that when I use the removeEventHandlers(); in the commandEnded handler,
the Document_CommandWillStart goes dead and will not load the command event handlers anymore, after the first time around.

Again, It will take me awhile to work through this so....

Thanks again.





Glenn R

  • Guest
Re: Need event handler help
« Reply #10 on: July 07, 2010, 03:04:20 PM »
Can you post a cut down solution that exhibits the problem?

BillZndl

  • Guest
Re: Need event handler help
« Reply #11 on: July 07, 2010, 03:53:08 PM »
Can you post a cut down solution that exhibits the problem?

Sure.
I'll see if I can remmber how to download to this site.

PartGroupsMonitor.cs has the event handling stuff and PartMonitor.cs is where the initialise is.
The dll should be in the zip too.

Just open a new drawing and make a few lines.
Open the Group dialog and type a name and hit the "new" button.
Select a line hit enter to return to the dialog and then hit okay to exit the dialog.
Open Group dialog again and repeat.
Always hit okay to leave the Group dialog before repeating.

Now look in the group dialog and pick the groups you have made in the group list.
Notice only the first group made has a date in the desciption field and
that the command line prompts from the handlers are only in the first during creation of the first group.

Thanks.


BillZndl

  • Guest
Re: Need event handler help
« Reply #12 on: July 07, 2010, 03:53:51 PM »
Oh, the zip is called EventHandling.zip.

Glenn R

  • Guest
Re: Need event handler help
« Reply #13 on: July 07, 2010, 04:04:29 PM »
Ah...what zip? I don't see one attached to your post...

BillZndl

  • Guest
Re: Need event handler help
« Reply #14 on: July 07, 2010, 04:07:50 PM »
Ah...what zip? I don't see one attached to your post...

I could've attached it to my post?  Sheesh, I didn't know that.

I uploaded it to the lily pond (I think  :lol: ).