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

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

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 не дал его повторно открыть. Я же без транзакций это делаю.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Проблема в том, что при перемещении курсора по списку слоёв начинается просто спам событий модификации и последующий за ними Idle.
Проверил и в AutoCAD 2019.1.2 (до того проверял в AutoCAD 2020) - и с Property Preview включенном и выключенном - только одно событие Database.ObjectModified показывает MGDDBG.
P.S.: Из спортивного интереса отключи аппаратное ускорение видео. Возможно это как-то связано с ним.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Именно так. MGDDBG умеет отфильтровывать эти события! Надо научиться делать также

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

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
То есть ObjectModified точно происходит и мой обработчик вызывается. Я вижу это в окне вывода VS - специально пишу туда через Debug.Print, потому что в командную строку может неизвестно когда вывестись сообщение. А вот MGDDBG в командную строку ничего не пишет, как будто событий не происходит.

И у меня в коде ни один объект не открывается на запись. Только чтение. Я даже блокировки документа не делаю.

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А вот MGDDBG в командную строку ничего не пишет, как будто событий не происходит.
Я думаю просто потому, что в этот момент невозможен вывод в комстроку. Я посмотрел исходники MGDDBG, там просто вывод данных в комстроку при наступлении события, никаких фильтров-проверок и т.п.

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

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Из спортивного интереса отключи аппаратное ускорение видео. Возможно это как-то связано с ним.
Проверил. Разницы нет

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

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
никаких фильтров-проверок и т.п.
А я так надеялся...

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А я так надеялся...
Ну как минимум, это значит, что если сделать метод модификации в виде команды и вызывать её через Document.SendStringToExecute с правильными аргументами, то должно будет отрабатывать нормально.

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

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

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

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Метода модификации у меня и нет, только считывание. Но попробую прямо в обработчиках событий вызывать свою команду.
Цитировать
вызывать её через Document.SendStringToExecute с правильными аргументами
С правильными - это с какими? эхо отключить? true, true, false - годится?

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

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

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
С правильными - это с какими? эхо отключить? true, true, false - годится?
Я бы запускал в данном случае со всеми false. И еще команда должна быть с флагами NoHistory (как я писал выше) | Redraw | UsePickSet
Последние два флага чтобы не сбрасывался набор предварительного выбора.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Честно говоря боюсь. Не работал никогда без транзакций. И надо две недели переписывать все исходники - везде транзакции. Проще для начала попробовать вызывать SendStringToExecute

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

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

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

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
И еще команда должна быть с флагами NoHistory (как я писал выше) | Redraw | UsePickSet
UsePickSet само собой, понимаю. А флаг Redraw, судя по названию, вызовет перерисовку всего чертежа? Это же на долго. Стараюсь его не писать никогда, если и так все работает.

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А флаг Redraw, судя по названию, вызовет перерисовку всего чертежа?
Нет конечно:



Я конечно понимаю, что читать документацию это "последнее дело"... :)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
Попробовал с командой. Веселуха! Теперь список слоев не схлопывается. Зато все весело моргает. При каждом перемещении мыши по слоям/цветам происходит присвоение объекту слоя/цвета, отображение его на экране, вызов события модификации, вызов doc.SendStringToExecute и (ОПА!) присвоение старого слоя, отображение старого цвета на экране, затем вызов моей команды, перерисовка моей палитры (как ни старался, но она при этом моргает). И так далее пока пользователь не кликнет слой.
То есть не надо никаких транзакций. В ObjectModified только вызов SendStringToExecute и больше ничего. И этого достаточно для эффекта елочной гирлянды :) Ну хотя бы слой пользователь теперь может выбрать. Оставлю так  :-\

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
С правильными - это с какими? эхо отключить? true, true, false - годится?
Я что-то вчера пробовал - никак не получилось. Если есть модификация объекта - то такое поведение в списке слоёв никак не фиксится. SendStringToExecute точно так же работает, как и прямой вызов метода из события. Видимо, они с методом Editor.WriteMessage сильно по-разному работают.
Более-менее адекватно получилось, если использовать событие Editor.EnteringQuiscentState для модификации объекта. Но оно вызывается сильно позже изменения свойств в палитре. Когда уже в чертеже начинаешь выполнять какие-то действия.
Думаю, надо копать в сторону определения редактирования с помощью палитры свойств и ждать когда это редактирование закончится. Но как это сделать - не представляю.
Ну и самое простое решение - в требованиях к приложению указывать, что надо отключать предпросмотр изменений свойств  8) И я на самом деле считаю, что это приемлемо. Т.к. то, как Autodesk реализовал эту штуку - это тихий ужас просто :-X

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Ну хотя бы слой пользователь теперь может выбрать.
А у меня с SendStringToExecute не выбирался. Видимо, как-то влияет то, что у меня не голый Автокад, а Сивил.

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

  • ADN Club
  • *****
  • Сообщений: 809
  • Карма: 166
    • Мои плагины к Автокаду
А у меня с SendStringToExecute не выбирался. Видимо, как-то влияет то, что у меня не голый Автокад, а Сивил.
Еще интересней. Цвет линий поменять могу - просто мельтешит, как выше писал. А вот цвет граней солида - не могу, захлопывается список цветов и применяется тот цвет, который успел попасть под мышь. или старый. В общем только отключать PROPERTYPREVIEW

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

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Думаю, надо копать в сторону определения редактирования с помощью палитры свойств и ждать когда это редактирование закончится. Но как это сделать - не представляю.
Наверное так: https://adn-cis.org/forum/index.php?topic=10109.msg46193#msg46193
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение