Author Topic: AddHandler CommandWillStart/RemoveHandler CommandWillStart not working  (Read 2959 times)

0 Members and 1 Guest are viewing this topic.

djee

  • Newt
  • Posts: 49
I'm trying to change the current layer when the user start a specific command. I'm using handler with the CommandWillStart/CommandEnded/CommandCancelled, etc...  I know the Autocad help says to;
Quote
Do not perform any action from an event handler that might trigger the same event.
I'm using the commandWillStart to change the AutoCAD variable "CLAYER" & return to the original layer when the CommandEnded is issued. My tininess brain (once confirm...) is thinking that, since i'm not manipulating the object itself (i'm just changing the "CLAYER" variable & checking/inserting layer), i'm still obeing the rules... Am I wrong? Because my code is not working & my "RemoveHandler CommandWillStart" doesn't seems to work (even though it's being called by the interpreter).
I'm loosing hair on this one.... & getting older...
Now, i've looked for previous post on this website, & found an interesting one concerning object overrule. I can't find any documentation concerning overrule from autodesk except the "Create my first .net project" thing on internet... Looks promising by I need to get a grip...
 

n.yuan

  • Bull Frog
  • Posts: 348
Re: AddHandler CommandWillStart/RemoveHandler CommandWillStart not working
« Reply #1 on: October 10, 2015, 10:26:30 AM »
Without seeing what you did in your code, it is difficult to comment. But based on your limited description, setting current layer when command starts and restore it back to previous layer when command ends/cancels is quite easy to do, and you do not need the help of Overrule (if it can ever help your need).

For example, I want to always draw LINE on a given layer, but do not want user to bother setting current layer correctly each time before the line is drawn, following code serves this purpose:

Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly: CommandClass(typeof(CommandWillStartHandler.Commands))]
[assembly: ExtensionApplication(typeof(CommandWillStartHandler.Commands))]

namespace CommandWillStartHandler
{
    public class Commands : IExtensionApplication
    {
        private static string _savedLayer = null;
        private const string LINE_LAYER = "MyLine";

        #region IExtensionApplication Interface

        public void Initialize()
        {
            Document dwg = CadApp.DocumentManager.MdiActiveDocument;
            Editor ed = dwg.Editor;

            try
            {
                ed.WriteMessage("\nInitialising custom add-in...");
                AddCommandHandler();
                ed.WriteMessage("\nInitializing custom add-in completed.");
            }
            catch
            {
                ed.WriteMessage("\nInitializing custom add-in failed");
            }
            finally
            {
                Autodesk.AutoCAD.Internal.Utils.PostCommandPrompt();
            }
        }

        public void Terminate()
        {

        }

        private void AddCommandHandler()
        {
            CadApp.DocumentManager.DocumentCreated += DocumentManager_DocumentCreated;

            foreach (Document d in CadApp.DocumentManager)
            {
                d.CommandWillStart += Document_CommandWillStart;
                d.CommandEnded += Document_CommandEnded;
                d.CommandCancelled += Document_CommandCancelled;
            }
        }

        private void DocumentManager_DocumentCreated(object sender, DocumentCollectionEventArgs e)
        {
            e.Document.CommandWillStart += Document_CommandWillStart;
            e.Document.CommandEnded += Document_CommandEnded;
            e.Document.CommandCancelled += Document_CommandCancelled;
        }

        private void Document_CommandEnded(object sender, CommandEventArgs e)
        {
            Document doc = CadApp.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            ed.WriteMessage("\nCommand {0} ended.", e.GlobalCommandName);

            if (!string.IsNullOrEmpty(_savedLayer))
            {
                CadApp.SetSystemVariable("CLAYER", _savedLayer);
                _savedLayer = null;
            }
        }

