Как автоматически обновлять поля блока?
| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Как автоматически обновлять поля блока?

Как автоматически обновлять поля блока?

Ответ
Поиск в этой теме
Непрочитано 29.07.2010, 15:59 #1
Как автоматически обновлять поля блока?
Ax3
 
Programming, automation, CADs, GISs. "Теплоком"
 
Россия, Санкт-Петербург
Регистрация: 02.02.2007
Сообщений: 306

Привет, братья по каду.
Столкнулся с проблемой. Дин. блок содержит lookup-ы и поля, отображающие значеия lookup-ов. Хотел сделать так, чтобы после изменений Lookup-ов пользователем производилось автоматическое обновление полей блока.
Прицепил к блоку vlr-object-reactor, в качестве его callback-функции указал свою функцию upd-fields.
И теперь вот думаю - а что в ней написать-то, в этой upd-fields?
В справке сказано "Do not update the object that issued the event notification." и запрещено использовать (command) и, видимо, (vl-cmdf) тоже запрещено, да они и не работают в реакторе. То есть (command "updatefield") отпадает.

Может, есть варианты? Кто-нибудь сталкивался с подобной задачей?

{2010.09.01}
Решение версии 1.00. Справка внутри (файл !readme!_blk_autoupd.txt)
blk_autoupd_v1.00(c)Danilov_AS_aka_`Hawk`_2010.09.01.rar

{2010.09.06}
Решение версии 1.01. Справка внутри (файл !readme!_blk_autoupd.txt)
blk_autoupd_v1.01(c)Danilov_AS_aka_`Hawk`_2010.09.03.rar

{2010.11.30}
blk_autoupd_v2.1(c)Danilov_AS_aka_`Hawk`_2010.11.30.rar

__________________
На LISPе можно мыслить!

Последний раз редактировалось Ax3, 30.11.2010 в 15:13.
Просмотров: 11804
 
Непрочитано 29.07.2010, 16:27
1 | #2
Александр Ривилис

программист, рыцарь ObjectARX
 
Регистрация: 09.05.2005
Киев
Сообщений: 2,413
Отправить сообщение для Александр Ривилис с помощью Skype™


В этом реакторе запоминай "кого нужно обновить", а обновляй в командном реакторе (CommandEnded).
Александр Ривилис вне форума  
 
Непрочитано 29.07.2010, 16:40
#3
TararykovDG

Программист-энтузиаст
 
Регистрация: 17.07.2009
Воронеж
Сообщений: 575


Только вот вопрос? Если Ваш ректор будет срабатывать на изменение блока и попытается изменить содержимое полей, которые в свою очередь являются элементами блока, то это приведет к новому срабатыванию реактора, так как блок поменялся и так до бесконечности, а точнее сразу все прервется какой-нибудь фатальной ошибкой? Или нет?
TararykovDG вне форума  
 
Автор темы   Непрочитано 29.07.2010, 16:44
#4
Ax3

Programming, automation, CADs, GISs. "Теплоком"
 
Регистрация: 02.02.2007
Россия, Санкт-Петербург
Сообщений: 306


Проблема цикличного вызова реактора "из себя" решается просто введением флага активности реактора.
>Александр Ривилис Благодарю за подсказку. Такое решение кажется вполне подходящим. Попробую.

Вот только чем поля обновлять? В LISP-е не нашел такой функции. (command), опять же, нельзя - в реакторах не работает
__________________
На LISPе можно мыслить!

Последний раз редактировалось Ax3, 29.07.2010 в 17:01.
Ax3 вне форума  
 
Непрочитано 29.07.2010, 19:03
#5
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,411


vla-update не сработает?
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 29.07.2010, 19:40
#6
TararykovDG

Программист-энтузиаст
 
Регистрация: 17.07.2009
Воронеж
Сообщений: 575


vla-UpDate не сработал, может как через vla-FieldCode узнать формула для поля, а потом доставать "бубен" и в TextString записать обновленные данные?
TararykovDG вне форума  
 
Автор темы   Непрочитано 30.07.2010, 11:20
#7
Ax3

Programming, automation, CADs, GISs. "Теплоком"
 
Регистрация: 02.02.2007
Россия, Санкт-Петербург
Сообщений: 306


Парни, я решил проблему! Ключом оказалась функция (vla-sendcommand). Она сама дожидается освобождения ("простоя") автокада и симулирует ввод команд.

