Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Андрей Бушман от 04-03-2014, 10:23:03

Название: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Андрей Бушман от 04-03-2014, 10:23:03
Доброго времени суток.

- AutoCAD 2009 SP3 x64 Enu (для меня в приоритете)
- AutoCAD 2014 SP1 x64 Enu

Посредством ContextMenuExtension формирую дополнительный набор пунктов контекстного меню для интересующего меня набора выбранных объектов. При открытии этого контекстного меню предварительное выделение тут же снимается. Т.о. нет возможности воспользоваться методом Editor.SelectImplied. Поскольку это не команда, то CommandFlags.UsePickSet не поставишь (насколько я понимаю). Возможно это очередной баг, но очень надеюсь, что это всё же не так...

Что нужно сделать, чтобы при открытии модифицированного контекстного меню, предварительный выбор не отменялся?

Спасибо.
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Александр Ривилис от 04-03-2014, 10:52:20
Андрей. Ну ты же опытный товарищь. Давай фрагмент кода, а еще лучше архивированный проект. Проверю и если не придумаю как выйти из положения - отправлю в ADN DevHelp.
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Андрей Бушман от 04-03-2014, 11:38:26
Цитата: Александр Ривилис
Давай фрагмент кода, а еще лучше архивированный проект.

Набросал такой Hello World - работает корректно, предварительный выбор не снимается (как и нужно):

Код - C# [Выбрать]
  1. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  2. using Ap = Autodesk.AutoCAD.ApplicationServices;
  3. using Db = Autodesk.AutoCAD.DatabaseServices;
  4. using Ed = Autodesk.AutoCAD.EditorInput;
  5. using Rt = Autodesk.AutoCAD.Runtime;
  6. using Wn = Autodesk.AutoCAD.Windows;
  7. ...
  8. static Wn.ContextMenuExtension cme;
  9. ...
  10. public void Initialize() {
  11.         cme = new Wn.ContextMenuExtension();
  12.         Rt.RXClass rxc = Db.Entity.GetClass(typeof(Db.BlockReference));
  13.         cad.AddObjectContextMenuExtension(rxc, cme);
  14.         cme.Title = "Hello World Title...";
  15.         cme.Popup += cme_Popup;
  16. }
  17.  
  18. // В обработчике события Popup я просматриваю выбранные элементы и исходя
  19. // из этого формирую нужный набор пунктов контекстного меню.
  20. void cme_Popup(object sender, EventArgs e) {
  21.         Wn.ContextMenuExtension _cme = (Wn.ContextMenuExtension)sender;
  22.         _cme.MenuItems.Clear();// Очищаю текущий набор пунктов меню
  23.  
  24.         // Здесь некоторая проверка и формирование нового набора пунктов
  25.         // ...
  26.         Wn.MenuItem mi = new Wn.MenuItem("Hello, World!");
  27.         mi.Click += mi_Click;
  28.         _cme.MenuItems.Add(mi);                
  29. }
  30.  
  31. void mi_Click(object sender, EventArgs e) {
  32.         Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  33.         Ed.Editor ed = doc.Editor;
  34.         ed.WriteMessage("Hello World pressed!\n");
  35. }
  36. ...
  37.  

