Author Topic: Getting notified when a PaletteSet is hidden/closed  (Read 5879 times)

0 Members and 1 Guest are viewing this topic.

TheMaster

  • Guest
Getting notified when a PaletteSet is hidden/closed
« on: July 05, 2012, 03:39:44 PM »
This was quickly written and only briefly tested, but appears to work more reliably than the solution shown on Kean's blog.

Code: [Select]
// Original code by Kean walmsley at:
// http://through-the-interface.typepad.com/through_the_interface/2011/12/creating-a-custom-paletteset-class-exposing-a-close-event-inside-autocad-using-net.html

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using System;
 
namespace Autodesk.AutoCAD.Windows
{
  public class PaletteSetWithCloseEvent : PaletteSet
  {
    public PaletteSetWithCloseEvent( string cmd )
      : base( cmd )
    {
      Init();
    }
   
    public PaletteSetWithCloseEvent( string cmd, Guid guid )
      : base( cmd, guid )
    {
      Init();
    }
 
    // Common construction operations. 
    // If you overload the constructor, your overloads
    // should call this method:
   
    void Init()
    {
      this.StateChanged += stateChanged;
    }
   
    // event to be fired on close
 
    public event EventHandler PaletteSetClosed;
   
    // flag indicating if Application.Idle is being handled
   
    bool idleHandled = false;

    void stateChanged( object sender, PaletteSetStateEventArgs e )
    {
      if( ! idleHandled && e.NewState == StateEventIndex.Hide )
      {
        idleHandled = true;
        Application.Idle += onIdle;
      }
      else if( idleHandled && e.NewState == StateEventIndex.Show )
      {
        idleHandled = false;
        Application.Idle -= onIdle;
      }
    }
   
    // If the paletteset is docked/undocked, the idle
    // event should not fire until the entire operation
    // is completed, allowing it to be used to detect
    // if the paletteSet is no longer visible:
   
    void onIdle( object sender, EventArgs e )
    {
      if( ! this.Visible )
        this.OnPaletteSetClosed();
      Application.Idle -= onIdle;
      idleHandled = false;
    }
   
    // If you derive your PaletteSet class from this class (recommended)
    // You can simply override this method rather than handing the
    // PaletteSetClosed event:

    protected virtual void OnPaletteSetClosed()
    {
      if( this.PaletteSetClosed != null )
        this.PaletteSetClosed( this, EventArgs.Empty );
    }
 
  }
}

« Last Edit: July 05, 2012, 06:56:59 PM by TheMaster »

Draftek

  • Guest
Re: Getting notified when a PaletteSet is hidden/closed
« Reply #1 on: July 05, 2012, 04:06:03 PM »
Thanks, that might come in handy.

TheMaster

  • Guest
Re: Getting notified when a PaletteSet is hidden/closed
« Reply #2 on: August 13, 2012, 02:06:58 AM »
This was quickly written and only briefly tested, but appears to work more reliably than the solution shown on Kean's blog.

Revised to overcome a bug causing the close event to fire when a paletteset's Auto-hide button is clicked and the PaletteSet is rolled up. Also includes a simple test class.