Таким образом получил следующее.
1. "Вешаю" реактор на свой блок:
Код:
[Выделить все]
;(c)Danilov_AS@GUNIPCGPSPb
  ;"Вешаем" реактор на только что созданный блок:
    (progn
      ;На случай ошибки при предыдущих выполнениях реактора - очистка флагов активности
      (setq upd-fields_command_active_ nil)
      (setq upd-fields_active_ nil)
      (setq
        is__stamp_reactor_
        (vlr-object-reactor
          (list is__mf__stamp_instance_) ; vla-объект!
          "Stamp Reactor"
          ;'((:vlr-modified . upd-fields))
          '((:vlr-objectClosed . upd-fields)) ;
        )
      )
(print is__stamp_reactor_)
2. Содержание callback-функции реактора:
Код:
[Выделить все]
(defun upd-fields
;(c)Danilov_AS@GUNIPCGPSPb
  (
  notifier-object
  reactor-object
  parameter-list
  /
  )
  (if
    (= upd-fields_active_ nil)
    (progn
      (setq upd-fields_active_ 't)
      (if
        (vlax-property-available-p
          notifier-object
          ;"Radius"
          "name"
        )
        (progn
;(princ "Block name: ")
(princ (vla-get-name notifier-object))
;(princ parameter-list)
          ;(command "_.updatefield" (vlax-vla-object->ename notifier-object "")
          ;(command "updatefield" uf__last_updated_object_ "")
          ;(vl-cmdf "_.regen")
          ;(entupd (vlax-vla-object->ename notifier-object))
          ;(vla-update (vlax-ename->vla-object (vlax-vla-object->ename notifier-object)))
;         ;----------------------------------------------------
;         ;This code causes fatal error :-):
;          (vla-regen
;            (vla-get-activedocument (vlax-get-acad-object))
;            0 ;active vp
;          )
;         ;----------------------------------------------------
          (setq uf__last_updated_object_ (vlax-vla-object->ename notifier-object)) ; - thx to Александр Ривилис@forum.dwg.ru
;(princ uf__last_updated_object_)
          (if
            (= upd-fields_command_active_ nil)
            (progn
              (setq upd-fields_command_active_ 't)
              (vla-sendcommand
                (vla-get-activedocument (vlax-get-acad-object))
                (strcat
                  "("
                  "progn"
                    "("
                    "vl-cmdf"
                      " "
                      (chr 34) "_.updatefield" (chr 34)
                      " "
                      "uf__last_updated_object_"
                      " "
                      (chr 34) (chr 34)
                    ")"
                    "("
                      "setq"
                      " "
                      "upd-fields_command_active_"
                      " "
                      "nil"
                      ")"
                    ")"
                (chr 13)
                )
              ) ;end vla-send-command
            )
          )
        );progn
      )
    );progn
  )
  (setq upd-fields_active_ nil)
)
То есть из callback-функции я делаю вызов (vla-sendcommand <лисповое выражение>) и запоминание названия модифицированного блока (Александру Ривилису спасибо за совет) в переменную last_updated_object. Лисповое выражение (отрабатывает по завершении реактора) содержит команду updatefield блока, указанного в last_updated_object и очистку флага активности команды. Флаг активности используется для исключения многократных рекуррентных вызовов функцией самой себя.

Спасибо за подсказки!

P.S. Поправка. Рекуррентные вызовы-то на самом деле, конечно, не исключаются, но само тело callback-функции при установленном флаге активности не выполняется. А вот исключить совсем рекуррентные вызовы можно теоретически "отцеплянием" реактора от блока в теле самого реактора (то есть на время выполнения реактора). По завершении работы реактора "прицеплять" его обратно. В Delphi подобный замут делал - работало, в LISP-е не пробовал еще...

P.P.S. Еще поправка. (vla-sendcommand), конечно, ничего не дожидается, видимо, она просто кладет указанные команды в некую очередь (пользовательских?) команд, которая как раз во время выполнения LISP-функций не обрабатывается кадом.

P.P.P.S. А, и еще важный момент. Надо позаботиться об удалении блока. То есть по идее при создании блока на него надо вешать два объектных реактора (vlr-object-reactor) - реактор на событие модификации (:vlr-modified либо :vlr-objectClosed) и реактор на событие "перед-удалением" (:vlr-goodbye). В реакторе "перед-удалением" надо отцеплять оба реактора от блока, иначе после удаления кад ругается "Automation error: object was erased". Но это так, к слову.

{}
По ходу, я рано обрадовался.
Глянул тему Supermax-а
http://forum.dwg.ru/showthread.php?t...command&page=2
и решил попробовать изменить lookup-ы своего блока из окна Properties.
И акад вылетел с треском!
Что делать?.. (риторический, наверно, вопрос :-))

{2010.08.02}
Посмотрев еще раз тему supermax-а, решил все-таки вынести само обновление полей во внешнее приложение, использующее связь с кадом по технологии COM.
Код callback-функции реактора преобразился примерно так:
Код:
[Выделить все]
(defun upd-fields
;(c)Danilov_AS@GUNIPCGPSPb
  (
  notifier-object
  reactor-object
  parameter-list
  /
  )
  (if
    (= upd-fields_active_ nil)
    (progn
      (setq upd-fields_active_ 't)
      (if
        (vlax-property-available-p
          notifier-object
          "name"
        )
        (progn
          (if
            (= upd-fields_command_active_ nil)
            (progn
              (setq upd-fields_command_active_ 't)
              (setq uf__last_updated_object_ (vlax-vla-object->ename notifier-object)) ; - thx to Александр Ривилис@forum.dwg.ru
              ;Сохраняем ssfirst:
              (setq uf__pickfirst_ (ssget "_i"))
              ;Вызываем внешнее приложение.
              ;Оно должно сделать следующее:
              ;1. Выдержка или ожидание отработки окна properties
              ;2. Обновление полей
              ;3. Восстановление pickfirst
              ;4. Сброс флага активности команды
              ;5. Очистка переменной ssfirst
              (startapp ;async????? yes!!!!!
                "B:\\Apps\\upd_fields.exe"
              )
            )
          )
        );progn
      )
    );progn
  )
  (setq upd-fields_active_ nil)
)
Исходный код внешней программы обновления полей (AutoIT):
Код:
[Выделить все]
Global $acad_obj_
Global $tmp_
$acad_obj_=ObjGet('','AutoCAD.Application')
;1:
acad_send_command_correctly('(prompt (strcat "please wait while updating " (vla-get-name (vlax-ename->vla-object uf__last_updated_object_)) "\n"))')
;2:
$tmp_='(vl-cmdf "_.updatefield" uf__last_updated_object_ ""'
If StringLeft($acad_obj_.version,4)='17.1' Then
	If StringLeft($acad_obj_.Preferences.Profiles.ActiveProfile,StringLen('AutoCAD Architecture'))='AutoCAD Architecture' Then
		$tmp_=$tmp_ & ' ""'
	EndIf
EndIf
acad_send_command_correctly($tmp_ & ')')
;3:
acad_send_command_correctly('(sssetfirst nil uf__pickfirst_)')
;4:
acad_send_command_correctly('(setq uf__pickfirst_ nil)')
;5:
acad_send_command_correctly('(setq upd-fields_command_active_ nil)')

Func acad_send_command_correctly($ascc__command_)
	While $acad_obj_.GetAcadState.isquiescent=False
		Sleep(200)
	WEnd
	$acad_obj_.activedocument.sendcommand($ascc__command_ & Chr(13))
EndFunc

Exit
В этом варианте внешняя программа вполне корректно дожидается, когда кад освободится (используя признак $acad_obj_.GetAcadState.isquiescent) и наконец-то появится возможность подпихнуть ему свои команды, и собственно делает это.
Работает пока без сбоев, никаких "тупо подождать пару секунд" нет, единственное узкое место - работа с винчестером для запуска внешней программы. С точки зрения программиста - через одно место, но зато надежно, при редактировании свойств (в т.ч. лукапов) блока из окна properties все отрабатывает без ошибок.
Интересно, можно ли это считать решением?
__________________
На LISPе можно мыслить!

Последний раз редактировалось Ax3, 30.07.2010 в 19:00.
Ax3 вне форума  
 
Непрочитано 17.08.2010, 11:23
#8
Eddicordo

КИП и А
 
Регистрация: 28.04.2010
Киев
Сообщений: 101
<phrase 1=


Цитата:
Сообщение от Ax3 Посмотреть сообщение
Парни, я решил проблему! Ключом оказалась функция (vla-sendcommand). Она сама дожидается освобождения ("простоя") автокада и симулирует ввод команд.
Уважаемый. А можно сделать готовый вариант Вашего решения. Закинуть в файлики. Или эти 2 кода нужно сохранить в один *.lsp ?? А то я чет не понимаю куда сохранять Ваш код. И как прикреплять этот реактор к конкретному блоку.
Извините за глупые вопросы.

У меня возник вопрос по автобновлениям. тут А вот сам вопрос #2065

Последний раз редактировалось Eddicordo, 17.08.2010 в 11:36.
Eddicordo вне форума  
 
Автор темы   Непрочитано 24.08.2010, 11:16
#9
Ax3

Programming, automation, CADs, GISs. "Теплоком"
 
Регистрация: 02.02.2007
Россия, Санкт-Петербург
Сообщений: 306


>>Eddicordo
Дружище, извини, давно не заглядывал в тему.
Да, конечно, через денек-другой сделаю и выложу.
На самом деле работа с реакторами оказалась несколько сложнее, чем я полагал вначале :-)
__________________
На LISPе можно мыслить!
Ax3 вне форума  
 
Непрочитано 26.08.2010, 11:01
#10
Eddicordo

КИП и А
 
Регистрация: 28.04.2010
Киев
Сообщений: 101
<phrase 1=


Цитата:
Сообщение от Ax3 Посмотреть сообщение
Да, конечно, через денек-другой сделаю и выложу.
Спасибо. Ждем.
Eddicordo вне форума  
 
Автор темы   Непрочитано 01.09.2010, 15:16
#11
Ax3

Programming, automation, CADs, GISs. "Теплоком"
 
Регистрация: 02.02.2007
Россия, Санкт-Петербург
Сообщений: 306


{2010.09.01 15.30}
Выложил в заголовке. Инструкции и описание - внутри, файл !readme!

P.S.
С днем знаний! :-)

{2010.09.01 17.36}
P.P.S.
Есть еще усложненный код, который сравнивает значения атрибутов до и после обновления и меняет цвет атрибута, текст которого изменился (то есть показывает пользователю, какие атрибуты он заполнил, а какие - нет). Если надо - могу выложить.

{2010.09.01 18.30}
P.P.P.S.
Друзья, у кого есть возможность - протестируйте, пожалуйста! Буду очень благодарен за нахождение новых багов :-)

{2010.09.06 09:06}
Пришла светлая мысль перенести весь LISP-код обновления полей обратно в LISP-программу. Это исключает конфликты кода обновления с кадом из-за его занятости. Во внешнем приложении оставил только вызов программы обновления полей плюс добавил обработку COM-ошибок, т.к. иногда не удавалось заставить кад отработать sendcommand с первого раза.
Версия 1.01 выложена в заголовке.
Для изучения COM-поведения када использовалась вот эта программка:
ACAD_COM_test(c)Danilov_AS_aka_`Hawk`_2010.09.03.rar
__________________
На LISPе можно мыслить!

Последний раз редактировалось Ax3, 06.09.2010 в 09:13.
Ax3 вне форума  
 
Непрочитано 19.10.2010, 17:58
#12
Eddicordo

КИП и А
 
Регистрация: 28.04.2010
Киев
Сообщений: 101
<phrase 1=


Можешь выложить что то по проще. И без привязки к определенному полю дин блока.
А то запустить некую постороннюю программу добавить доп меню. Очень сложно для пользования обычными пользователями.
Или я не правильно ее использовал........ все по инструкции.
За пример можно взять самый простой дин блок в котором линия с атрибутом в котором поле с длиной линии.
Eddicordo вне форума  
 
Автор темы   Непрочитано 21.10.2010, 14:44
#13
Ax3

Programming, automation, CADs, GISs. "Теплоком"
 
Регистрация: 02.02.2007
Россия, Санкт-Петербург
Сообщений: 306


в readme написано:
Цитата:
Использование программы:
(0. Закрыть кад)
1. Запустить ACAD_apps_u.setup.exe
2. Запустить кад.
Появится панель инструментов blk_autoupd, дальше все понятно
Так делал?

Поясни, плз, что значит "без привязки к определенному полю дин.блока?" Блок, приложенный в качестве примера, обновляется целиком независимо от того, какое поле или динамическое свойство было отредактировано
__________________
На LISPе можно мыслить!
Ax3 вне форума  
 
Непрочитано 26.10.2010, 18:22
#14
Eddicordo

КИП и А
 
Регистрация: 28.04.2010
Киев
Сообщений: 101
<phrase 1=


Ax3
Извени что долго не отвечал.

Выполняю все как написано.
Цитата:
Сообщение от Ax3 Посмотреть сообщение
Использование программы:
(0. Закрыть кад)
1. Запустить ACAD_apps_u.setup.exe
2. Запустить кад.
Появится панель инструментов blk_autoupd, дальше все понятно
Появилась панелька, но кроме вставки штампа с панельки больше ничего не обновляется.
Оп заметил что у тебя поля в атрибуте забиты как то по иному.(Выбор Лукапа)
Может из за этого?
Тогда встречный вопрос.
Как забить в атрибут поле с выбором Лукапа?
Я обычно указываю какой лукап. Вот файл Вариант №1.dwg
http://forum.dwg.ru/showpost.php?p=639362&postcount=106

Да и это получается что каждый раз как мне надо работать в AutoCad с дин блоками нужно будет всегда запускать файл ACAD_apps_u.setup.exe


День спустя.
Странно проделываю все что было сказано и уже не работает выдает ошибку
Код:
[Выделить все]
Команда: (bu__insert_blk__main_func) ; ошибка: no function definition: 
BU__INSERT_BLK__MAIN_FUNC

Последний раз редактировалось Eddicordo, 27.10.2010 в 17:33.
Eddicordo вне форума  
 
Автор темы   Непрочитано 29.10.2010, 20:00
#15
Ax3

Programming, automation, CADs, GISs. "Теплоком"
 
Регистрация: 02.02.2007
Россия, Санкт-Петербург
Сообщений: 306


>>Eddicordo
1. Немного изменил сборку.
Распаковываешь архив, запускаешь 0_ainst_universal_script_v1.09(c)Danilov_AS_aka_`Hawk`_2009.12.15.exe.
Если все нормально отработает, то:
- Папка blk_autoupd появится в %Program Files%\ACAD_addons\
- blk_autoupd.lsp будет добавлен в Startup Suite
- при первом (после установки данной программы) запуске автокада появится сообщение об обновлении панели `blk_autoupd`
2. Вместо тестового блока вставил твой, только атрибуты в нем сделал предустановленными.

Ну а дальше понятно - на появившейся в каде панельке интсрументов `blk_autoupd` жмем серую кнопку, вставится блок, щелкаем в нем лукапы - срабатывает автообновление.
После закрытия-открытия чертежа автообновление не работает. Для восстановления автообновления нажать красную кнопку.

Если надо вставить в значение атрибута не свойства объекта, а значения лукапов, то в block editor'е в диалоговом окне вставки поля в левом списке выбрать не "Объект", а "BlockPlaceHolder" (по-русски, кажись, "Местозаполнитель блока").

Отпишись, плз, как проверишь, - работает ли. Удачи.
Кстати, любопытно - что это за блок? В смысле как он используется и для чего?
Вложения
Тип файла: rar blk_autoupd_v2.0(с)Danilov_AS_aka_`Hawk`_2010.10.29.rar (1.27 Мб, 85 просмотров)
__________________
На LISPе можно мыслить!

Последний раз редактировалось Ax3, 29.10.2010 в 20:08.
Ax3 вне форума  
 
Непрочитано 01.11.2010, 12:59
#16
Eddicordo

КИП и А
 
Регистрация: 28.04.2010
Киев
Сообщений: 101
<phrase 1=


ОО вроде работает отлично с моим блоком "Кабель".
Есть очень большой минус.
Обновляется только блок с именем "Кабель". А если на чертеже много блоков с полями и разными именами. Они не обновляются.
Я так понял нужно дописывать ИМЕНА всех используемых блоков.
Куда дописывать?


Цитата:
Сообщение от Ax3 Посмотреть сообщение
После закрытия-открытия чертежа автообновление не работает. Для восстановления автообновления нажать красную кнопку.
Очень не удобно. Можно сделать что бы при открытии нового чертежа программа сама нажимала кнопку обновить. Для чего лишние клацанья?
Да и это мне понятно что для обновления нужно клацнуть. А другие могут и не понять что если хочешь автообновление то при каждом заходе на чертеж нужно по клацать там, там и еще там. Да и перед компом 3 раза присесть и сказать волшебное слово.


Цитата:
Сообщение от Ax3 Посмотреть сообщение
Кстати, любопытно - что это за блок? В смысле как он используется и для чего?
Блок по выбору марки кабели и трубы для приборов и не только.
Естественно блок сырой и набросан по быстрому что бы идея была понятна.
Используется он очень просто.
Каждый прибор соединяется кабелем и куда то подключается (клеммная коробка, щит и т.д.).
Вот на "Схеме соединений внешних проводок" КИП и А нужно показывать каким именно кабелем ты подключаешь прибор и куда ведешь его.

Вот еще одно не удобство.
При изменении одного из Лукапов и автообновлении, его выделение блока снимается.
В моем случае с блоком "Кабель" для настройки блока нужно поиграться с 4 Лукапами. То есть 4 раза выделять блок заново приходится. Что не есть хорошо.
Обновление должно происходить с тем блоком который я выделил. И не выходить из выделения пока я сам этого не захочу стандартным методом.
Выходя с этого более реально сделать автообновление полей в блоках по всему чертежу, а не конкретных которых я прописал где то. Тобиш обновление происходит только с выделенным блоком. А не автообновление всех блоков на чертеже. Что и не будет влечь за собой нагрузку на ПК и тормоза.

Последний раз редактировалось Eddicordo, 01.11.2010 в 14:05.
Eddicordo вне форума  
 
Автор темы   Непрочитано 03.11.2010, 16:59
#17
Ax3

Programming, automation, CADs, GISs. "Теплоком"
 
Регистрация: 02.02.2007
Россия, Санкт-Петербург
Сообщений: 306


Ну, раз дело пошло - за праздники постараюсь доработать :-)
__________________
На LISPе можно мыслить!
Ax3 вне форума  
 
