(изменено: 777, 27 октября 2014г. 13:44:31)

Тема: Реакция на двойной щелчок или замена команды

Пробовал это сделать по своему, не совсем получилось, думал я чего-то не понимаю. Взял пример - то же самое...
Задача - заменить стандартный диалог редактирования атрибутов определённых блоков, т.е. мне нужен не столько двойной щелчок, сколько замена EATTEDIT, но и там и там проблема одна...
В общем всё работает на любых объектах, кроме динамических блоков.
Т.е. когда где-то в DocumentManager_DocumentLockModeChanged() или в Application_BeginDoubleClick() мы пытаемся получить выбранный (PICKFIRST) объект получаем ошибку:
Application.DocumentManager.MdiActiveDocument.Editor.SelectImplied().Status == PromptStatus.Error
Причём оно как-то иногда срабатывает, например, после DBLCLKEDIT = 0, DBLCLKEDIT = 1 (передёргиваем туда сюда), но тоже не всегда и, теперь даже и так не могу воспроизвести.
Кто-нибудь сталкивался? Что не так?

P.S. AutoCAD 2015, 2014, 2013, ...; VS 2013 C#; Win7x64

P.P.S. Ну и мой код тогда уж:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using f = System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using System.IO;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using System.Reflection;
using Autodesk.AutoCAD.Geometry;

namespace DoubleClickHandler
{
    public class Class1
    {
        [CommandMethod("AR77TEST")]
        public void test()
        {
            Application.DocumentManager.DocumentLockModeWillChange += DocumentManager_DocumentLockModeWillChange;
            Application.DocumentManager.DocumentLockModeChanged += DocumentManager_DocumentLockModeChanged;
            Application.DocumentManager.CurrentDocument.CommandEnded += CurrentDocument_CommandEnded;
            Application.DocumentManager.CurrentDocument.CommandWillStart += CurrentDocument_CommandWillStart;
            Application.DocumentManager.CurrentDocument.CommandCancelled += CurrentDocument_CommandCancelled;
            Application.DocumentManager.CurrentDocument.Database.ObjectErased += Database_ObjectErased;
            Application.DocumentManager.CurrentDocument.Editor.PromptingForCorner += Editor_PromptingForCorner;
            Application.BeginDoubleClick += Application_BeginDoubleClick;
            Application.DocumentManager.CurrentDocument.Editor.PromptedForCorner += Editor_PromptedForCorner;
            Application.DocumentManager.DocumentLockModeChangeVetoed += DocumentManager_DocumentLockModeChangeVetoed;
        }

        void DocumentManager_DocumentLockModeChangeVetoed(object sender, DocumentLockModeChangeVetoedEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\t" + e.GlobalCommandName + "\r\n");
            if (e.GlobalCommandName.ToUpper().Equals("EATTEDIT"))
            {
                Editor ed = Application.DocumentManager.CurrentDocument.Editor;
                var res = ed.SelectImplied();
                log("\tSelectImplied status is " + res.Status.ToString() + "\r\n"); //==Error
            }
        }

        void Database_ObjectErased(object sender, ObjectErasedEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
        }

        void CurrentDocument_CommandCancelled(object sender, CommandEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\t" + e.GlobalCommandName + "\r\n");
        }

        void CurrentDocument_CommandWillStart(object sender, CommandEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\t" + e.GlobalCommandName + "\r\n");
        }

        void CurrentDocument_CommandEnded(object sender, CommandEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\t" + e.GlobalCommandName + "\r\n");
        }