Code - C#: [Select]
  1.  
  2. // PaletteSetWithCloseEvent.cs
  3. // Copyright (c) 2009-2012  Tony Tanzillo
  4.  
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using Autodesk.AutoCAD.ApplicationServices;
  10. using Autodesk.AutoCAD.Runtime;
  11. using Autodesk.AutoCAD.Windows;
  12.  
  13. /// Abstract:
  14. ///
  15. /// This class specializes the Autodesk.AutoCAD.Windows.PaletteSet
  16. /// class, adding a PaletteSetClosed event along with a corresponding
  17. /// overridable virtual method, allowing the PaletteSet and observers
  18. /// of the event to be notified when the PaletteSet is closed.
  19. ///
  20. /// Background:
  21. ///
  22. /// The PaletteSet's StateChanged event fires multiple times when a
  23. /// PaletteSet is docked, undocked, or rolled up when the Auto-hide
  24. /// button is clicked. Because of that, it becomes impossible to use
  25. /// that event directly to tell when a PaletteSet is actually hidden
  26. /// (technically, PaletteSets are never 'closed', when the "x" close
  27. /// button is clicked - rather they are hidden and remain in memory,
  28. /// ready to be made visible again).
  29. ///
  30. /// This class employs a few tricks to overcome this limitation, and
  31. /// provides a new Event and overridable virtual method that signals
  32. /// when the PalletSet is actually closed.
  33. ///
  34. /// You can use this class in lieu of the stock PaletteSet class, if
  35. /// you need to be notified when the PaletteSet is hidden. In all
  36. /// other respects, it behaves exactly the same as its base class.
  37.  
  38. namespace Autodesk.AutoCAD.Windows
  39. {
  40.  
  41.    public class PaletteSetWithCloseEvent : PaletteSet
  42.    {
  43.       bool initialized = false;
  44.       public PaletteSetWithCloseEvent( string showCommand )
  45.          : base( showCommand )
  46.       {
  47.          Init();
  48.       }
  49.  
  50.       public PaletteSetWithCloseEvent( string showCommand, Guid guid )
  51.          : base( showCommand, guid )
  52.       {
  53.          Init();
  54.       }
  55.  
  56.       // Common construction operations.  
  57.       // If you overload the constructor in a derived type,
  58.       // your overload must either supermessage one of the
  59.       // above constructors, or must call this method:
  60.  
  61.       protected void Init()
  62.       {
  63.          if( ! initialized )
  64.          {
  65.             initialized = true;
  66.             this.StateChanged += stateChanged;
  67.          }
  68.       }
  69.  
  70.       // Event to be fired on close.
  71.  
  72.       // Note:
  73.       //
  74.       // If you derive your PaletteSet class from
  75.       // this class, then you should override the
  76.       // OnPaletteSetClosed() virtual method below,
  77.       // rather than handling this event. This event
  78.       // is primarily intended to be used from the
  79.       // outside, rather than from a derived type.
  80.  
  81.       public event EventHandler PaletteSetClosed;
  82.  
  83.       // flag indicating if Application.Idle is being handled
  84.  
  85.       bool idleHandled = false;
  86.  
  87.       // Flag indicating if the PaletteSet was rolled up when
  88.       // the StateChanged event fired:
  89.  
  90.       bool wasRolledUp = false;
  91.  
  92.       void stateChanged( object sender, PaletteSetStateEventArgs e )
  93.       {
  94.          if( ! idleHandled && e.NewState == StateEventIndex.Hide )
  95.          {
  96.             idleHandled = true;
  97.             this.wasRolledUp = base.RolledUp;
  98.             Application.Idle += onIdle;
  99.          }
  100.          else if( idleHandled && e.NewState == StateEventIndex.Show )
  101.          {
  102.             idleHandled = false;
  103.             Application.Idle -= onIdle;
  104.          }
  105.       }
  106.  
  107.       // If the paletteset is docked/undocked or rolled-up,
  108.       // the idle event should not fire until the entire
  109.       // operation is completed, allowing it to be used to
  110.       // detect if the paletteSet is no longer visible:
  111.  
  112.       // [TT] 08-12-12:
  113.       // Revised to deal with auto-hide, which was being
  114.       // mis-interpreted as closing the paletteset.
  115.  
  116.       void onIdle( object sender, EventArgs e )
  117.       {
  118.          Application.Idle -= onIdle;
  119.          idleHandled = false;
  120.          if( ! ( base.Visible || ( wasRolledUp ^ this.RolledUp ) ) )
  121.          {
  122.             this.OnPaletteSetClosed();
  123.          }
  124.       }
  125.  
  126.       // If you derive your PaletteSet class from this class (recommended),
  127.       // your derived class can override this method rather than handing
  128.       // the PaletteSetClosed event:
  129.  
  130.       protected virtual void OnPaletteSetClosed()
  131.       {
  132.          if( this.PaletteSetClosed != null )
  133.             this.PaletteSetClosed( this, EventArgs.Empty );
  134.       }
  135.  
  136.    }
  137. }
  138.  
  139. // MyPaletteSet.cs - simple test case
  140. //
  141. // This simple test case also demonstrates the recommended
  142. // pattern for consuming a PalletSet - by deriving a class from
  143. // it that encapsulates all required functionality.
  144.  
  145. using System;
  146. using System.Collections.Generic;
  147. using System.Linq;
  148. using System.Text;
  149. using Autodesk.AutoCAD.Windows;
  150. using Autodesk.AutoCAD.ApplicationServices;
  151. using Autodesk.AutoCAD.Runtime;
  152.  
  153. namespace PaletteSetWithCloseEventTest
  154. {
  155.    public class MyPaletteSet : PaletteSetWithCloseEvent
  156.    {
  157.       static MyPaletteSet instance = null;
  158.       static Guid guid = new Guid( "{41738157-3080-4015-AB53-3ACF8067C791}" );
  159.       const string showCommand = "MYPALETTESET";
  160.  
  161.       public MyPaletteSet()
  162.          : base( showCommand, guid )
  163.       {
  164.          base.Add( "UserControl", new System.Windows.Forms.UserControl() );
  165.       }
  166.  
  167.       protected override void OnPaletteSetClosed()
  168.       {
  169.          Document doc = Application.DocumentManager.MdiActiveDocument;
  170.          if( doc != null )
  171.          {
  172.             doc.Editor.WriteMessage( "\n*** OnPaletteSetClosed() - Without the kludge  :p ***\n" );
  173.          }
  174.       }
  175.  
  176.       [CommandMethod( showCommand )]
  177.       public static void MyPaletteSetCommand()
  178.       {
  179.          if( instance == null )
  180.             instance = new MyPaletteSet();
  181.          instance.Visible = true;
  182.       }
  183.    }
  184. }
  185.  
  186.  
  187.  
« Last Edit: August 13, 2012, 03:56:31 PM by TT »