Непрочитано 10.11.2010, 10:59
#18
Eddicordo

КИП и А
 
Регистрация: 28.04.2010
Киев
Сообщений: 101
<phrase 1=


Ax3,
Дело пойдет если будет что тестить и проверять на работоспособность
Eddicordo вне форума  
 
Автор темы   Непрочитано 30.11.2010, 14:40
#19
Ax3

Programming, automation, CADs, GISs. "Теплоком"
 
Регистрация: 02.02.2007
Россия, Санкт-Петербург
Сообщений: 306


Cорри. В нашей нелегкой жизни так часто бывают запарки и геморрои.
Версия 2.1.
Реактор обновления теперь сохраняется в чертеже. Красная кнопка больше не нужна. Однако если открыть чертеж на компе, где не установлена программа blk_autoupd, при изменении лукапа блока кад будет ругаться на то, что "; error: no function definition: BU__UPD-FIELDS_FUNC". В принципе это не страшно, просто так - к сведению.
blk_autoupd_v2.1(c)Danilov_AS_aka_`Hawk`_2010.11.30.rar

Пока на большее не созрел, извиняй, дружище.

P.S.
По поводу снятия выделения. Технически - на самом деле выделение не снимается. Просто есть у Автокада какой-то глюк с прорисовкой pickfirst selection set (я использую функцию sssetfirst), выражающийся в том, что пропадают ручки редактирования у объектов, включенных в pickfirst selection set. Впрочем, как бы там ни было, эта проблема пока не решена.

