Author Topic: Object Events  (Read 12689 times)

0 Members and 1 Guest are viewing this topic.

BlackBox

  • King Gator
  • Posts: 3770
Object Events
« on: September 27, 2012, 01:06:39 PM »
After some much needed clarification on DocumentCollection Events in another thread, I thought I'd start learning more about Events in general in a similar way that I learned Visual LISP Reactors... So I am taking aspects of my LISP library that we use daily for production, and attempting to both port the code to C#, and enhance where possible.

Perhaps I am still just naive to the AutoCAD .NET API, but I was shocked when I looked into Autodesk.AutoCAD.DatabaseService.Viewport and found no Events at all... When I was hoping, anticipating, expecting to find some pseudo ViewportActivated, ViewportToBeActivated, ViewportDeactivated, ViewportToBeDeactivated, etc. Events.

Now, in my Visual LISP Reactor, I am relegated to using a callback to check for MSpace Object to detect when a PViewport is active.

To replicate this functionality (which works fine, again, I'm just trying to learn porting existing code) in C#, should I follow the same logic by registering (+=) a CommandEnded Event handler, etc.... or am I missing something?

TIA
"How we think determines what we do, and what we do determines what we get."

TheMaster

  • Guest
Re: Object Events
« Reply #1 on: September 28, 2012, 09:26:25 PM »
After some much needed clarification on DocumentCollection Events in another thread, I thought I'd start learning more about Events in general in a similar way that I learned Visual LISP Reactors... So I am taking aspects of my LISP library that we use daily for production, and attempting to both port the code to C#, and enhance where possible.

Perhaps I am still just naive to the AutoCAD .NET API, but I was shocked when I looked into Autodesk.AutoCAD.DatabaseService.Viewport and found no Events at all... When I was hoping, anticipating, expecting to find some pseudo ViewportActivated, ViewportToBeActivated, ViewportDeactivated, ViewportToBeDeactivated, etc. Events.

Now, in my Visual LISP Reactor, I am relegated to using a callback to check for MSpace Object to detect when a PViewport is active.

To replicate this functionality (which works fine, again, I'm just trying to learn porting existing code) in C#, should I follow the same logic by registering (+=) a CommandEnded Event handler, etc.... or am I missing something?

TIA

I think the CVPORT system variable will tell you when the active viewport has changed, that is assuming that the SystemVariableChanged event fires when it changes (it doesn't fire for all system variables).

BlackBox

  • King Gator
  • Posts: 3770
Re: Object Events
« Reply #2 on: September 29, 2012, 01:07:54 AM »
Thanks for the reply, Tony.

My existing VL code uses ActiveSpace Object in lieu of CVPORT, but I greatly appreciate the tip about the Variable Changed event.
"How we think determines what we do, and what we do determines what we get."

BlackBox

  • King Gator
  • Posts: 3770
Re: Object Events
« Reply #3 on: October 05, 2012, 02:59:42 PM »
After testing a combination of both TILEMODE and CVPORT to account for three conditions (i.e., ModelSpace, PaperSpace, and PViewport Active), the SystemVariableChanged event misfires when switching from Model Tab to Layout* Tab, but does fire correctly when switching from PViewport Active to PaperSpace.

The behavior I am observing, is that when switching from Model Tab (CVPORT = 2), to the only Layout Tab in my test drawing (CVPORT = 1), the SystemVariableChanged Event fires as I switch to Layout Tab, CVPORT is queried with a value of 2 (Model Tab) prior to the tab actually having been switched.

My thought is to continue with my original VL coding logic (which was very successful over the past couple of years), by monitoring CommandEnded Event for:

Code - C#: [Select]
  1.         public static void Document_CommandEnded(Object sender, CommandEventArgs e)
  2.         {
  3.             if (Utils.WcMatch(e.GlobalCommandName.ToUpper(),
  4.                 "*CHSPACE,*MSPACE,*PSPACE,LAYOUT_CONTROL,U,*UNDO,*VPMAX,*VPMIN"))
  5.             {
  6.                // ...
  7.             }
  8.         }
  9.  

... But I still require an effective test expression for determining the Active Space.

I found an example that I believe can be modified to suite my needs, but I wondered if this may be a good place to employ StartOpenCloseTransaction()?

Obviously not much (if any) documentation on this, only going from others' posts on the topic to the best of my understanding.

Am I correct in that when using StartOpenCloseTransaction() that I need not use Commit()? Also, as this is going to be employed across all open Documents, is there any advise on using this method for testing Active Space that will allow me to avoid errors (not that I've experienced any yet, just new to .NET and want to do a bit of CYA)?

As I understand it, I'd only need to open BlockTableRecord ForRead to query the active space's Name Property, then end the Transaction... Perhaps something like:

Code - C#: [Select]
  1. // ...
  2.             Document doc = Application.DocumentManager.MdiActiveDocument;
  3.             Editor ed = doc.Editor;
  4.             Database db = doc.Database;
  5.  
  6.             Transaction tr =
  7.                 db.TransactionManager.StartOpenCloseTransaction();
  8.  
  9.             using (tr)
  10.             {
  11.                 BlockTable bt =
  12.                   (BlockTable)tr.GetObject(
  13.                     db.BlockTableId,
  14.                     OpenMode.ForRead
  15.                   );
  16.  
  17.                 BlockTableRecord btr =
  18.                   (BlockTableRecord)tr.GetObject(
  19.                     db.CurrentSpaceId,
  20.                     OpenMode.ForRead
  21.                   );
  22.  
  23.                 ed.WriteMessage("\n** " + btr.Name + " ** \n");
  24.             }
  25. // ...
  26.  

TIA

"How we think determines what we do, and what we do determines what we get."

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Object Events
« Reply #4 on: October 05, 2012, 11:23:57 PM »
After testing a combination of both TILEMODE and CVPORT to account for three conditions (i.e., ModelSpace, PaperSpace, and PViewport Active), the SystemVariableChanged event misfires when switching from Model Tab to Layout* Tab, but does fire correctly when switching from PViewport Active to PaperSpace.

The behavior I am observing, is that when switching from Model Tab (CVPORT = 2), to the only Layout Tab in my test drawing (CVPORT = 1), the SystemVariableChanged Event fires as I switch to Layout Tab, CVPORT is queried with a value of 2 (Model Tab) prior to the tab actually having been switched.

I not sure I follow exactly what your saying but it is very easy for me to be confused.
Are you saying when switching from model tab to a layout tab the SystemVariableChanged event is not firing at all or you saying it is not firing for CVPORT?
When switching tabs I think the SystemVariableChanged event should fire for TILEMODE.
Using MdbDbg event thingy TILEMODE is changed when switching between any tabs(although the value is same when switching between 2 paperspace tabs it still fires) looks like a VIEWBACKSTATUS changes also but have no idea what its doing.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Object Events
« Reply #5 on: October 05, 2012, 11:42:00 PM »
Turning Application events on in MgdDbg here is what I get
Also depending on how many viewports, viewport properties, system variables like LAYOUTREGENCTL, etc..... will probably cause different results.
 
 
switching from model to paper tab
Code: [Select]

 Command:   <Switching to: Layout1>
[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : CLAYER
[App Event] : System Var Changed        : CLAYER
[App Event] : System Var Changing       : TILEMODE
[App Event] : System Var Changed        : TILEMODE
[App Event] : System Var Changing       : REGENMODE
[App Event] : System Var Changed        : REGENMODE
[App Event] : System Var Changing       : REGENMODE
[App Event] : System Var Changed        : REGENMODERestoring cached viewports - Regenerating layout.
[App Event] : System Var Changing       : VIEWBACKSTATUS
[App Event] : System Var Changed        : VIEWBACKSTATUS

 
Switching from paper to another paper
Code: [Select]

 Command:   <Switching to: Layout2>
[App Event] : System Var Changing       : VIEWBACKSTATUS
[App Event] : System Var Changed        : VIEWBACKSTATUS
[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : CLAYER
[App Event] : System Var Changed        : CLAYER
[App Event] : System Var Changing       : UCSNAME
[App Event] : System Var Changed        : UCSNAME
[App Event] : System Var Changing       : PSLTSCALE
[App Event] : System Var Changed        : PSLTSCALE
[App Event] : System Var Changing       : PLIMCHECK
[App Event] : System Var Changed        : PLIMCHECK
[App Event] : System Var Changing       : PINSBASE
[App Event] : System Var Changed        : PINSBASE
[App Event] : System Var Changing       : PLIMMIN
[App Event] : System Var Changed        : PLIMMIN
[App Event] : System Var Changing       : PLIMMAX
[App Event] : System Var Changed        : PLIMMAX
[App Event] : System Var Changing       : PEXTMIN
[App Event] : System Var Changed        : PEXTMIN
[App Event] : System Var Changing       : PEXTMAX
[App Event] : System Var Changed        : PEXTMAX
[App Event] : System Var Changing       : TILEMODE
[App Event] : System Var Changed        : TILEMODE
[App Event] : System Var Changing       : REGENMODE
[App Event] : System Var Changed        : REGENMODE
[App Event] : System Var Changing       : REGENMODE
[App Event] : System Var Changed        : REGENMODERestoring cached viewports - Regenerating layout.
[App Event] : System Var Changing       : VIEWBACKSTATUS
[App Event] : System Var Changed        : VIEWBACKSTATUS

 
Switching from paper to model
Code: [Select]

Command:   <Switching to: Model>
[App Event] : System Var Changing       : VIEWBACKSTATUS
[App Event] : System Var Changed        : VIEWBACKSTATUS
[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : NAVBARDISPLAY
[App Event] : System Var Changed        : NAVBARDISPLAY
[App Event] : System Var Changing       : CLAYER
[App Event] : System Var Changed        : CLAYER
[App Event] : System Var Changing       : UCSNAME
[App Event] : System Var Changed        : UCSNAME
[App Event] : System Var Changing       : TILEMODE
[App Event] : System Var Changed        : TILEMODERestoring cached viewports.
[App Event] : System Var Changing       : UCSNAME
[App Event] : System Var Changed        : UCSNAME

BlackBox

  • King Gator
  • Posts: 3770
Re: Object Events
« Reply #6 on: October 06, 2012, 04:16:24 AM »
Sorry for any confusion, Jeff.

Put simply, I'm trying to identify the active space... Model Tab, Layout Tab (PViewport inactive), Layout Tab (PViewport active).

My VL code uses a command reactor's CommandEnded Event to test for the WCMATCH string posted above, and qualifies the active space to perform one of three actions (one for each condition).

The SystemVariableChanged Event fires, it's just that Tony's warning holds true for CVPORT; perhaps an alternative to using the CommandEnded Event is to use a LayoutActivated Event (not tested, just read up on a bit today).

Also, thanks for educating me about MgdDbg... Never heard of that before... Found an ADN article & DevCast that goes over ArxDbg, MgdDbg, and Inspector.

Cheers! :beer:
"How we think determines what we do, and what we do determines what we get."

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Object Events
« Reply #7 on: October 06, 2012, 04:48:22 AM »
MgdDbg is a must have.
 
 
Do you have to know when they change or just need to know what action to take in a method depending on which space is active?
 
Also if your inside a viewport or the viewport is active then Database.CurrentSpaceId will return ModelSpaces ObjectID.
 
 
 
 

BlackBox

  • King Gator
  • Posts: 3770
Re: Object Events
« Reply #8 on: October 06, 2012, 01:28:33 PM »
MgdDbg is a must have.

Just downloaded them (ArxDbg, MgdDbg, and Inspector) from the DevCast article mentioned above.
 
Do you have to know when they change or just need to know what action to take in a method depending on which space is active?
 
Also if your inside a viewport or the viewport is active then Database.CurrentSpaceId will return ModelSpaces ObjectID.

All of what follows was done prior to knowing of MgdDbg, so take from this what you will:



The initial attempt was to monitor when CVPORT changed to determine which space was active, which is not successful in all three conditions.

Sample command line output:
Code - Auto/Visual Lisp: [Select]
  1. Command: netload Assembly file name: "FOO.dll"
  2. FOO events registered
  3.  
  4. ** TILEMODE: 1 **
  5.  
  6. ** ModelSpace activated **
  7.  
  8. Command: _RIBBON
  9.  
  10. Command: COMMANDLINE
  11.  
  12. Command: properties
  13.  
  14. Command: *Cancel*
  15.  
  16. Command: *Cancel*
  17.  
  18. Command:   <Switching to: Layout1>
  19.  
  20. ** TILEMODE: 0 **
  21.  
  22. ** CVPORT: 2 **
  23. Regenerating layout.
  24.  
  25. Command: mview
  26.  
  27. Specify corner of viewport or
  28. [ON/OFF/Fit/Shadeplot/Lock/Object/Polygonal/Restore/LAyer/2/3/4] <Fit>:
  29. Specify opposite corner: Regenerating model.
  30.  
  31. Command: Specify opposite corner: *Cancel*
  32.  
  33. Command: _.MSPACE
  34. ** TILEMODE: 0 **
  35.  
  36. ** CVPORT: 2 **
  37.  
  38. Command: _.PSPACE
  39. ** TILEMODE: 0 **
  40.  
  41. ** CVPORT: 1 **
  42.  
  43. ** PaperSpace activated **
  44.  
  45. Command: *Cancel*
  46.  
  47. Command: *Cancel*
  48.  
  49. Command:   <Switching to: Model>
  50.  
  51. ** TILEMODE: 1 **
  52.  
  53. ** ModelSpace activated **
  54. Regenerating model.
  55.  
  56. Command: *Cancel*
  57.  
  58. Command: *Cancel*
  59.  
  60. Command:   <Switching to: Layout1>
  61.  
  62. ** TILEMODE: 0 **
  63.  
  64. ** CVPORT: 2 **
  65. Regenerating layout.
  66. Regenerating model.
  67.  



My next thought was that I need to first test for TILEMODE / CTAB to determine Model, or Layout. Then, if Layout check the BlockTableRecord.Name to determine *Paper_Space (PViewport inactive), or *Model_Space (PViewport active).

Code - C#: [Select]
  1.  
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5.  
  6. using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
  7.  
  8. using System;
  9.  
  10. namespace FOO
  11. {
  12.     public class Events
  13.     {
  14.         public static void Register()
  15.         {
  16.             acApp.SystemVariableChanged -= acApp_SystemVariableChanged;
  17.             acApp.SystemVariableChanged += acApp_SystemVariableChanged;
  18.  
  19.             DocumentCollection acDocs = acApp.DocumentManager;
  20.  
  21.             acDocs.DocumentActivated -= acDocs_DocumentActivated;
  22.             acDocs.DocumentActivated += acDocs_DocumentActivated;
  23.  
  24.             acDocs.MdiActiveDocument.Editor.WriteMessage(
  25.                 "\nFOO events registered \n"
  26.                 );
  27.  
  28.             Reconcile();
  29.         }
  30.  
  31.         public static void acApp_SystemVariableChanged(Object sender, SystemVariableChangedEventArgs e)
  32.         {
  33.             if (e.Changed == true)
  34.             {
  35.                 if (e.Name == "CVPORT" || e.Name == "TILEMODE")
  36.                 {
  37.                     Reconcile();
  38.                 }
  39.             }            
  40.         }
  41.  
  42.         public static void acDocs_DocumentActivated(Object sender, DocumentCollectionEventArgs e)
  43.         {
  44.             if (e.Document != null)
  45.             {
  46.                 Reconcile();
  47.             }
  48.         }
  49.  
  50.         public static bool _PViewportActive(Document doc)
  51.         {
  52.             Database db = doc.Database;
  53.  
  54.             Transaction tr =
  55.                 // Which one is better for this purpose?
  56.                 db.TransactionManager.StartOpenCloseTransaction();
  57.                 //db.TransactionManager.StartTransaction();
  58.  
  59.             using (tr)
  60.             {
  61.                 BlockTable bt =
  62.                   (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  63.  
  64.                 BlockTableRecord btr =
  65.                   (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
  66.  
  67.                 if (btr.Name.ToUpper() == "*MODEL_SPACE")
  68.                 {
  69.                     return true;
  70.                 }
  71.  
  72.                 else
  73.                 {
  74.                     return false;
  75.                 }
  76.             }
  77.         }
  78.  
  79.         public static void Reconcile()
  80.         {
  81.             DocumentCollection acDocs = acApp.DocumentManager;
  82.             Document doc = acDocs.MdiActiveDocument;
  83.             Editor ed = doc.Editor;
  84.  
  85.             string tilemode = acApp.GetSystemVariable("TILEMODE").ToString();
  86.  
  87.             // Model space
  88.             if (tilemode == "1")
  89.             {
  90.                 ed.WriteMessage("\n** ModelSpace active ** \n");
  91.             }
  92.  
  93.             else
  94.             {
  95.                 // Pviewport
  96.                 if (_PViewportActive(doc))
  97.                 {
  98.                     ed.WriteMessage("\n** PViewport active ** \n");
  99.                 }
  100.  
  101.                 // Paper space
  102.                 else
  103.                 {
  104.                     ed.WriteMessage("\n** PaperSpace active ** \n");
  105.                 }
  106.             }
  107.         }
  108.  
  109.     }
  110. }
  111.  

... But that seems to suffer the same issue, in that when switching from Model Tab to Layout Tab, BlockTableRecord.Name returns *Model_Space before the Tab has actually changed, resulting in detecting PViewport Active when actually in *Paper_Space.

Sample command line output:
Code - Auto/Visual Lisp: [Select]
  1. Command: netload Assembly file name: "FOO.dll"
  2. FOO events registered
  3.  
  4. ** ModelSpace active **
  5.  
  6. Command: _RIBBON
  7.  
  8. Command: COMMANDLINE
  9.  
  10. Command: properties
  11.  
  12. Command: *Cancel*
  13.  
  14. Command: *Cancel*
  15.  
  16. Command:   <Switching to: Layout1>
  17.  
  18. ** PViewport active **
  19. Regenerating layout.
  20.  
  21. Command: mview
  22.  
  23. Specify corner of viewport or
  24. [ON/OFF/Fit/Shadeplot/Lock/Object/Polygonal/Restore/LAyer/2/3/4] <Fit>:
  25. Specify opposite corner: Regenerating model.
  26.  
  27. Command: Specify opposite corner: *Cancel*
  28.  
  29. Command: _.MSPACE
  30. ** PViewport active **
  31.  
  32. Command: _.PSPACE
  33. ** PaperSpace active **
  34.  
  35. Command: *Cancel*
  36.  
  37. Command: *Cancel*
  38.  
  39. Command:   <Switching to: Model>
  40.  
  41. ** ModelSpace active **
  42. Regenerating model.
  43.  
  44. Command: *Cancel*
  45.  
  46. Command: *Cancel*
  47.  
  48. Command:   <Switching to: Layout1>
  49.  
  50. ** PViewport active **
  51. Regenerating layout.
  52. Regenerating model.
  53.  

At this point, I'm not sure which would yield greater success (as I have not yet tested)... To either go the CommandEnded route (which I know to have worked for LISP), or to look into the LayoutActivated Event, rather than using the SystemVariableChanged Event.
"How we think determines what we do, and what we do determines what we get."

BlackBox

  • King Gator
  • Posts: 3770
Re: Object Events
« Reply #9 on: October 06, 2012, 01:35:48 PM »
MgdDbg is just fantastic... Thanks for bringing it up, Jeff!

I also turned on Document Events (for Commands, etc.), and LayoutManager Events, and it appears that the CommandEnded Event is what I am after:

Code - Auto/Visual Lisp: [Select]
  1. [Doc Event] : Command will Start        : LAYOUT_CONTROL <Switching to: Layout1>
  2.  
  3. [App Event] : System Var Changing       : NAVBARDISPLAY
  4. [App Event] : System Var Changed        : NAVBARDISPLAY
  5. [App Event] : System Var Changing       : NAVBARDISPLAY
  6. [App Event] : System Var Changed        : NAVBARDISPLAY
  7. [App Event] : System Var Changing       : CLAYER
  8. [App Event] : System Var Changed        : CLAYER
  9. [App Event] : System Var Changing       : TILEMODE
  10. [App Event] : System Var Changed        : TILEMODE
  11. [App Event] : System Var Changing       : REGENMODE
  12. [App Event] : System Var Changed        : REGENMODE
  13. [App Event] : System Var Changing       : REGENMODE
  14. [App Event] : System Var Changed        : REGENMODERegenerating layout.
  15. Regenerating model.
  16.  
  17. [Layout Manager Event] : Layout Switched
  18. [Doc Event] : Command Ended             : LAYOUT_CONTROL
  19. Command: Specify opposite corner:
  20. [App Event] : System Var Changing       : DYNMODE
  21. [App Event] : System Var Changed        : DYNMODE
  22. [App Event] : System Var Changing       : DYNMODE
  23. [App Event] : System Var Changed        : DYNMODE*Cancel*
  24.  
  25. Command: _.MSPACE
  26. [Doc Event] : Command will Start        : MSPACE
  27. [App Event] : System Var Changing       : CVPORT
  28. [App Event] : System Var Changed        : CVPORT
  29. [Doc Event] : Command Ended             : MSPACE
  30. [App Event] : System Var Changing       : UCSNAME
  31. [App Event] : System Var Changed        : UCSNAME
  32. Command: _.PSPACE
  33. [Doc Event] : Command will Start        : PSPACE
  34. [App Event] : System Var Changing       : CVPORT
  35. [App Event] : System Var Changed        : CVPORT
  36. [Doc Event] : Command Ended             : PSPACE
  37.  
"How we think determines what we do, and what we do determines what we get."

BlackBox

  • King Gator
  • Posts: 3770
Re: Object Events
« Reply #10 on: October 06, 2012, 01:42:42 PM »
It also appears that I could use Database Events, as the PViewport Object is modified when switching from Paper Space to Model Space (PViewport active)... But methinks the CommandEnded Event is just simpler, so I'm going to test that route.

After all, it worked well for my original VL routine. I just wanted to explore theses alternative routes to make sure there was not a simpler, perhaps better way moving forward into .NET API.
« Last Edit: October 06, 2012, 02:44:53 PM by RenderMan »
"How we think determines what we do, and what we do determines what we get."

BlackBox

  • King Gator
  • Posts: 3770
Re: Object Events
« Reply #11 on: October 06, 2012, 02:27:43 PM »
Still more to add before I've fully ported my VL routine to .NET, but as for this particular task... I've got it sorted now.  :-)



Here's the working source-code (inefficient as it may be):

Code - C#: [Select]
  1.  
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Internal;
  6. using Autodesk.AutoCAD.Runtime;
  7.  
  8. using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
  9.  
  10. using System;
  11.  
  12. [assembly: ExtensionApplication(typeof(FOO.Events))]
  13.  
  14. namespace FOO
  15. {
  16.     public class Events : IExtensionApplication
  17.     {
  18.         void IExtensionApplication.Initialize()
  19.         {
  20.             Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;
  21.             ed.WriteMessage("\nFOO events registered \n");
  22.  
  23.             Register();
  24.         }
  25.  
  26.         void IExtensionApplication.Terminate()
  27.         {
  28.         }
  29.  
  30.         public static void Register()
  31.         {
  32.             DocumentCollection acDocs = acApp.DocumentManager;
  33.             Editor ed = acDocs.MdiActiveDocument.Editor;
  34.  
  35.             try
  36.             {
  37.                 foreach (Document doc in acDocs)
  38.                 {
  39.                     doc.CommandEnded -= doc_CommandEnded;
  40.                     doc.CommandEnded += doc_CommandEnded;
  41.                 }
  42.  
  43.                 acDocs.DocumentCreated -= acDocs_DocumentCreated;
  44.                 acDocs.DocumentCreated += acDocs_DocumentCreated;
  45.  
  46.                 acDocs.DocumentActivated -= acDocs_DocumentActivated;
  47.                 acDocs.DocumentActivated += acDocs_DocumentActivated;
  48.  
  49.                 Reconcile();
  50.             }
  51.  
  52.             catch (System.Exception ex)
  53.             {
  54.                 ed.WriteMessage("\n; error: " + ex.Message + " \n");
  55.             }
  56.         }
  57.  
  58.         public static void acDocs_DocumentActivated(Object sender, DocumentCollectionEventArgs e)
  59.         {
  60.             if (e.Document != null)
  61.             {
  62.                 Reconcile();
  63.             }
  64.         }
  65.  
  66.         public static void acDocs_DocumentCreated(Object sender, DocumentCollectionEventArgs e)
  67.         {
  68.             if (e.Document != null)
  69.             {
  70.                 Register();
  71.             }
  72.         }
  73.  
  74.         public static void doc_CommandEnded(Object sender, CommandEventArgs e)
  75.         {
  76.             if (Utils.WcMatch(e.GlobalCommandName.ToUpper(),
  77.                 "*CHSPACE,*MSPACE,*PSPACE,*LAYOUT_CONTROL,U,*UNDO,*VPMAX,*VPMIN"))
  78.             {
  79.                 Reconcile();
  80.             }
  81.         }
  82.  
  83.         public static bool PViewportActive(Document doc)
  84.         {
  85.             Editor ed = doc.Editor;
  86.             Database db = doc.Database;
  87.  
  88.             Transaction tr =
  89.                 db.TransactionManager.StartOpenCloseTransaction();
  90.                 //db.TransactionManager.StartTransaction();
  91.  
  92.             using (tr)
  93.             {
  94.                 BlockTable bt =
  95.                   (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  96.  
  97.                 BlockTableRecord btr =
  98.                   (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
  99.  
  100.                 if (btr.Name.ToUpper() == "*MODEL_SPACE")
  101.                 {
  102.                     return true;
  103.                 }
  104.  
  105.                 else
  106.                 {
  107.                     return false;
  108.                 }
  109.             }
  110.         }
  111.  
  112.         public static void Reconcile()
  113.         {
  114.             DocumentCollection acDocs = acApp.DocumentManager;
  115.             Document doc = acDocs.MdiActiveDocument;
  116.             Editor ed = doc.Editor;
  117.  
  118.             string tilemode = acApp.GetSystemVariable("TILEMODE").ToString();
  119.  
  120.             // Model space
  121.             if (tilemode == "1")
  122.             {
  123.                 ed.WriteMessage("\n** ModelSpace active ** \n");
  124.             }
  125.  
  126.             else
  127.             {
  128.                 // Pviewport
  129.                 if (PViewportActive(doc))
  130.                 {
  131.                     ed.WriteMessage("\n** PViewport active ** \n");
  132.                 }
  133.  
  134.                 // Paper space
  135.                 else
  136.                 {
  137.                     ed.WriteMessage("\n** PaperSpace active ** \n");
  138.                 }
  139.             }
  140.            
  141.         }
  142.     }
  143. }
  144.  



Separately, I'd still appreciate it if someone could clarify if I am using StartOpenCloseTransaction() correctly, or if there's something I should watch for / correct in this test expression.

TIA
"How we think determines what we do, and what we do determines what we get."

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Object Events
« Reply #12 on: October 06, 2012, 04:55:53 PM »
I do not know but first thang that came to mind was could shorten a little and not have to open blocktable and BlockTablerecord
 
Code - C#: [Select]
  1.  
  2.          public static void Reconcile()
  3.         {
  4.             DocumentCollection acDocs = acApp.DocumentManager;
  5.             Document doc = acDocs.MdiActiveDocument;
  6.             Editor ed = doc.Editor;
  7.             Database db = doc.Database;
  8.             // Model space
  9.             if (db.TileMode)
  10.             {
  11.                 ed.WriteMessage("\n** ModelSpace active ** \n");
  12.             }
  13.             else
  14.             {
  15.                 // Pviewport
  16.                 if (SymbolUtilityServices.GetBlockModelSpaceId(db) == db.CurrentSpaceId)
  17.                 {
  18.                     ed.WriteMessage("\n** PViewport active ** \n");
  19.                 }
  20.                 // Paper space
  21.                 else
  22.                 {
  23.                    
  24.                     ed.WriteMessage("\n** PaperSpace active ** \n");
  25.                 }
  26.             }
  27.         }
  28.  

BlackBox

  • King Gator
  • Posts: 3770
Re: Object Events
« Reply #13 on: October 06, 2012, 05:54:34 PM »
I do not know but first thang that came to mind was could shorten a little and not have to open blocktable and BlockTablerecord

Excellent feedback, Jeff.

Another .NET novice mistake rectified by using Database.Tilemode, rather than acApp.GetSystemVariable("TILEMODE")... I didn't even know you could query it as a Property.

This alternative must have been overlooked in the Set and Return System Variables Documentation:roll:

Also, in all of the searching I did, not one illustrated the use of SymbolUtilityServices.GetBlockModelSpaceId(), so thanks also for this little lesson.

Cheers! :beer:
"How we think determines what we do, and what we do determines what we get."

TheMaster

  • Guest
Re: Object Events
« Reply #14 on: October 07, 2012, 04:57:57 AM »
Still more to add before I've fully ported my VL routine to .NET, but as for this particular task... I've got it sorted now.  :-)



Here's the working source-code (inefficient as it may be):

Code - C#: [Select]
  1.  
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Internal;
  6. using Autodesk.AutoCAD.Runtime;
  7.  
  8. using acApp = Autodesk.AutoCAD.ApplicationServices.Application;
  9.  
  10. using System;
  11.  
  12. [assembly: ExtensionApplication(typeof(FOO.Events))]
  13.  
  14. namespace FOO
  15. {
  16.     public class Events : IExtensionApplication
  17.     {
  18.         void IExtensionApplication.Initialize()
  19.         {
  20.             Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;
  21.             ed.WriteMessage("\nFOO events registered \n");
  22.  
  23.             Register();
  24.         }
  25.  
  26.         void IExtensionApplication.Terminate()
  27.         {
  28.         }
  29.  
  30.         public static void Register()
  31.         {
  32.             DocumentCollection acDocs = acApp.DocumentManager;
  33.             Editor ed = acDocs.MdiActiveDocument.Editor;
  34.  
  35.             try
  36.             {
  37.                 foreach (Document doc in acDocs)
  38.                 {
  39.                     doc.CommandEnded -= doc_CommandEnded;
  40.                     doc.CommandEnded += doc_CommandEnded;
  41.                 }
  42.  
  43.                 acDocs.DocumentCreated -= acDocs_DocumentCreated;
  44.                 acDocs.DocumentCreated += acDocs_DocumentCreated;
  45.  
  46.                 acDocs.DocumentActivated -= acDocs_DocumentActivated;
  47.                 acDocs.DocumentActivated += acDocs_DocumentActivated;
  48.  
  49.                 Reconcile();
  50.             }
  51.  
  52.             catch (System.Exception ex)
  53.             {
  54.                 ed.WriteMessage("\n; error: " + ex.Message + " \n");
  55.             }
  56.         }
  57.  
  58.         public static void acDocs_DocumentActivated(Object sender, DocumentCollectionEventArgs e)
  59.         {
  60.             if (e.Document != null)
  61.             {
  62.                 Reconcile();
  63.             }
  64.         }
  65.  
  66.         public static void acDocs_DocumentCreated(Object sender, DocumentCollectionEventArgs e)
  67.         {
  68.             if (e.Document != null)
  69.             {
  70.                 Register();
  71.             }
  72.         }
  73.  
  74.         public static void doc_CommandEnded(Object sender, CommandEventArgs e)
  75.         {
  76.             if (Utils.WcMatch(e.GlobalCommandName.ToUpper(),
  77.                 "*CHSPACE,*MSPACE,*PSPACE,*LAYOUT_CONTROL,U,*UNDO,*VPMAX,*VPMIN"))
  78.             {
  79.                 Reconcile();
  80.             }
  81.         }
  82.  
  83.         public static bool PViewportActive(Document doc)
  84.         {
  85.             Editor ed = doc.Editor;
  86.             Database db = doc.Database;
  87.  
  88.             Transaction tr =
  89.                 db.TransactionManager.StartOpenCloseTransaction();
  90.                 //db.TransactionManager.StartTransaction();
  91.  
  92.             using (tr)
  93.             {
  94.                 BlockTable bt =
  95.                   (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  96.  
  97.                 BlockTableRecord btr =
  98.                   (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
  99.  
  100.                 if (btr.Name.ToUpper() == "*MODEL_SPACE")
  101.                 {
  102.                     return true;
  103.                 }
  104.  
  105.                 else
  106.                 {
  107.                     return false;
  108.                 }
  109.             }
  110.         }
  111.  
  112.         public static void Reconcile()
  113.         {
  114.             DocumentCollection acDocs = acApp.DocumentManager;
  115.             Document doc = acDocs.MdiActiveDocument;
  116.             Editor ed = doc.Editor;
  117.  
  118.             string tilemode = acApp.GetSystemVariable("TILEMODE").ToString();
  119.  
  120.             // Model space
  121.             if (tilemode == "1")
  122.             {
  123.                 ed.WriteMessage("\n** ModelSpace active ** \n");
  124.             }
  125.  
  126.             else
  127.             {
  128.                 // Pviewport
  129.                 if (PViewportActive(doc))
  130.                 {
  131.                     ed.WriteMessage("\n** PViewport active ** \n");
  132.                 }
  133.  
  134.                 // Paper space
  135.                 else
  136.                 {
  137.                     ed.WriteMessage("\n** PaperSpace active ** \n");
  138.                 }
  139.             }
  140.            
  141.         }
  142.     }
  143. }
  144.  



Separately, I'd still appreciate it if someone could clarify if I am using StartOpenCloseTransaction() correctly, or if there's something I should watch for / correct in this test expression.

TIA

Before we talk about StartOpenCloseTransaction(), (and sorry to have to point this out), that code has major problems (which is perfectly fine if you're just learning the API and language- no offense intended).

What is the idea behind that Register() method (which is called every time a document is opened), and the removing and then immediately adding back event handlers for all open documents and the documents collection?