Сейчас разбираюсь, почему в моём случае происходит снятие выделения... Пока, как вариант, решил обозначенную выше проблему таким способом, хотя он мне и не нравиться:
Код - C# [Выбрать]
  1. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  2. using Ap = Autodesk.AutoCAD.ApplicationServices;
  3. using Db = Autodesk.AutoCAD.DatabaseServices;
  4. using Ed = Autodesk.AutoCAD.EditorInput;
  5. using Rt = Autodesk.AutoCAD.Runtime;
  6. using Wn = Autodesk.AutoCAD.Windows;
  7. ...
  8. private static Db.ObjectId[] impsel;
  9. ...
  10. Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  11. ...
  12. // Эту регистрацию нужно выполнить для всех уже имеющихся документов в
  13. // DocumentManager, а так же для всех открываемых (показываю не текущем документе):
  14. doc.ImpliedSelectionChanged += doc_ImpliedSelectionChanged;
  15. ...
  16. static void doc_ImpliedSelectionChanged(object sender, EventArgs e) {
  17.         Ap.Document doc = (Ap.Document) sender;
  18.         Ed.PromptSelectionResult psr = doc.Editor.SelectImplied();                     
  19.         impsel = psr.Status == Ed.PromptStatus.OK ? psr.Value.GetObjectIds() : null;
  20. }
  21. ...
  22. /// <summary>
  23. /// Код, который выполняется каждый раз перед тем, как будет отображено
  24. /// контекстное меню выбранного в редакторе AutoCAD элемента.
  25. /// </summary>
  26. /// <param name="sender">Объект расширения контекстного меню.</param>
  27. /// <param name="e">Пустой аргумент (заглушка).</param>
  28. public static void cme_Popup(object sender, EventArgs e) {
  29.         Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  30.         Ed.Editor ed = doc.Editor;
  31.  
  32.         Ed.PromptSelectionResult result;
  33.  
  34.         if (impsel != null) {
  35.                 ed.SetImpliedSelection(impsel);
  36.                 result = ed.SelectImplied();
  37.         }
  38.         else {
  39.                 Db.TypedValue[] tv = GetDynBlockFilter(BlockRiseMarkExtension.RiseMarkBlockName);
  40.                 Ed.SelectionFilter filter = new Ed.SelectionFilter(tv);
  41.                 Ed.PromptSelectionOptions pso = new Ed.PromptSelectionOptions();
  42.                 pso.MessageForAdding = String.Format("Выберите экземпляры блока '{0}', которым желаете назначить якорь",
  43.                         BlockRiseMarkExtension.RiseMarkBlockName);
  44.                 pso.SingleOnly = false;
  45.                 result = ed.GetSelection(pso, filter);
  46.         }
  47. ...
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Дима_ от 04-03-2014, 12:24:26
Посмотрел у себя - не знаю правильно-ли, но т.к. объектное меню всплывет "только" при выделенных объектах заданного типа (причем если в выделении будет + еще какой-то то оно просто не "среагирует" - акад 2010), то по Popup у меня ObjectId "вытягиваются" через document.Editor.GetSelection().
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Андрей Бушман от 04-03-2014, 12:32:59
Это понятно, что оно появится лишь при условии, что выбраны только экземпляры типа, указанного при регистрации. Обозначенный мною выше Hello World прекрасно работает (выделение не снимается). Сейчас занимаюсь рефакторингом кода и поиском причины, по которой у меня это выделение слетает.
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Александр Ривилис от 04-03-2014, 12:45:09
Сейчас занимаюсь рефакторингом кода и поиском причины, по которой у меня это выделение слетает.
Вот видишь! Достаточно было сделать пример кода, как стало ясно что причина в чем-то другом.
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Дима_ от 04-03-2014, 12:52:07
Я к тому что если Ваше меню зарегестрированно только как объектное, то (impsel != null) лишена смысла т.к. такой ситуации не будет (кстати проверять "!=" с вариантом ветки else меня до сих пор коробит "=" и менять ветки then else местами) - такой ситаации просто не возникнет- если "всплыло" то смело преобразуй GetSelection() - там точно есть объекты и только те которые нужны. Если только таким образом не проверяется какой вариант запущен (одно и то-же меню зарегестрированно на общее и объектное) - ихмо я бы сделал 2 разных.
з.ы. В добавление к сказанному А.Ривилиса - Андрей давно в отпуск ходили?  ;)
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Андрей Бушман от 04-03-2014, 13:08:51
Я к тому что если Ваше меню зарегестрированно только как объектное, то (impsel != null) лишена смысла т.к. такой ситуации не будет - там точно есть объекты и только те которые нужны.
Я тоже так думал, пока не столкнулся с тем, что предварительный выбор слетает. Именно после этого и добавил такую проверку, дабы "вручную" восстанавливать предварительный набор. Скорее всего велосипед кроется в каком-то косяке, допущенном мною (пока не нашёл).