P.P.S.
По поводу других блоков.
Как лучше реализовать? Мне в голову пришли такие способы:
1. Для каждого блока - своя кнопка в панели инструментов для его вставки в чертеж.
2. Одна кнопка (назовем ее "Повесить реактор на блок", например), которая просит указать блок и включает автообновление полей указанного блока.
3. Тупо, без разбора вешать реакторы на все блоки при их вставке в чертеж (или прописать список блоков, на которые вешать автообновление, и делать это при вставке в чертеж блоков, перечисленных в этом списке)

{Добавлено _2010.12.04_22.39.22}
Или вот еще мысль.
4. При создании все блоки, к которым предполагается прикреплять автообновление полей, помечаются каким-нибудь скрытым атрибутом. Тогда можно прописать реактор на команду вставки блока, который будет анализировать вставленный в чертеж блок на предмет этого самого скрытого атрибута и при его обнаружении будет прикреплять реактор автообновления полей к вставленному экземпляру блока.
Но этот вариант будет слегка тормозить работу Автокада и вообще он замороченный.

Мне кажется, что оптимально будет сделать панель инструментов с кнопками для вставки всех нужных блоков. Ну и в главное меню в раздел "Вставка" можно добавить пункт "Блоки кабелей"-><список блоков>.
__________________
На LISPе можно мыслить!

