Панель свойств захлопывает список слоев при открытии транзакции

Автор Тема: Панель свойств захлопывает список слоев при открытии транзакции  (Прочитано 8925 раз)

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

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Когда пользователь назначает цвет/слой в обычной панели свойств, то Автокад непрерывно модифицирует выбранные объекты, присваивая слой из-под курсора мыши. Идут события Database_ObjectModified, активируется моя программа (чтоб показать свойства в другой самодельной панели) и (ОПА!) панелька со списком слоев закрывается, назначается старый слой. Приехали. Пользователь не может поменять цвет/слой.
Выяснил, что схлопывание вызывает Application.DoEvents(). Убрал его. Теперь схлопывается на открытие(!) транзакции. Точнее само схлопывание я не могу видеть в пошаговом режиме отладки, но ловлю новое событие модификации и там уже у объекта старый слой.
Читаю данные не сразу в ObjectModified, а позже из AcadApp_Idle. Но это не помогает. Idle вызывается мгновенно после ObjectModified, пользователь еще не кликнул на нужном слое.
Добавил задержку чтения на полсекунды. Иногда успеваю кликнуть слой и тогда все ОК. Но чуть притормозил и список схлопывается :(
Вопрос в том как проигнорировать именно такие "временные" модификации объектов? Или может есть какой-то особенный способ читать чертеж пока открыт этот список слоев?
Тут видео https://www.dropbox.com/s/cobieyazw67xppd/ScreenRecorderProject1.mp4?dl=0

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

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

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Вопрос в том как проигнорировать именно такие "временные" модификации объектов?
А что в объекте модифицируется, если слой ещё не был задан? Почему у него вызывается событие модификации? Возможно, это модифицируется другой объект? И если так, то почему это обрабатывает кастомная палитра?
Вообще, впервые такое вижу. А с кастомными палитрами и свойствами объектов в них очень плотно работал. Есть подозрение, что где-то в коде обработки событий что-то не так...

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
DocumentLockModeChanged попробую по отлавливать, но вряд ли поможет - Автокад наверняка блокирует/разблокирует документ всегда, когда меняет слои.
Цитировать
А что в объекте модифицируется, если слой ещё не был задан?
Когда пользователь выбирает цвет/слой из списка, то модифицируется цвет/слой. Объект - тот самый, что выбран в чертеже и в панели свойств. Событие модификации вызывается потому что он в самом деле модифицируется, меняет цвет "на лету", без клика по конкретному слою - такая вот фича в Автокад (в клонах такого нет).

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А обработчик события случайно не в коде формы?

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Нет, в статическом классе. И все считывания данных чертежа - в специальных классах, никак не связанных с WinForms. До работы с формами вообще не доходит. Я же вижу когда проскакивает модификация объекта обратно к исходному значению слоя.
Сейчас пытаюсь отловить открытия этих списков. Никаких команд при смене слоя Автокад не посылает. Но, оказывается DocumentLockModeChanged отлавливает гораздо больше команд, в частности некую команду PREVIEW_END до первой смены слоя и команду #PREVIEW_END, когда пользователь таки кликнет цвет/слой. Попробую не реагировать на модификации объектов в этом промежутке. Но кто его знает, когда еще эти команды проскакивают...

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Вот такой костыль вставил:
Код - C# [Выбрать]
  1.     static bool preview_end = false;
  2.  
  3.     private static void DocumentManager_DocumentLockModeChanged(object sender, DocumentLockModeChangedEventArgs e)
  4.     {
  5.       preview_end = e.GlobalCommandName == "PREVIEW_END" && e.CurrentMode == DocumentLockMode.Write
  6.                          || e.GlobalCommandName == "" && e.CurrentMode == DocumentLockMode.ProtectedAutoWrite;
  7.     }
Если preview_end, то игнорирую модификацию объектов.
Иногда это даже работает... Но события DocumentLockModeChanged происходят довольно хаотично. В результате, то моя панель не обновиться, то у пользователя из под мыши исчезает список слоев... :(

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

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

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
в частности некую команду PREVIEW_END до первой смены слоя и команду #PREVIEW_END, когда пользователь таки кликнет цвет/слой.
У меня такого нет. Более того нет вызова ObjectModified при движении по списку. Только после выбора пользователем:
[Doc Event] : Implied Selection Changed
Command:
[Doc Mgr Event] : Document Lock Mode Will Change : Drawing1.dwg
    Global Command Name  :
    Current Mode         : NotLocked
    My Current Mode      : NotLocked
    My New Mode          : ProtectedAutoWrite
[Doc Mgr Event] : Document Lock Mode Changed : Drawing1.dwg
    Global Command Name  :
    Current Mode         : ProtectedAutoWrite
    My Current Mode      : NotLocked
    My Previous Mode     : ProtectedAutoWrite
[DB Event : 712294208] : Object Opened For Modify  : <Line, 291>
[DB Event : 712294208] : Object Modified           : <Line, 291>

Похоже у тебя что-то гадит в AutoCAD.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн avcАвтор темы

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
О-как  :o. Гадить-то может только мой же плагин... Значит какие-то мои же обработчики событий что-то делают... буду отсекать все лишнее. Спасибо.

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

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

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Есть такая беда. По крайней мере, у меня воспроизводится.
Код - C# [Выбрать]
  1. namespace Test
  2. {
  3.     using System;
  4.     using System.Collections.Generic;
  5.     using Autodesk.AutoCAD.DatabaseServices;
  6.     using Autodesk.AutoCAD.EditorInput;
  7.     using Autodesk.AutoCAD.Runtime;
  8.     using Application = Autodesk.AutoCAD.ApplicationServices.Core.Application;
  9.  
  10.     public class EventPropertyTest
  11.     {
  12.         private bool _isOn;
  13.         private bool _needUpdate;
  14.         private readonly List<ObjectId> _ids = new List<ObjectId>();
  15.         private readonly Random _random = new Random();
  16.         private bool _innerModify;
  17.  
  18.         [CommandMethod(nameof(RunEventPropertyTest))]
  19.         public void RunEventPropertyTest()
  20.         {
  21.             if (!_isOn)
  22.             {
  23.                 Application.Idle += ApplicationOnIdle;
  24.                 _isOn = true;
  25.             }
  26.  
  27.  
  28.             var ed = Application.DocumentManager.MdiActiveDocument.Editor;
  29.             var res = ed.GetEntity("\nSelect object: ");
  30.  
  31.             if (res.Status != PromptStatus.OK) return;
  32.  
  33. #pragma warning disable 618
  34.             using (var obj = res.ObjectId.Open(OpenMode.ForRead))
  35. #pragma warning restore 618
  36.             {
  37.                 obj.Modified += ObjOnModified;
  38.                 _ids.Add(obj.Id);
  39.             }
  40.         }
  41.  
  42.         private void ObjOnModified(object sender, EventArgs e)
  43.         {
  44.             if (!_innerModify)
  45.             {
  46.                 _needUpdate = true;
  47.             }
  48.         }
  49.  
  50.         private void ApplicationOnIdle(object sender, EventArgs e)
  51.         {
  52.             if (_needUpdate)
  53.             {
  54.                 if (_ids.Count > 0)
  55.                 {
  56.                     using (Application.DocumentManager.MdiActiveDocument.LockDocument())
  57.                     {
  58.                         _innerModify = true;
  59.                         foreach (var id in _ids)
  60.                         {
  61. #pragma warning disable 618
  62.                             using (var obj = (Entity)id.Open(OpenMode.ForWrite))
  63. #pragma warning restore 618
  64.                             {
  65.                                 obj.ColorIndex = _random.Next(1, 255);
  66.                             }
  67.                         }
  68.  
  69.                         _innerModify = false;
  70.                     }
  71.                 }
  72.  
  73.                 _needUpdate = false;
  74.             }
  75.         }
  76.     }
  77. }
https://autode.sk/3lO5PQC

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Дмитрий Загорулькин,
Так просто делать нельзя. Idle - это событие интерфейса и к событиям обновления базы данных отношения не имеет. Поэтому модифицировать объект, который только что был модифицирован, нельзя. Это допустимо только в Overrule.
Кроме того я имел в виду событие Database.ObjectModified а не DBObject.Modified
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

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

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А я пробовал и DBObject.Modified и Database.ObjectModified - результат один и тот же.
Проблема в том, что при перемещении курсора по списку слоёв начинается просто спам событий модификации и последующий за ними Idle.
Это всё из-за функции предпросмотра изменения свойств.
Да я думаю, что объект закрыт в момент, когда Idle наступает. Иначе, мне бы AutoCAD не дал его повторно открыть. Я же без транзакций это делаю.