        void DocumentManager_DocumentLockModeChanged(object sender, DocumentLockModeChangedEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\tGlobalCommandName = " + e.GlobalCommandName + "\r\n");
            log("\tCurrentMode = " + e.CurrentMode.ToString() + "\r\n");
            log("\tMyCurrentMode = " + e.MyCurrentMode.ToString() + "\r\n");
            log("\tMyPreviousMode = " + e.MyPreviousMode.ToString() + "\r\n");
            if (e.GlobalCommandName.ToUpper().Equals("EATTEDIT"))
            {
                Editor ed = Application.DocumentManager.CurrentDocument.Editor;
                var res = ed.SelectImplied();
                log("\tSelectImplied status is " + res.Status.ToString() + "\r\n");
                if (res.Status == PromptStatus.OK)
                {
                    log("\tSelected count is " + res.Value.Count.ToString() + "\r\n");
                    if (res.Value.Count == 1)
                    {
                        log("\tDxfName = " + res.Value.GetObjectIds()[0].ObjectClass.DxfName + "\r\n");
                        log("\tVeto\r\n");
                        e.Veto();
                        f.MessageBox.Show("Настройки");
                    }
                }
            }
        }

        void DocumentManager_DocumentLockModeWillChange(object sender, DocumentLockModeWillChangeEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\tGlobalCommandName = " + e.GlobalCommandName + "\r\n");
            log("\tCurrentMode = " + e.CurrentMode.ToString() + "\r\n");
            log("\tMyCurrentMode = " + e.MyCurrentMode.ToString() + "\r\n");
            log("\tMyNewMode = " + e.MyNewMode.ToString() + "\r\n");
        }

        void Editor_PromptedForCorner(object sender, PromptPointResultEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            flag = false;
        }
        bool flag_ = false; //Если выбран объект, но двойной щелчок на пустом месте
        bool flag
        {
            get
            {
                return flag_;
            }
            set
            {
                flag_ = flag;
                log(MethodBase.GetCurrentMethod().Name + "\r\n");
                log("\tflag = " + flag_.ToString() + "\r\n");
            }
        }

        void Editor_PromptingForCorner(object sender, PromptPointOptionsEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            flag = true;
        }

        //bool flag2_ = false;    //Двойной щелчок был на нашем объекте и мы отменили стандартную команду
        //bool flag2
        //{
        //    get { return flag2_; }
        //    set
        //    {
        //        flag2_ = value;
        //        log(MethodBase.GetCurrentMethod().Name + "\r\n");
        //        log("\tflag2 = " + flag2_.ToString() + "\r\n");
        //    }
        //}

        void Application_BeginDoubleClick(object sender, BeginDoubleClickEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");

            if (flag)
                return;

            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

            PromptSelectionResult res = ed.SelectImplied();
            //res = ed.GetSelection();
            log("\tSelection status is " + res.Status.ToString() + "\r\n");
            if (res.Status == PromptStatus.OK)
            {
                ObjectId[] ids = res.Value.GetObjectIds();
                log("\tSelected count is " + ids.Length.ToString() + "\r\n");
                log("\tDxfName = " + ids[0].ObjectClass.DxfName + "\r\n");
                if (ids.Length == 1 && ids[0].ObjectClass.DxfName.ToUpper().Equals("INSERT"))
                {
                    //flag2 = true;
                    f.MessageBox.Show("Настройки");
                }
            }
        }

        void log(string entry)
        {
            File.AppendAllText(@"c:\temp\test.log", entry);
        }
    }
}

Re: Реакция на двойной щелчок или замена команды

Попробуй через событие Editor.SelectionAdded получить набор предварительного выбора. Editor.SelectImplied можно использовать только в очень узких рамках.

(изменено: 777, 30 октября 2014г. 06:10:01)

Re: Реакция на двойной щелчок или замена команды

В общем, я чего-то делал делал и вроде теперь всё как надо работает.
Единственное нужно делать вот это где-то в начале (косяк Автокада?):

      object v = Application.GetSystemVariable("DBLCLKEDIT"); 
            if (v.Equals(0)) 
                Application.SetSystemVariable("DBLCLKEDIT", 1); 
            else 
                Application.SetSystemVariable("DBLCLKEDIT", 0); 
            Application.SetSystemVariable("DBLCLKEDIT", v); 