Последний раз редактировалось Ax3, 04.12.2010 в 22:46.
Ax3 вне форума  
 
Непрочитано 13.01.2011, 17:24
#20
Frigate

КИП, АСУ ТП, слаботочка
 
Регистрация: 02.09.2010
Москва-Тюмень
Сообщений: 422


Доброе время автору темы и всем-всем-всем!

Тоже решил сегодня разобраться с реакторами. И мне это удалось. Благодаря автору и еще некоторым программистам с этого форума.

Вот этот код можно закинуть в .lsp файл, сохранить и загрузить как приложение:

Код:
[Выделить все]
(PRINC "\nВыберите блоки, которые хотите сделать самообновляемыми:")
 
;============================================================================= 
;|
*    Функция преобразования набора, полученного через (ssget), в список 
* vla-примитивов. 
*    Параметры вызова: 
*   selset   набор примитивов 
*    Примеры вызова: 
(adv-convertdatatype-selset-to-vlalist (ssget)) 
|;
(defun adv-convertdatatype-selset-to-vlalist (selset)
  (if selset
    (mapcar 'vlax-ename->vla-object
            (adv-convertdatatype-selset-to-list selset)
    ) ;_ end of mapcar
  ) ;_ end of if
) ;_ end of defun
 
(setq vla_selset
    (adv-convertdatatype-selset-to-vlalist (ssget '((0 . "INSERT")(66 . 1))))
    flag nil
    flag_command nil
) ;_end of setq
 
 
 
 
(setq Obj_fields_Update (vlr-object-reactor vla_selset
 "Obj_Closed-Reactor" '((:vlr-objectClosed . adv-reac-block-update_fields))))
 
 
(defun adv-reac-block-update_fields (notifier-object reactor-object parameter-list / r_obj)
(PRINC(entget (vlax-vla-object->ename notifier-object)))
(if (null flag)
    (PROGN         ;PROGN1
    (setq flag T)
    (setq obj_to_upd (vlax-vla-object->ename notifier-object))
(if (null flag_command)
    (PROGN        ;PROGN2
    (setq flag_command T)
    (vla-sendcommand
        (vla-get-activedocument (vlax-get-acad-object))
            (strcat
            (vl-prin1-to-string '(PROGN
                (vl-cmdf "_UPDATEFIELD" obj_to_upd "" "") ;<<<красным выделено изменение от 14.01.2011
                (setq flag_command nil)
            ))    
            "\r"
            )
    )
) ;end of PROGN
)
) ;end of PROGN
)
(setq flag nil)
)
Выделяем нужные нам блоки, и они становятся автоматически обновляемыми.

Просто такая легко модифицируемая форма проще воспринимается, чем готовое внешнее приложение, управляющее акадом, по крайней мере такими начинающими лисперами-любителями как я.

Автору респект и увжуха


Возник такой вопрос - можно ли как-нить так переделать код, чтобы измененный нами блок остался выделенным? Работа реактора и callback функции убивает грипсы - выделение блока исчезает. Пробовал внутри vla-sendcommand выделить при помощи sssetfirst, но не получилось.


Нашел ответ:

(vl-cmdf "_.regen")

только на слабых компах ощутимые тормоза начинаются )))

