Re: Макрос на кнопку "Отключение слоя или группы слоев"

> VVA
А что, решение хорошее. Гибкое. Все корректно работает. Макросы, которые предложили Владимир Громов и kpblc тоже хороши. Но могу предположить, что программа представленная Вами обойдет  по удобству работы. Я поработаю несколько дней и сообщу о результатах. Но на первый взгляд- это то, что нужно. Большое спасибо.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

Самое главное, что гибкое. Кнопка одна, и требование одно: имя фильтра должно быть то, что на кнопке, а вот его наполнение от чертежа к чертежу меняется.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> VVA
Вот. Все отлично работает. Я только макрос на кнопку чуть подправил.

C^C^((if (not C:layer-filters-status-change) (load "layer-filters-status-change")) (layer-filters-status-change "AT");

Может кому пригодится. А так все нормально. Еще раз спасибо.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Sailor
Неверно вы код макроса кнопки подправили. В программе VVA нет определения функции C:layer-filters-status-change. У VVA программа, видимо, находится в автозагрузке, поэтому в его макросе нет функции "load". Ваш код будет работать, потому что расшифровать его работу можно так:
если в памяти нет команды C:layer-filters-status-change, то необходтмо загрузить файл layer-filters-status-change.lsp (расширение не пишется) и выполнить находящуюся в нем функцию layer-filters-status-change. Но ведь команды такой совсем нет, и значит файл будет всегда загружаться в память. А вот если бы она была в памяти, то загружать файл каждый раз при нажатии кнопки не надо было бы. Команда сразу выполнялась бы. Ваш макрос может выглядеть так:

^C^C(load "layer-filters-status-change") (layer-filters-status-change "AT")

Обратите внимание на первые символы в макросе, как они должны быть записаны. Я эту программу не пробовал, так как не работаю с фильтрами слоев.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Владимир Громов
В первом варианте макрос был такой

(layer-filters-status-change "AT")

. Вот я и попытался загрузить программу с кнопки и отработать ее. А как мне корректно загрузить программу, что бы она работала для всех открытых чертежей и для чертежей открываемых впоследствии?

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Sailor
Обычно я определяю функцию как "C:ИМЯ_ФУНКЦИИ". В этом случае функция становится новой командой AutoCAD'а и может повторно выполняться по правой кнопке мыши, по "Enter" и по нажатию пробела. Другие не используют префикс "C:", потому что им надо передать параметр(ы) в функцию, как в данном случае. Макрос, который я написал, будет работать, только всегда будет загружаться файл с программой в память. Если это нежелательно, то можно, IMHO, записать макрос так:

^C^C(if (not (layer-filters-status-change)) (load "layer-filters-status-change")) (layer-filters-status-change "AT")

Тут я не совсем уверен в правильности записи.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Владимир Громов
Честно говоря, мне трудно это понять. Знаний не хватает. Я не очень представляю как  размещается второй раз вызываемая LICP программа в памяти. По тем же адреспм, что и первая? Или уже по другим. И не понимаю как взаимодействуют одна и та же программа в разных открытых чертежах. Насколько возможна ошибка. Но тот макрос, который я интуитивно написал, вроде, работает. Сначала при вызове выскакивала ошибка связанная с количеством скобок, но сама программа отрабатывалась корректно. Потом, опытным путем я поменял скобки и ошибка при вызове исчезла. Внешне, как будь то все нормально. А что на самом деле происходит, не очень представляю.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

А вот почитайте тут:
https://www.caduser.ru/forum/topic19699.html
если, конечно, хватит терпения.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

Перечитал сам и,похоже, последний макрос должен выглядеть так:

^C^C(if (not layer-filters-status-change) (load "layer-filters-status-change")) (layer-filters-status-change "AT")

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Владимир Громов
Прочел то, что написано в рекомендованной ветке. В общем то понятно. И ваш последний макрос согласуется с теми положениями, которые  выложены в той ветке. Кстати, макрос работает корректно. Я установил его, проверил. Работает. Так он и остался в CUI. Но и мой макрос, вроде не верный, то же работал без видимых ошибок. Т.е. с запуском и исполненим макроса с передачей аргумента и соответственно с запуском и исполнением программы в соответствии с передаваемым аргументом все в порядке. Можно эту тему логически закончить с положительным результатом....
  Но я не сумел все таки уяснить как же все таки взаимодействуют одинаковые программы. И почему требуется при открытии другого чертежа вновь вызывать программу ранее вызванную в другом чертеже. Это, конечно, теория, но интересно было бы иметь хоть какое то представление. Об этом в той ветке ничего не было написано. Без уяснения глубины речки, как то страшновато плыть. Можно и на мель сесть. Ну и о синтаксике макрокоманд на кнопках там ни слова. Мне кажется это упущение. Для меня это большая проблема. Ведь ветка посвящена неопытным пользователям, которые мало что смыслят в программировании, но работать уже надо. Примерно, таким как я. Тем более есть достаточно много хороших программ, которые бы хотелось правильно запустить. Я сейчас работаю по шаблонам, которые предоставляют такие опытные специалисты как Вы. Но хотелось бы и самому уверено плыть. Впрочем, все это к данной теме отношения не имеет.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

Вопрос загрузки лиспа мной не рассматривался, у нас свое меню и mnl файл погружает необходимое. Но если необходимо подгружать, я бы сделал как
Владимир Громов (2006-05-29 22:08:43), только вместо пробела поставил бы ; мне так нагляднее.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

Все таки я бы поступил по другому. Я бы завел себе файл, куда бы складывал нужные мне лиспы. Пусть он назывется mylisp.lsp. Копируем туда код ф-ции layer-filters-status-change. В команде _appload в автозагрузку помещаем ссылку на файл mylisp.lsp. В файл mylisp.lsp добавляем еще одну строку

(defun C:AT ()(layer-filters-status-change "AT"))

Мы создали команду Автокада с именем AT, которая будет изменять групповой фильтр с именет "AT" (english) и автоматом загружаться во все открываемые чертежи.
Тогда макрос на кнопку выглядит

'AT;

Преимущество в том, что отсутствует ^C^C, т.е. команда выполняется прозрачно.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Sailor
Вот еще пришла идея в голову. Без использования групповых фильтров. Основная проблема у нас состоит в том, что не решено, где хранить список отключаемых слоев, если он может быть разным для разных рисунков да и в конкретном рисунке может меняться. В системной переменной USERS информация не сохраняется, она действительна только на перид сеанса работы. В текстовых файлах, привязанных к рисунку тоже не удобно. Использовать групповые фильтры - громоздко, на мой взгляд, и для данной задачи не оптимально. Но подход VVA правильный. Нужна программа, инвариантная к списку слоев. Сам список должен быть в рисунке, а программа только вытаскивает этот список, обрабатывет его и выполняет нужные действия. Так где хранить такой список с возможностью легкого его редактирования? А вот где - в атрибуте. Создается атрибут с именем, допустим, "LAY_OFFON" на непечатаемом слое. В качестве значения атрибута задается список слоев. Далее программно извлекается этот список и обрабатывается. Таким образом, программа будет работать одинаково для всех рисунков. Список слоев в атрибуте изменяется чрезвычайно легко - достаточно дважды щелкнуть на нем. Рассматривал я еще вариант с полем, но там все сводится к MText'у, это как-то не интересно. Извлечение списка слоев из атрибута я уже отработал, теперь надо продумать механизм обработки этого списка.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> [url=https://www.caduser.ru/forum/topic20414.html]Владимир Громов (2006-05-30 10:56:21)[/url]

Я вижу один недостаток - это вписывать имена слоев ручками. Можно просто допустить описку.
Тогда надо писать диалог, который выбирает слои и запихивает их в атрибут.

продумать механизм обработки этого списка

Если допустить, что имена слоев в атрибуте отделяются друг от друга , уже прочитаны и хранятся в переменной LAY_LIST
например

(setq LAY_LIST "Слой1,Слой2,Слой3")

тогда дальше

(setq LAY_LIST (str-str-lst LAY_LIST ","))
(setq LAY_LIST (mapcar '(lambda (s)(vla-item (vla-get-layers (vla-get-activedocument (vlax-get-acad-object))) s)) LAY_LIST))
(setq onoff_list (mapcar 'vla-get-LayerOn LAY_LIST))
(if (vl-member-if '(lambda (s)(eq s :vlax-false)) onoff_list)
        (setq onoff :vlax-true) ;_Хотя бы один слой выключен
        (setq onoff :vlax-false)
        )
(mapcar '(lambda (x)(vla-put-layeron x onoff)) LAY_LIST)

Ф-цию str-str-lst брать здесь https://www.caduser.ru/forum/topic25197.html Евгений Елпанов (2006-03-05 19:33:41)

Re: Макрос на кнопку "Отключение слоя или группы слоев"

Смешная программа, но работает.
Условие: слои должны существовать.
Проверка текущего слоя не выполняется, словом, примитивная программа.
Но себе я ее оставлю, может, на досуге доработаю.

(defun C:LAYOFFON ( / lay lay_list)
(setq lay (getvar "CLAYER"))
(if (tblsearch "LAYER" "lay_offon")
    (progn
    (ssget "_X" (list (cons 8 "lay_offon")))
    (setq lay_list (cdr (assoc 1 (entget (entlast)))))
    (Cond
         ((= (getvar "USERI1") 0)
         (command "_-layer" "_off" lay_list "")
         (setvar "USERI1" 1)
         )
         ((= (getvar "USERI1") 1)
         (command "_-layer" "_on" lay_list "")
         (setvar "USERI1" 0)
         )
    )
    )
    (progn
    (princ "\n Для работы программы необходимо определить атрибут на слое LAY_OFFON.")
    (alert "   Для работы программы необходимо\nопределить атрибут на слое LAY_OFFON.")
    (command "_-LAYER" "_m" "LAY_OFFON" "_p" "_n" "LAY_OFFON" "")
    (command "_attdef" "" "LAY_OFFON" "Записать слои через запятую без пробелов" "" (list 0 0) "" "")
    (command "_ddedit" (list 0 0) "")
    )
)
(setvar "CLAYER" lay)
(princ)
)

Если сохранить код в файле lay_offon.lsp, то макрос для кнопки или пункта меню может выглядеть так:

^C^C^P(if (not C:LAYOFFON) (load "lay_offon")) LAYOFFON

При первом запуске программа создаст непечатаемый слой "LAY_OFFON" и разместит
в начале координат атрибут, в который будут записываться слои.
Для изменения списка слоев надо сделать еще одну кнопку с таким макросом:

_.DDEDIT;0,0;;

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Владимир Громов

> VVA
Я второй день работаю с помощью программы, предложенной VVA и макросом  Владимир Громов. Нормально. Нигде не "жмет". Вроде удобно. На старых открываемых чертежах быстро формирую фильтр "AT". За два дня рука уже автоматом тянется к новой кнопке.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

;********************* lay_offon.lsp ************************************
; Программа выключения и включения слоев, задаваемых
; пользователем в виде списка для значения атрибута.
; В программе использована рекурсивная фукция (str-str-lst),
; разработанная Евгением Елпановым см.:
; https://www.caduser.ru/forum/topic25197.html
; Автор Владимир Громов.
; Для запуска программы можно использовать макрос:
;  ^C^C^P(if (not C:LAYOFFON) (load "lay_offon")) LAYOFFON
; Для удобного редактирования атрибута со списком слоев
; можно создать кнопку с макросом:
;  _.DDEDIT;0,0;;
;
(defun C:LAYOFFON ( / echo lay lay_list list_len n lay_n)
(setq echo (getvar "CMDECHO"))
(setvar "CMDECHO" 1)
(setq lay (getvar "CLAYER"))
(if (tblsearch "LAYER" "lay_offon")
    (progn
    (ssget "_X" (list (cons 8 "lay_offon")))
    (setq lay_list (cdr (assoc 1 (entget (entlast)))))
(str-str-lst lay_list ",")
    (setq list_len (length list_lay))
    (Cond
         ((= (getvar "USERI1") 0) (setq n 0)
         (repeat list_len
             (setq lay_n (nth n list_lay))
             (if (and (tblsearch "LAYER" lay_n) (/= (getvar "CLAYER") lay_n))
                 (command "_-layer" "_off" lay_n "")
             ) ; if
             (if (and (tblsearch "LAYER" lay_n) (= (getvar "CLAYER") lay_n))
                 (command "_-layer" "_off" lay_n "_y" "")
             ) ; if
             (if (= (tblsearch "LAYER" lay_n) nil)
                 (progn
                 (princ "\n Слой ") (princ lay_n)
                 (princ " отсутствует или неправильно записан!")
                 )
             ) ; if
             (setq n (1+ n))
         ) ; repeat
         (setvar "USERI1" 1)
         )
         ((= (getvar "USERI1") 1) (setq n 0)
         (repeat list_len
             (setq lay_n (nth n list_lay))
             (if (tblsearch "LAYER" lay_n)
                 (command "_-layer" "_on" lay_n "")
             ) ; if
             (if (= (tblsearch "LAYER" lay_n) nil)
                 (progn
                 (princ "\n Слой ") (princ lay_n)
                 (princ " отсутствует или неправильно записан!")
                 )
             ) ; if
             (setq n (1+ n))
         ) ; repeat
         (setvar "USERI1" 0)
         )
    ) ; cond
    ) ; progn
    (progn
    (princ "\n Для работы программы необходимо определить атрибут на слое LAY_OFFON.")
    (alert "   Для работы программы необходимо\nопределить атрибут на слое LAY_OFFON.")
    (command "_-LAYER" "_m" "LAY_OFFON" "_p" "_n" "LAY_OFFON" "")
    (command "_attdef" "" "LAY_OFFON" "Записать слои через запятую без пробелов" "" (list 0 0) ""
"")
    (command "_ddedit" (list 0 0) "")
    ) ; progn
) ; if
(setvar "CLAYER" lay)
(setvar "CMDECHO" echo)
(princ)
)
; Программа, пребразующая строку слоев в список слоев
(defun str-str-lst (str pat / i)
  (cond
  ((= str "") nil)
  ((setq i (vl-string-search pat str))
       (setq list_lay
           (cons
           (substr str 1 i)
           (str-str-lst (substr str (+ 2 i)) pat)
           ) ;_  cons
       ) ; setq
   )
   (t
       (list str))
  ) ;_  cond
)

Если сохранить код в файле lay_offon.lsp, то макрос для кнопки или пункта меню может выглядеть так:

^C^C^P(if (not C:LAYOFFON) (load "lay_offon")) LAYOFFON

При первом запуске программа создаст непечатаемый слой "LAY_OFFON" и разместит
в начале координат атрибут, в который будут записываться слои.
Для изменения списка слоев надо сделать еще одну кнопку с таким макросом:

_.DDEDIT;0,0;;

Re: Макрос на кнопку "Отключение слоя или группы слоев"

Лучше в начале кода установить "CMDECHO" в ноль.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Владимир Громов
Программа, конечно Super. Но, обьясните, пож-ста, почему такой подход к решению вопроса о OFF/ON слоях Вам больше нравится.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Screwy
А это Sailor поставил задачу - использовать одну кнопку для выключения/выключения слоев (в другой теме) - а я и зацепился.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Владимир Громов
Насчет Sailor понятно. Но, обьясните, пож-ста, почему Вы предложили другое решение вопроса о OFF/ON слоях? Можно было остановиться на программе предложенном VVA. Или Вы предложили свое решение как вариант. Я вот никак не могу уловить преимущества или недостатки обоих вариантов.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

> Screw
А, вот вы о чем. Да просто я захотел написать программу без ActiveX.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

Ну, и без фильтров слоев.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

Владимир Громов пишет:

...без ActiveX...

А, тогда, ясно. Я, правда, в этом слабо разбираюсь.

Re: Макрос на кнопку "Отключение слоя или группы слоев"

Как выяснилось, если в списке присутствует всего одно имя, то после него надо ставить запятую.