        private void Document_CommandCancelled(object sender, CommandEventArgs e)
        {
            Document doc = CadApp.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            ed.WriteMessage("\nCommand {0} cancelled.", e.GlobalCommandName);

            if (!string.IsNullOrEmpty(_savedLayer))
            {
                CadApp.SetSystemVariable("CLAYER", _savedLayer);
                _savedLayer = null;
            }
        }

        private void Document_CommandWillStart(object sender, CommandEventArgs e)
        {
            Document doc = CadApp.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;

            ed.WriteMessage("\nCommand {0} will start.", e.GlobalCommandName);

            //Whenever "LINE" command starts, the active layer is set to
            //LINE_LAYER so that the line is drawn on that layer
            if (e.GlobalCommandName.ToUpper() == "LINE")
            {
                _savedLayer = CadApp.GetSystemVariable("CLAYER").ToString();
                CadApp.SetSystemVariable("CLAYER", LINE_LAYER);
            }
        }

        #endregion
    }
}

HTH

djee

  • Newt
  • Posts: 49
Re: AddHandler CommandWillStart/RemoveHandler CommandWillStart not working
« Reply #2 on: October 13, 2015, 09:17:18 PM »
Your code is working perfectly but my RemoveHandler part is not working... In my form I have a "OFF" button which fire's off the "RemoveHandler" part. Even after triggering the "RemoveHandler" the program is still issuing the "CommandWillStart" event.  Here's my (fairly simple) problematic code I had written so far. I've chopped down most of the code that does not relate to the eventhandler. Is there any inconsistency concerning the "RemoveHandler" function?
You're help is much appreciated... Thanks!
Code: [Select]
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.ApplicationServices.Core.Application
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.ApplicationServices.Application
Imports System.Windows.Forms
Imports Autodesk.AutoCAD.Colors
Imports System.IO
Imports Autodesk.AutoCAD.Runtime

Public Class Form1
    Implements IExtensionApplication
    Private CurrentLayerName As String
    Private _SelectedLayer As LayerData
    Private Shared acDoc As Document

    Public Sub Initialize() Implements IExtensionApplication.Initialize
            Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Initialize")
        acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
    End Sub

    Public Sub Terminate() Implements IExtensionApplication.Terminate
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        _SelectedLayer = New LayerData
      End Sub

    Private Sub myOnButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles myOnButton.Click
         AddHandler acDoc.CommandWillStart, AddressOf SwapTheLayer
    End Sub

    Private Sub OFF_Button_Click(ByVal sender As Object, ByVal e As EventArgs) Handles OFF_Button.Click
        RemoveHandler acDoc.CommandWillStart, AddressOf SwapTheLayer
    End Sub

    Private Sub SwapTheLayer(ByVal senderObj As Object, ByVal e As CommandEventArgs)
        CurrentLayerName = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CLAYER")
        Dim importedLayer As Array = _SelectedLayer.ToArray
        Select Case e.GlobalCommandName
            Case "MTEXT"
                If checkIfLayerExistInDrawing(MText_TextBox.Text) = True Then
                    Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("layer exist")
                    Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("CLAYER", MText_TextBox.Text.ToString)
                Else
                    Dim myCreateLay As New CreateLayer(importedLayer(0).MyLayerName,
                                                       importedLayer(0).MyLayerDescription,
                                                       importedLayer(0).MyLayerColor,
                                                       importedLayer(0).MyLayerPlot,
                                                       importedLayer(0).MyLayerLinetypeName,
                                                       importedLayer(0).MyLayerLineweight)
                    Autodesk.AutoCAD.ApplicationServices.Core.Application.SetSystemVariable("CLAYER", MText_TextBox.Text)
                    Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("layer do not exist in drawing")
                End If
                Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("AddHandler CommandEnded")
                AddHandler acDoc.CommandEnded, AddressOf BackToOriginalLayer
                AddHandler acDoc.CommandCancelled, AddressOf BackToOriginalLayer
                AddHandler acDoc.CommandFailed, AddressOf BackToOriginalLayer
            End Select
    End Sub
    Private Sub BackToOriginalLayer(ByVal senderObj As Object, ByVal e As CommandEventArgs)
        Select Case e.GlobalCommandName
            Case Is = "MTEXT"
                Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("CLAYER", CurrentLayerName)
                Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("RemoveHandler CommandEnded")
                RemoveHandler acDoc.CommandEnded, AddressOf BackToOriginalLayer
                RemoveHandler acDoc.CommandCancelled, AddressOf BackToOriginalLayer
                RemoveHandler acDoc.CommandFailed, AddressOf BackToOriginalLayer
        End Select
    End Sub

    Private Function checkIfLayerExistInDrawing(ByVal myLayerName As String)
        Dim LayerExist As Boolean
        '' Get the current document and database
        Dim acCurDb As Database = acDoc.Database
        '' Start a transaction
        Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
            '' Open the Layer table for read
            Dim acLyrTbl As LayerTable
            acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForRead)

            'layer exist in drawing...
            If acLyrTbl.Has(myLayerName) = False Then
                LayerExist = False
            Else
                LayerExist = True
            End If
        End Using
        Return LayerExist
    End Function