Последний раз редактировалось Frigate, 14.01.2011 в 06:54.
Frigate вне форума  
 
Непрочитано 13.01.2011, 19:22
#21
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,996


Зыбыл добавить описание функции adv-convertdatatype-selset-to-vlalist
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума  
 
Непрочитано 14.01.2011, 06:47
#22
Frigate

КИП, АСУ ТП, слаботочка
 
Регистрация: 02.09.2010
Москва-Тюмень
Сообщений: 422


что-то сегодня прога нормально работает только если изменить строку:

Код:
[Выделить все]
(vl-cmdf "_UPDATEFIELD" obj_to_upd "")
на

Код:
[Выделить все]
 
(vl-cmdf "_UPDATEFIELD" obj_to_upd "" "")
VVA,

точно )))

Сейчас откорректирую пост. №20

В принципе, эта функция является "чкстно стыренной" у тебя же


Интересно узнать, как у других сработает код, с каким вариантом строки "(vl-cmdf ...)"


Совместно с реакторами на удаление объекта работать не получается. ПОможет ли здесь удаление первого реактора и запись его пар во второй объект реактора? И как удалить реактотр? Именно удалить, а не остановить (vlr-remove), которая все равно не работает.

Последний раз редактировалось Frigate, 14.01.2011 в 07:29.
Frigate вне форума  
 