На всякий случай работающий как надо код, вдруг кому пригодится:

    public class Class1 : IExtensionApplication
    {
        [CommandMethod("AR77TEST2", CommandFlags.UsePickSet)]
        public void test2()
        {
            try
            {
                log(MethodBase.GetCurrentMethod().Name + "\r\n");
                log("\tobj = " + obj.Handle.Value.ToString() + "\r\n");
                if (obj.Equals(ObjectId.Null))
                {
                    Editor ed = Application.DocumentManager.CurrentDocument.Editor;
                    var res = ed.SelectImplied();
                    log("\tSelectImplied status is " + res.Status.ToString() + "\r\n");
                    if (res.Status == PromptStatus.OK && res.Value.GetObjectIds().Length == 1)
                        obj = res.Value.GetObjectIds()[0];
                    else if (res.Status != PromptStatus.OK || obj.Equals(ObjectId.Null))
                    {
                        res = ed.GetSelection();
                        log("\tGetSelection status is " + res.Status.ToString() + "\r\n");
                        if (res.Status == PromptStatus.OK && res.Value.GetObjectIds().Length == 1)
                            obj = res.Value.GetObjectIds()[0];
                    }
                }
                if (!obj.ObjectClass.DxfName.ToUpper().Equals("INSERT"))
                    return;
                using (Transaction tr = obj.Database.TransactionManager.StartOpenCloseTransaction())
                {
                    string blkName = "";
                    BlockReference bref = (BlockReference)tr.GetObject(obj, OpenMode.ForRead);

                    if (bref.IsDynamicBlock)
                    {
                        if (bref.Name.StartsWith("*"))
                        {
                            BlockTableRecord br = (BlockTableRecord)tr.GetObject(bref.DynamicBlockTableRecord, OpenMode.ForRead);
                            blkName = br.Name;
                        }
                        else
                        {
                            blkName = bref.Name;
                        }
                    }
                    else
                    {
                        blkName = bref.Name;
                    }

                    log("\tАтрибуты:\r\n");
                    foreach (ObjectId i in bref.AttributeCollection)
                    {
                        AttributeReference ar = (AttributeReference)tr.GetObject(i, OpenMode.ForRead);
                        log("\t\t" + ar.Tag + "\r\n");
                    }
                    log("\tСвойства:\r\n");
                    DynamicBlockReferenceProperty p = null;
                    foreach (DynamicBlockReferenceProperty i in bref.DynamicBlockReferencePropertyCollection)
                    {
                        if (i.PropertyName.ToUpper().Equals("ШТАМП"))
                            p = i;
                        log("\t\t" + i.PropertyName + "\t" + i.Description + "\t" + i.Value.ToString() + "\t" + i.VisibleInCurrentVisibilityState.ToString() + "\r\n");
                    }

                    //Здесь будет что-то более сложное (своя форма для редактирования блока)
                    f.MessageBox.Show(obj.Equals(ObjectId.Null) ? "(null)" : obj.Handle.Value.ToString() + "\n" + blkName + "\n" + (p == null ? "(null)" : p.Value.ToString()));
                    tr.Commit();
                }
                obj = ObjectId.Null;
            }
            catch (System.Exception err)
            {
                log("\t" + err.Message + "\r\n");
            }
        }

        public void link_events(Document doc)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\tDocument = " + doc.Name + "\r\n");
            doc.Editor.PromptingForCorner += Editor_PromptingForCorner;
            doc.Editor.PromptedForCorner += Editor_PromptedForCorner;
            //Application.DocumentManager.CurrentDocument.CommandEnded += CurrentDocument_CommandEnded;
            //Application.DocumentManager.CurrentDocument.CommandWillStart += CurrentDocument_CommandWillStart;
            //Application.DocumentManager.CurrentDocument.CommandCancelled += CurrentDocument_CommandCancelled;
            //Application.DocumentManager.CurrentDocument.Database.ObjectErased += Database_ObjectErased;
            //Application.DocumentManager.CurrentDocument.Database.ObjectAppended += Database_ObjectAppended;
        }

        void Database_ObjectAppended(object sender, ObjectEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
        }

        void DocumentManager_DocumentLockModeChangeVetoed(object sender, DocumentLockModeChangeVetoedEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\t" + e.GlobalCommandName + "\r\n");
            if (e.GlobalCommandName.ToUpper().Equals("EATTEDIT") && flag2)
            {
                flag2 = false;
                Application.DocumentManager.CurrentDocument.SendStringToExecute("_AR77TEST2 ", true, false, true);
            }
        }

        void Database_ObjectErased(object sender, ObjectErasedEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
        }

        void CurrentDocument_CommandCancelled(object sender, CommandEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\t" + e.GlobalCommandName + "\r\n");
        }

        void CurrentDocument_CommandWillStart(object sender, CommandEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\t" + e.GlobalCommandName + "\r\n");
        }

        void CurrentDocument_CommandEnded(object sender, CommandEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\t" + e.GlobalCommandName + "\r\n");
        }

        void DocumentManager_DocumentLockModeChanged(object sender, DocumentLockModeChangedEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\tGlobalCommandName = " + e.GlobalCommandName + "\r\n");
            log("\tCurrentMode = " + e.CurrentMode.ToString() + "\r\n");
            log("\tMyCurrentMode = " + e.MyCurrentMode.ToString() + "\r\n");
            log("\tMyPreviousMode = " + e.MyPreviousMode.ToString() + "\r\n");
            if (e.GlobalCommandName.ToUpper().Equals("EATTEDIT") && flag2)
            {
                log("\tVeto\r\n");
                e.Veto();
            }
        }

        void DocumentManager_DocumentLockModeWillChange(object sender, DocumentLockModeWillChangeEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            log("\tGlobalCommandName = " + e.GlobalCommandName + "\r\n");
            log("\tCurrentMode = " + e.CurrentMode.ToString() + "\r\n");
            log("\tMyCurrentMode = " + e.MyCurrentMode.ToString() + "\r\n");
            log("\tMyNewMode = " + e.MyNewMode.ToString() + "\r\n");
        }

        void Editor_PromptedForCorner(object sender, PromptPointResultEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            flag = false;
        }
        bool flag_ = false; //Если выбран один объект, но двойной щелчок на пустом месте
        bool flag
        {
            get
            {
                return flag_;
            }
            set
            {
                flag_ = flag;
                log(MethodBase.GetCurrentMethod().Name + "\r\n");
                log("\tflag = " + flag_.ToString() + "\r\n");
            }
        }

        void Editor_PromptingForCorner(object sender, PromptPointOptionsEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            flag = true;
        }

        bool flag2_ = false;    //Двойной щелчок был на нашем объекте и мы отменили стандартную команду
        bool flag2
        {
            get { return flag2_; }
            set
            {
                flag2_ = value;
                log(MethodBase.GetCurrentMethod().Name + "\r\n");
                log("\tflag2 = " + flag2_.ToString() + "\r\n");
            }
        }

        static ObjectId obj_ = ObjectId.Null;
        static ObjectId obj
        {
            get
            {
                return obj_;
            }
            set
            {
                log(MethodBase.GetCurrentMethod().Name + "(" + value.Handle.Value.ToString() + ")\r\n");
                obj_ = value;
                log("\tobj = " + obj.Handle.Value.ToString() + "\r\n");
            }
        }
        void Application_BeginDoubleClick(object sender, BeginDoubleClickEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");

            if (flag)
                return;

            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

            PromptSelectionResult res = ed.SelectImplied();
            log("\tSelection status is " + res.Status.ToString() + "\r\n");
            if (res.Status == PromptStatus.OK)
            {
                ObjectId[] ids = res.Value.GetObjectIds();
                log("\tSelected count is " + ids.Length.ToString() + "\r\n");
                log("\tDxfName = " + ids[0].ObjectClass.DxfName + "\r\n");
                if (ids.Length == 1 && ids[0].ObjectClass.DxfName.ToUpper().Equals("INSERT"))
                {
                    var bn = GetBlockId(ids[0]);
                    if (bn != null && bn.ToUpper().Equals("ФОРМАТ"))
                    {
                        flag2 = true;
                        obj = ids[0];
                        log("\tobj = " + obj.Handle.Value.ToString() + "\r\n");
                    }
                }
            }
        }

        static void log(string entry)
        {
            File.AppendAllText(@"c:\temp\test.log", entry);
        }

        public void Initialize()
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            object v = Application.GetSystemVariable("DBLCLKEDIT");
            if (v.Equals(0))
                Application.SetSystemVariable("DBLCLKEDIT", 1);
            else
                Application.SetSystemVariable("DBLCLKEDIT", 0);
            Application.SetSystemVariable("DBLCLKEDIT", v);
            //Application.DocumentManager.DocumentLockModeWillChange += DocumentManager_DocumentLockModeWillChange;
            Application.DocumentManager.DocumentLockModeChanged += DocumentManager_DocumentLockModeChanged;
            Application.BeginDoubleClick += Application_BeginDoubleClick;
            Application.DocumentManager.DocumentLockModeChangeVetoed += DocumentManager_DocumentLockModeChangeVetoed;
            Application.DocumentManager.DocumentCreated += DocumentManager_DocumentCreated;
            foreach (Document d in Application.DocumentManager)
                link_events(d);
        }

        void DocumentManager_DocumentCreated(object sender, DocumentCollectionEventArgs e)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            link_events(e.Document);
        }

        public void Terminate()
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
        }

        private string GetBlockId(ObjectId entId)
        {
            log(MethodBase.GetCurrentMethod().Name + "\r\n");
            try
            {
                string blkName = "";

                using (Transaction tran = entId.Database.TransactionManager.StartOpenCloseTransaction())
                {
                    BlockReference bref = (BlockReference)tran.GetObject(entId, OpenMode.ForRead);

                    if (bref.IsDynamicBlock)
                    {
                        if (bref.Name.StartsWith("*"))
                        {
                            BlockTableRecord br = (BlockTableRecord)tran.GetObject(bref.DynamicBlockTableRecord, OpenMode.ForRead);
                            blkName = br.Name;
                        }
                        else
                        {
                            blkName = bref.Name;
                        }
                    }
                    else
                    {
                        blkName = bref.Name;
                    }

                    log("\tАтрибуты:\r\n");
                    foreach (ObjectId i in bref.AttributeCollection)
                    {
                        AttributeReference ar = (AttributeReference)tran.GetObject(i, OpenMode.ForRead);
                        log("\t\t" + ar.Tag + "\r\n");
                    }
                    log("\tСвойства:\r\n");
                    foreach (DynamicBlockReferenceProperty i in bref.DynamicBlockReferencePropertyCollection)
                    {
                        log("\t\t" + i.PropertyName + "\t" + i.Description + "\t" + i.Value.ToString() + "\t" + i.VisibleInCurrentVisibilityState.ToString() + "\r\n");
                    }

                    tran.Commit();
                }

                return blkName;
            }
            catch (System.Exception err)
            {
                log("\t" + err.Message + "\r\n");
            }
            return null;
        }
    }

P.S.
:idea: Никогда не надо спешить, получается обычно дольше, чем если не спешить
P.P.S.
А, вспомнил в чём основная проблема была, кроме передёргивания DBLCLKEDIT... Переменная obj была не статической и поэтому, не смотря на то, что в событии по двойному щелчку она устанавливалась, позже при вызове других методов/событий (метода команды, например) она снова была == null (проинициализирована). По логам видно, что объект создаётся не только при инициализации (IExtensionApplication), но и при каждом вызове команды и, наверное, ещё в каких-то случаях.