End Class

n.yuan

  • Bull Frog
  • Posts: 348
Re: AddHandler CommandWillStart/RemoveHandler CommandWillStart not working
« Reply #3 on: October 14, 2015, 09:45:49 AM »
I do not see how the form is called to show. I guess you have another CommandClass with CommandMethod to define your command, in which the form is called.

Without seeing other code (which you may think is is irrelevant to the problem, but I'd think it is relevant), I can see a couple of issues with your code:

1. The good practice of UI design (Form, in this case) is to separate business logic (AutoCAD related operation, handling Document's command events, in this case) from UI, as much as possible. It is even worse to implement IExtensionApplication interface in the UI module. You should place the adding/removing event handler in a separate class. For example, you can have 2 CommandMethods in the your CommandClass. That is, you can have 2 separate custo commands "AddHanler", "RemoveHandler", which not only can be entered by user at command line as commands, but can also be called by your form (it looks like you show the form as modeless (floating form) by calling MdiDocument.SendStringToExecute().

2. The direct reason of your code does not removing event handler is likely due to the fact that you set a static/Shared variable aDoc to the MdiActiveDocument in the Initialize() method, and never re-point it if MdiActiveDocument changes: AutoCAD is multi-document app, its active document can be changed. Your code need to make sure all the open documents have the handlers added/removed. Or, if you only target particular documents (not all opening docuements), your code need to remember which document has the handlers added, so you can remove them accordingly. Also remember, new document could be opened, and existing document can be closed by user. If you only target particular document (not all document), you may also want to learn how to associate CommandClass with each document or with all document (with Shared or not Shared CommandMethod call).

djee

  • Newt
  • Posts: 49
Re: AddHandler CommandWillStart/RemoveHandler CommandWillStart not working
« Reply #4 on: October 14, 2015, 09:26:29 PM »
Quote
The good practice of UI design (Form, in this case) is to separate business logic
I'll keep that in mind for future project... Or modify this one when I got time...
Quote
Or, if you only target particular documents (not all opening documents), your code need to remember which document has the handlers added, so you can remove them accordingly.
At this point in my coding i'm just trying to make it work in one particular document. Once working i'll tackle the multiple document interface.  That's exactly why I used the shared/static document variable in the initialize portion. From MSDN on the shared topic:
Quote
Sharing a member of a class or structure makes it available to every instance, rather than nonshared, where each instance keeps its own copy.
In an effort to make my handler work, I though that by sharing the same MdiActiveDocument to addhandler & removehandler in my Class it would alleviate the risk of error... As you said;
Quote
your code need to remember which document has the handlers added
Any suggestion on how to achieve that if not using the shared variable?

Again thanks a lot for your time & suggestion! very appreciated...