Автор темы   Непрочитано 19.01.2011, 12:33
#23
Ax3

Programming, automation, CADs, GISs. "Теплоком"
 
Регистрация: 02.02.2007
Россия, Санкт-Петербург
Сообщений: 306


>>Frigate
По поводу внешнего приложения.
Я в самом начале так же, как и ты, решил, что (vla-sendcommand) поможет. Но попытка изменения свойств блока из окна properties приводила к Fatal Error (см. пост #7), поэтому я и решил вынести обновление блока во внешнее приложение.

Однако мой опыт работы в этом направлении показал, что работа с реакторами чрезвычайно... (прошу прощения за выражение) геморройна. То есть автообновление полей несложных блоков, пожалуй, имеет смысл, а со сложными динамическими блоками это всё работает как-то через ж... Впрочем, помучившись изрядно, я добился-таки стабильной работы своего блока с автообновлением, но второй раз что-то уже нет желания повторять такое :-)

По поводу (vl-cmdf "_UPDATEFIELD" obj_to_upd "" "") и проблем с одной/двумя кавычками - ха, спасибо, друг, подтвердил мои проблемы, описанные в теме http://forum.dwg.ru/showthread.php?p=606042#post606042.
Я этот момент поборол так:
Код:
[Выделить все]
  ;На всякий случай избавляемся от влияния pickfirst:
  (setq ufx__uffe__pickfirst_var_ (getvar 'pickfirst)) ; - запоминаем исходное значение PICKFIRST
  (setvar 'pickfirst 0)
  ;(sssetfirst nil nil) ; - добавлено как попытка устранения Fatal Error при попытке изменения штампа сразу после открытия чертежа. Но не помогло.
  (vl-cmdf "_.updatefield" ufx__uffe__being_updated_object_ "")
  (setvar 'pickfirst ufx__uffe__pickfirst_var_) ; - восстановление пользовательского PICKFIRST
    (setq ufx__uffe__pickfirst_var_ nil)
__________________
На LISPе можно мыслить!

Последний раз редактировалось Ax3, 19.01.2011 в 12:44.
Ax3 вне форума  
 
Непрочитано 19.01.2011, 13:53
#24
Лиспер


 
Регистрация: 11.10.2010
Сообщений: 979


Я не очень понимаю, а в updatefield подставляется указатель на вхождение блока, что ли (просто не сталкивался с такой задачей)? Если да, то почему б не попробовать так:
Код:
[Выделить все]
 (vl-load-com)

(defun test (/ adoc selset layouts blockrefs _dwgru-conv-pickset-to-list active_layout)

  (defun _dwgru-conv-pickset-to-list (value / tab item)
    (repeat (setq tab  nil
                  item (sslength value)
                  ) ;_ end setq
      (setq tab (cons (ssname value (setq item (1- item))) tab))
      ) ;_ end repeat
    ) ;_ end defun

  (vla-startundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  (vlax-for item (vla-get-layouts adoc)
    (setq blockrefs (cons (cons item
                                (_dwgru-conv-pickset-to-list
                                  (ssget "_X" (list '(0 . "INSERT") '(66 . 1) (cons 410 (vla-get-name item))))
                                  ) ;_ end of _dwgru-conv-pickset-to-list
                                ) ;_ end of cons
                          blockrefs
                          ) ;_ end of cons
          ) ;_ end of setq
    ) ;_ end of vlax-for
  (setq active_layout (vla-get-activelayout adoc))
  (foreach item blockrefs
    (vla-put-activelayout adoc (car item))
    (foreach blockref (cdr item)
      (command "_.undatefield" blockref "")
      ) ;_ end of foreach
    ) ;_ end of foreach
  (vla-put-activelayout adoc active_layout)
  (vla-endundomark adoc)
  (princ)
  ) ;_ end of defun
Код не проверял вообще.
---
P.S. Спасибо Админу, классную кнопочку сделал!
__________________
(/= RegDate StartReadDate)
Лиспер вне форума  
 
Непрочитано 19.01.2011, 13:55
#25
Frigate

КИП, АСУ ТП, слаботочка
 
Регистрация: 02.09.2010
Москва-Тюмень
Сообщений: 422


точно )))
а я не вникал в суть этой переменной раньше...

ее изменение в "0" (если потом не восстановить, в том числе предусмотреть это и в обработике ошибок) может сильно осложнить жизнь юзерам автокада - ничего нельзя привычным способом отредактировать


вот так вот поменял функцию callback:

Код:
[Выделить все]
 
(defun adv-reac-block-update_fields (notifier-object reactor-object parameter-list)
(if (null flag)
    (PROGN         ;PROGN1
    (setq flag T)
    (setq obj_to_upd (vlax-vla-object->ename notifier-object))
(if (null flag_command)
    (PROGN        ;PROGN2
    (setq flag_command T)
    (vla-sendcommand
        (vla-get-activedocument (vlax-get-acad-object))
            (strcat
            (vl-prin1-to-string '(PROGN
  (setq PICKFIRST_old (getvar "PICKFIRST"))
  (setvar "PICKFIRST" 0)
                (vl-cmdf "_UPDATEFIELD" obj_to_upd "")
                (setq flag_command nil)
  (setvar "PICKFIRST" PICKFIRST_old)
  (setq nbr_blocks (ssadd obj_to_upd)) ; <<< эту строку надо убрать
  (sssetfirst nil nbr_blocks)       ; <<< эту строку надо убрать
            ))    
            "\r"
            )
    )
) ;end of PROGN
)
) ;end of PROGN
)
(setq flag nil)
)

пока вроде работает

Лиспер,

что-то я не понимаю, как твою функцию применить в callback функции...

Ведь реактор кинет в callback функцию (у мня пока другого не получалось) только ОДИН указатель на блок, и обновлять надо именно этот блок.

К тому же в твоем коде именно комендный метод, который и применен у меня, именно такой вариант убирает выделение блока после редактирования его динсвойств.

Что заметил:

эти две строки

Код:
[Выделить все]
 (setq nbr_blocks (ssadd obj_to_upd)) ; создали пустой набор
  (sssetfirst nil nbr_blocks)
в реальности-то выделяют измененный блок, на котором висит реактор, НО это выделение становится видно только после _regen.

Ну, как я уже писал, в таком случае можно вообще обойтись регенерацией, не затрагивая обновление полей - и выделение не пропадает и все нормуль, только слабые компы подвисают )))

