При открытии модифицированного контекстного меню снимается предварительный выбор

Автор Тема: При открытии модифицированного контекстного меню снимается предварительный выбор  (Прочитано 7621 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Доброго времени суток.

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

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

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

Спасибо.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Андрей. Ну ты же опытный товарищь. Давай фрагмент кода, а еще лучше архивированный проект. Проверю и если не придумаю как выйти из положения - отправлю в ADN DevHelp.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Цитата: Александр Ривилис
Давай фрагмент кода, а еще лучше архивированный проект.

Набросал такой 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. ...

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Посмотрел у себя - не знаю правильно-ли, но т.к. объектное меню всплывет "только" при выделенных объектах заданного типа (причем если в выделении будет + еще какой-то то оно просто не "среагирует" - акад 2010), то по Popup у меня ObjectId "вытягиваются" через document.Editor.GetSelection().

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Это понятно, что оно появится лишь при условии, что выбраны только экземпляры типа, указанного при регистрации. Обозначенный мною выше Hello World прекрасно работает (выделение не снимается). Сейчас занимаюсь рефакторингом кода и поиском причины, по которой у меня это выделение слетает.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Сейчас занимаюсь рефакторингом кода и поиском причины, по которой у меня это выделение слетает.
Вот видишь! Достаточно было сделать пример кода, как стало ясно что причина в чем-то другом.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Я к тому что если Ваше меню зарегестрированно только как объектное, то (impsel != null) лишена смысла т.к. такой ситуации не будет (кстати проверять "!=" с вариантом ветки else меня до сих пор коробит "=" и менять ветки then else местами) - такой ситаации просто не возникнет- если "всплыло" то смело преобразуй GetSelection() - там точно есть объекты и только те которые нужны. Если только таким образом не проверяется какой вариант запущен (одно и то-же меню зарегестрированно на общее и объектное) - ихмо я бы сделал 2 разных.
з.ы. В добавление к сказанному А.Ривилиса - Андрей давно в отпуск ходили?  ;)

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Я к тому что если Ваше меню зарегестрированно только как объектное, то (impsel != null) лишена смысла т.к. такой ситуации не будет - там точно есть объекты и только те которые нужны.
Я тоже так думал, пока не столкнулся с тем, что предварительный выбор слетает. Именно после этого и добавил такую проверку, дабы "вручную" восстанавливать предварительный набор. Скорее всего велосипед кроется в каком-то косяке, допущенном мною (пока не нашёл).

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

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

Цитата: Дима_
з.ы. В добавление к сказанному А.Ривилиса - Андрей давно в отпуск ходили?  ;)
Я уже не помню что это такое... :) Каждые выходные занимаюсь ремонтом квартиры. Последний отпуск был занят тем же, помимо возни с ребёнком.

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Я не понял этой фразы.
Имееться в виду что если в if есть обе ветки проверки условия (then и else), то проверять отрицание какого-либо свойства идеологически не верно т.к. проверив условие и поменяв ветки результат будет такой-же - типа лишния опреация - но по сути это конечно не то, от чего может потеряется скорость, да и компилятор вероятно делает такую перестановку сам - но насчет СИ подобных не уверен - из-за особенностей синтаксиса тому, кто на него вобще рабочий компилятор написал надо памятник ставить (хотя лично по мне - лучше б вобще не писал).

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
...В добавление к сказанному А.Ривилиса...
Дима. Ты в каком падеже меня проскланял? ;-)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Я не понял этой фразы.
Имееться в виду что если в if есть обе ветки проверки условия (then и else), то проверять отрицание какого-либо свойства идеологически не верно т.к. проверив условие и поменяв ветки результат будет такой-же - типа лишния опреация - но по сути это конечно не то, от чего может потеряется скорость, да и компилятор вероятно делает такую перестановку сам - но насчет СИ подобных не уверен - из-за особенностей синтаксиса тому, кто на него вобще рабочий компилятор написал надо памятник ставить (хотя лично по мне - лучше б вобще не писал).
Я, видимо, уже плохо соображаю, поскольку по прежнему не понял. Если можно, то на пальцах (т.е. на простом примере кода). :)


По теме топика: после некоторого рефакторинга всё заработало как нужно (исправил ошибку, так её и не найдя).
« Последнее редактирование: 04-03-2014, 16:27:17 от Андрей Бушман »

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Я, видимо, уже плохо соображаю, поскольку по прежнему не понял. Если можно, то на пальцах (т.е. не простом примере кода).
Да забей...
То Александр - сорри "Шура. Вы же знаете как я Вас уважаю" Паниковский (с). Я так понимаю у Вас фамилия не склоняемая - постараюсь запомнить.
« Последнее редактирование: 04-03-2014, 16:34:23 от Дима_ »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
То Александр - сорри
Как раз склоняемая. Поэтому вместо:
Цитировать
...В добавление к сказанному А.Ривилиса...
должно быть
Цитировать
...В добавление к сказанному А.Ривилисом...

P.S.: А за Андрея рад!  :)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Осознал - был неправ, если формировать MenuItem на основе выбранных объектов, то нужно использовать именно SelectImplied(), а не GetSelection() т.к. в моем случае (исправил уже) две программы зарегестрированные на 1 класс вместе "не уживутся"...

Оффлайн Андрей БушманАвтор темы

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
нужно использовать именно SelectImplied()
я именно так и делаю.