Ещё поковыряюсь в коде, если так и не найду причины такого поведения, то выложу исходники здесь, дабы каждый желающий смог воочию увидеть сей "ахтунг". Может свежим глазом кто и заметит причину. Пока не вижу. Вроде всё сделано по аналогии с обозначенным выше Hello World...

Цитата: Дима_
кстати проверять "!=" с вариантом ветки else меня до сих пор коробит "=" и менять ветки then else местами
Я не понял этой фразы. Предполагаю, что не хватает знаков пунктуации, т.к. читается "казнить нельзя помиловать". Или меня уже можно выносить строиться... :)

Цитата: Дима_
з.ы. В добавление к сказанному А.Ривилиса - Андрей давно в отпуск ходили?  ;)
Я уже не помню что это такое... :) Каждые выходные занимаюсь ремонтом квартиры. Последний отпуск был занят тем же, помимо возни с ребёнком.
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Дима_ от 04-03-2014, 14:26:20
Я не понял этой фразы.
Имееться в виду что если в if есть обе ветки проверки условия (then и else), то проверять отрицание какого-либо свойства идеологически не верно т.к. проверив условие и поменяв ветки результат будет такой-же - типа лишния опреация - но по сути это конечно не то, от чего может потеряется скорость, да и компилятор вероятно делает такую перестановку сам - но насчет СИ подобных не уверен - из-за особенностей синтаксиса тому, кто на него вобще рабочий компилятор написал надо памятник ставить (хотя лично по мне - лучше б вобще не писал).
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Александр Ривилис от 04-03-2014, 14:57:11
...В добавление к сказанному А.Ривилиса...
Дима. Ты в каком падеже меня проскланял? ;-)
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Андрей Бушман от 04-03-2014, 15:11:59
Я не понял этой фразы.
Имееться в виду что если в if есть обе ветки проверки условия (then и else), то проверять отрицание какого-либо свойства идеологически не верно т.к. проверив условие и поменяв ветки результат будет такой-же - типа лишния опреация - но по сути это конечно не то, от чего может потеряется скорость, да и компилятор вероятно делает такую перестановку сам - но насчет СИ подобных не уверен - из-за особенностей синтаксиса тому, кто на него вобще рабочий компилятор написал надо памятник ставить (хотя лично по мне - лучше б вобще не писал).
Я, видимо, уже плохо соображаю, поскольку по прежнему не понял. Если можно, то на пальцах (т.е. на простом примере кода). :)


По теме топика: после некоторого рефакторинга всё заработало как нужно (исправил ошибку, так её и не найдя).
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Дима_ от 04-03-2014, 16:23:50
Я, видимо, уже плохо соображаю, поскольку по прежнему не понял. Если можно, то на пальцах (т.е. не простом примере кода).
Да забей...
То Александр - сорри "Шура. Вы же знаете как я Вас уважаю" Паниковский (с). Я так понимаю у Вас фамилия не склоняемая - постараюсь запомнить.
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Александр Ривилис от 04-03-2014, 19:09:50
То Александр - сорри
Как раз склоняемая. Поэтому вместо:
Цитировать
...В добавление к сказанному А.Ривилиса...
должно быть
Цитировать
...В добавление к сказанному А.Ривилисом...

P.S.: А за Андрея рад!  :)
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Дима_ от 05-03-2014, 10:26:55
Осознал - был неправ, если формировать MenuItem на основе выбранных объектов, то нужно использовать именно SelectImplied(), а не GetSelection() т.к. в моем случае (исправил уже) две программы зарегестрированные на 1 класс вместе "не уживутся"...
Название: Re: При открытии модифицированного контекстного меню снимается предварительный выбор
Отправлено: Андрей Бушман от 05-03-2014, 10:39:17
нужно использовать именно SelectImplied()
я именно так и делаю.