Есть ли возможность сделать регенерацию для отдельного объекта (у нас - блока)?

ТОлько не _update - это поля не обновляет

Прошу прощения, выделил в коде красным две строки, которые все равно не работают, а иногда и вызывают сбой... Я о выделении через ssetfirst. Их лучше убрать.

Итак вывод: обновление полей автоматом после изменения динсвойства блока возможно. Но оно неприменимо для динблоков, с динсвойствами которых часто и много работают, т.к. при обновлении полей исчезает выделение блока, вернуть выделение у меня не получилось. Нуа ГУРУ ЛИСПа пока тоже не отвечают, возможно этой проблемой никто и не занимался, зная проблемность реакторов.

Единственный вариант, когда возможно обновить поля и сохранить выделение - это использовать вместо _updatefiekd регенерацию _regen. Но - слабые компы такого издевательства не выдержат. Так что это нельзя назвать универсальным инструментом, так как у пользователя не обязательно будет навороченный комп.

Последний раз редактировалось Frigate, 20.01.2011 в 06:49.
Frigate вне форума  
 
Непрочитано 29.04.2014, 16:08
#26
sam_n


 
Регистрация: 04.06.2013
Сообщений: 34


Попробую поднять тему. Так у меня лисп в итоге и не заработал. Хотя сам Frigate говорит, что все отлично работает.
sam_n вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Как автоматически обновлять поля блока?



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Некорректно обновляются поля блока NEDIS AutoCAD 50 19.02.2013 15:47
Поля атрибутов вложенного блока не отображают своих значений hwd AutoCAD 7 23.12.2009 08:40
Подскажите, пожалуйста, как сделать описание (description) для блока? Ламер AutoCAD 5 27.08.2009 14:33
Мониторы LCD CRT Разное 94 17.06.2008 10:51
Как в чертеже автоматически прописать полный путь? Соня AutoCAD 5 14.09.2004 16:33