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

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Защита блока от редактирования с помощью реакторов

Защита блока от редактирования с помощью реакторов

Ответ
Поиск в этой теме
Непрочитано 29.01.2020, 16:17
Защита блока от редактирования с помощью реакторов
Tonic
 
Воронеж
Регистрация: 26.06.2007
Сообщений: 151

Добрый день!
Возможно ли защитить блоки (не все подряд, а только имеющие определённые расширенные данные) от попыток редактирования? Например, чтобы при событии vlr-subObjModified (изменён подпримитив объекта) или vlr-modified (объект изменён) срабатывала команда Undo.
То ли это реактор объектов (но тогда придётся всегда следить за актуальным списком объектов), то ли реактор событий изменения базы рисунка (что предпочтительнее). Может, есть готовые части программ (не нашёл, а LockObjects от Lee Mac работает не так, как нужно)?
Просмотров: 4635
 
Непрочитано 30.01.2020, 16:06
#21
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


skkkk,
1. Где фильтрация по расширенным данным?
2.
Цитата:
Сообщение от skkkk Посмотреть сообщение
Они же, как правило, не творят прямо-таки откровенную дичь, особенно, если им объяснить, что порушится алгоритм какой-то программы.
если на алгоритм работы какой то программы влияет внешний вид блоков - то тут уже не пользователей ограничивать надо, имхо..))
Сергей812 вне форума  
 
Непрочитано 30.01.2020, 16:20
#22
skkkk


 
Регистрация: 20.03.2008
Сообщений: 2,653


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
1. Где фильтрация по расширенным данным?
Ну так ведь у меня нет данных по этим данным расширенным. Потому я там оставил комментарий в коде:
Цитата:
Сообщение от skkkk Посмотреть сообщение
Код:
[Выделить все]
 (= TMP "AA") ;;; сюда добавить свое условие
----- добавлено через ~5 мин. -----
Код, разумеется, в качестве готовой, рабочей программы не годится. Кроме того, нужно еще учитывать возможность контекстного редактирования блока, обработка которой также не прописана в коде. Это просто черновик своего рода.
skkkk вне форума  
 
Непрочитано 30.01.2020, 16:32
#23
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


так ранее и писал
Цитата:
Сообщение от Сергей812 Посмотреть сообщение
Ну или отслеживать запуск команд редактирования блока через vlr-command-reactor
а потом понял - что это будет работать, если супер-сознательные пользователи, всегда выделяющие блок перед вызовом команды редактирования блока. Т.е. что-то из области фантастики)
Сергей812 вне форума  
 
Непрочитано 30.01.2020, 17:10
#24
skkkk


 
Регистрация: 20.03.2008
Сообщений: 2,653


Сколько знаю пользователей, все редактируют блоки по двойному клику на блок с последующим нажатием "ОК". Кто и зачем станет набирать команду в строку? Ну, допустим, кто-то хочет редактировать блок иначе, и знает про кнопку _BEDIT. Нужно в общем, подумать, как фильтровать, но это не самое важное в данном случае, на мой взгляд.

Тут я бы в первую очередь озадачился подходом в принципе. Исходных данных для полноценной думы маловато. Расширенные данные (РД) вносятся куда? Во вхождение блока или в его описание? По какому принципу программа должна понять, какой именно блок можно редактировать, а какой - нет? Очевидно, если РД добавлены в одни вхождения, а в другие - нет, то редактирование описания при двойном клике на вхождение без РД изменит и одноименные блоки с РД - и тогда вся затея накрывается медным тазом. Если же РД добавляются к описанию, так почему бы тогда не запретить редактирование просто перечня блоков по их именам? Допускаю, что во избежание вероятного их переименования, ОК. В любом случае, проверить при срабатывании реактора наличие РД у описания блока проблем не составит.

И повторюсь: в данном случае у меня лично большие сомнения вызывает необходимость использования реакторов. А код я выложил больше в качестве результатов своего баловства, причем, в качестве намёка о серьезности намерений там перед ним соответствующий смайлик разместил. Однако, в случае, если все же есть объективная причина использовать реакторы, то можно и попробовать - главный вопрос темы (запретить редактирование блока с помощью редакторов) решён. Пусть и не вполне красиво (в идеале-то было бы вообще не допустить редактирования), но и лучше, чем в исходной задаче: не через _UNDO, а через моментальное закрытие редактора блоков в случае, если редактирование данного блока "запрещено".
skkkk вне форума  
 
Автор темы   Непрочитано 30.01.2020, 17:47
#25
Tonic


 
Регистрация: 26.06.2007
Воронеж
Сообщений: 151


skkkk, в функцию действия не посылается объект (блок), для которого вызывается редактирование, поэтому в ней (в этой функции) не получится проверить нужное условие: есть ли у блока расширенные данные или нет.
Расширенные данные вносятся заранее (при вставке блоков) во вхождения блоков. Соответственно, если у редактируемого блока есть эти РД (допустим, (1000 . "UGO") приложения "myapp"), то нельзя давать изменять его в редакторе блоков. Одинаковых (на вид и имя) блоков, где бы у части из них не было РД, нет. Тема так называется, потому что первое, что пришло мне на ум при размышлении над задачей с таким условием (при этом не внося изменения ни в блоки, ни в словари) — это работа с реакторами.

Последний раз редактировалось Tonic, 30.01.2020 в 17:53.
Tonic вне форума  
 
Непрочитано 30.01.2020, 17:52
#26
skkkk


 
Регистрация: 20.03.2008
Сообщений: 2,653


Цитата:
Сообщение от Tonic Посмотреть сообщение
в функцию действия не посылается объект (блок)
А что же мешает его послать? Можете более детально изложить суть задачи? Ну и снять-таки возникшие в процессе обсуждения вопросы:
1. Допустимо ли отказаться от внедрения реакторов всем пользователям, вместо этого изменив всем операцию при двукратном нажатии на блок?
2. Куда вносятся расширенные данные? Во вхождение блока (то есть в конкретный его экземпляр) или в его описание?
3. Каков формат и состав этих РД?
Ну и файл бы приложить не мешало.

Последний раз редактировалось skkkk, 30.01.2020 в 17:58.
skkkk вне форума  
 
Автор темы   Непрочитано 30.01.2020, 18:49
#27
Tonic


 
Регистрация: 26.06.2007
Воронеж
Сообщений: 151


1. Допустимо. Только почему речь о двукратном нажатии? У меня при этом появляется окно "Редактор атрибутов блока", а речь о "Редакторе блоков" (вызывается из контекстного меню).
2. Расширенные данные вносятся во все вхождения блоков (эти блоки вставляются программно, поэтому с этим проблем нет).
3. У всех "наших" блоков есть группа 1000 со значением "UGO", имя приложения для РД у них тоже одинаковое.
Суть задачи: сделать так, чтобы при открытии чертежа с "нашими" блоками их нельзя было отредактировать (например, изменить текст внутри блока). При этом допускается, что заранее в acaddoc была прописана функция, которая бы помогала в этой защите.
Условие проверки я пишу такое:
Код:
[Выделить все]
 
(and
  (vla-GetXData (vlax-ename->vla-object obj) "myapp" 'XDataType 'XDataValue)
  XDataValue
  (setq xdata_value (vlax-safearray->list XDataValue))
  (= (setq xdata_value1 (nth 1 (mapcar 'vlax-variant-value xdata_value))) "UGO")
)
В случае с кодом выше непонятно, откуда взять имя объекта, изменение которого привели к вызову реактора. В функцию действия посылаются два аргумента, но среди них нет имени примитива.
Tonic вне форума  
 
Непрочитано 30.01.2020, 20:13
#28
kp+

идущий по граблям
 
Регистрация: 26.05.2005
Сообщений: 5,091


Цитата:
Сообщение от Tonic Посмотреть сообщение
откуда взять имя объекта, изменение которого привели к вызову реактора
Для режима контекстного редактирования блока (который все равно придется обрабатывать) есть системная переменная REFEDITNAME, которая как раз показывает имя редактируемого блока. Для редактора блоков подобной переменной нет .
Хотя имя редактируемого блока и показывается в окне редактора, но запрятано глубже, и может даже недоступно через системные переменные или ActiveX
kp+ вне форума  
 
Непрочитано 30.01.2020, 21:02
#29
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


Цитата:
Сообщение от kp+ Посмотреть сообщение
Хотя имя редактируемого блока и показывается в окне редактора, но запрятано глубже, и может даже недоступно через системные переменные или ActiveX
угу
Сергей812 вне форума  
 
Непрочитано 30.01.2020, 21:38
#30
skkkk


 
Регистрация: 20.03.2008
Сообщений: 2,653


Цитата:
Сообщение от Tonic Посмотреть сообщение
1. Допустимо. Только почему речь о двукратном нажатии? У меня при этом появляется окно "Редактор атрибутов блока", а речь о "Редакторе блоков" (вызывается из контекстного меню)
Совсем позабыл, что уже давным-давно переделал это стандартное поведение, и у меня только при двойном клике именно на атрибут выскакивает редактор атрибута (аналогичный редактору Мтекста), а по другим элементам блока - вообще другое меню. Вот тут я об этом писал: Редактирование атрибута дин. блока по двойному нажатию мышью.

Цитата:
Сообщение от Tonic Посмотреть сообщение
речь о "Редакторе блоков" (вызывается из контекстного меню)
Ну так и в это контекстное меню можно добавить свою функцию (команду).


Цитата:
Сообщение от Tonic Посмотреть сообщение
2. Расширенные данные вносятся во все вхождения блоков (эти блоки вставляются программно, поэтому с этим проблем нет).
То есть, всё-таки ко вхождению блока добавляются расширенные данные.

Ну, тогда в данном случае можно попробовать переопределить стандартные команды BEDIT и -BEDIT (пояснения в комментариях в коде):
Код:
[Выделить все]
 (defun C:-BEDIT () (C:BEDIT))
(defun C:BEDIT ( / ss obj)
	(or
		(setq ss (ssget "_I")) ;;;создаем набор объектов, подсвеченных ручками
		;;; на всякий случай обработаем вариант, если введена команда BEDIT, но блок не выбран
		(setq ss (ssget "_:S" '((0 . "INSERT"))))
	)
	 ;;; поскольку подразумевается, что пункт "Редактировать блок" в контекстном меню 
	 ;;; может присутствовать только, если выбран ОДИН блок, 
	 ;;; а также во втором случае мы задали единичный выбор ssget ("_:S"),
	 ;;; то единственный объект в этом наборе и будет наш искомый блок
	(setq obj (ssname ss 0))
	(sssetfirst nil ss)
	;;; создаем список условий
	(cond
	  (	(and
			(vla-GetXData (vlax-ename->vla-object obj) "myapp" 'XDataType 'XDataValue)
			XDataValue
			(setq xdata_value (vlax-safearray->list XDataValue))
			(= (setq xdata_value1 (nth 1 (mapcar 'vlax-variant-value xdata_value))) "UGO")
		) ;;; если есть РД,
		;;; то не даем редактировать блок
		(alert "Данный блок редактировать нельзя")
		;;; или просто об этом сообщаем в комстроку и всё.
		(princ "\nДанный блок редактировать нельзя")
		(princ)
	  )
	  ( T ;;; если предыдущие условия не выполнены
		(vl-cmdf "_.BEDIT") ;;; запускаем редактор
	  )
	)
)
Уже не помню, но кажется, там, в контекстном меню блока с атрибутами (в _CUI) в поле "Макрос" было что-то мудрёное, не знаю, сработает ли сразу, если нет, то вбиваем туда просто (без ^C^C):

Только надо не забыть перезагрузить Автокад, чтоб переопределение BEDIT, произошедшее после загрузки предыдущего лиспа, отменилось

Код:
[Выделить все]
 (vl-load-com)
;;; Создаем реактор
(setq Cmnd_Reac 
	(vlr-command-reactor "Реактор комманд"
		(list '(:VLR-commandWillStart . commandWillStart))
	)
)

;;; функция действия
(defun commandWillStart(reac data / ) 
	(setq ss (ssget "_I"))
	(setq obj (ssname ss 0))
	(setq CMD (car data))
	(cond 
	  (	(and 
			(member	CMD (list "_BEDIT" "BEDIT" "-BEDIT")) 
			(vla-GetXData (vlax-ename->vla-object obj) "myapp" 'XDataType 'XDataValue)
			XDataValue
			(setq xdata_value (vlax-safearray->list XDataValue))
			(= (setq xdata_value1 (nth 1 (mapcar 'vlax-variant-value xdata_value))) "UGO")

		)
		(alert "Tonic запрещает редактировать блоки!")
		(vla-SendCommand (vla-get-ActiveDocument (vlax-get-acad-object)) "(vl-cmdf \"_BCLOSE\") ")
	  )
    )
)	


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

Цитата:
Сообщение от kp+ Посмотреть сообщение
Хотя имя редактируемого блока и показывается в окне редактора, но запрятано глубже, и может даже недоступно через системные переменные или ActiveX
kp+, имя редактируемого блока нам, в общем-то и не нужно, потому что РД добавляются ко вхождению, а не к описанию (судя по тому, как Tonic их считывает).
skkkk вне форума  
 
Автор темы   Непрочитано 31.01.2020, 01:37
#31
Tonic


 
Регистрация: 26.06.2007
Воронеж
Сообщений: 151


skkkk, спасибо, это хороший и простой способ — переопределение команды. Минус в том, что нужно будет отредактировать имя команды для макроса контекстного меню. При этом если программу "защиты блоков" (для переопределения команды) не вызывать, команда в макросе так и останется "bedit", что будет означать появление лишнего окна (вместо _-bedit, как там написано изначально).
Ну или зашить в начало кода функции переопределения C:BEDIT изменение макроса контекстного меню (наверняка такая функция в autolisp/ActiveX есть), а в конце работы функции C:BEDIT снова восстанавливать значение в "^C^C_-bedit".
Tonic вне форума  
 
Непрочитано 31.01.2020, 02:19
#32
skkkk


 
Регистрация: 20.03.2008
Сообщений: 2,653


Что-то не очень я понял, о чем речь и в чем минус. Что плохого в том, чтоб изменить один раз вручную макрос для контекстного меню, если понадобится?

Я проверял на 2011-м и 2015-м - все работало без лишнего окна. В новых версиях, возможно, по-другому себя ведет, не знаю. Не помню уже, менял ли я там что-то в макросах, контекстными меню объектов мы не пользуемся, но у меня там стоит (в конце - пробел):
Код:
Может, поможет, если в строке 29 (в коде из #30) добавить черточку в имя команды? (_-.BEDIT) Точка означает, что команда будет вызываться именно не переопределенная.

Как в лиспе изменять макрос контекстного меню, я не в курсе - никогда не было такой нужды. Создал в свое время, давно все макросы, (уже лет 10 они сами макросы у нас не меняются - только коды исполняемых ими лиспов), а потом на новые машины (или новые системы после ремонта) делал всегда импорт адаптаций. И зачем макрос менять обратно потом?

В самом лиспе переопределены обе команды: и BEDIT, и -BEDIT, - и обе они выполняют одну и ту же функцию, поэтому неважно, что из этого прописано в макросе на контекстном меню. Главное, чтобы в макросе точки не было, чтоб переопределенная команда вызывалась макросом.
Чтобы этот код работал всегда, можно добавить в acaddoc.lsp строку загрузки лисп-файла из #30. Если файл обозвать "BEDIT.lsp" (предварительно положив его в папку, прописанную в путях доступа), то строка будет такой:
Код:
[Выделить все]
(load "BEDIT.lsp")
Либо в макрос контекстного меню блока прописать строку
Код:
[Выделить все]
(load "BEDIT.lsp");BEDIT
А можно просто весь код целиком вставить в acaddoc.
Во всех случаях переопределение будет активно при любом запуске Автокада и обычные блоки даст редактировать, а РД-шные - не даст.

Последний раз редактировалось skkkk, 31.01.2020 в 02:24.
skkkk вне форума  
 
Автор темы   Непрочитано 31.01.2020, 19:17
#33
Tonic


 
Регистрация: 26.06.2007
Воронеж
Сообщений: 151


Про "минус" я имел в виду следующее: если пользователь решит вдруг удалить лишний код из acaddoc.lsp (или сам файл — ну мало ли), или код вообще будет подгружаться не из acaddoc, а автоматически из "Загруженных приложений" в папке "Доверенные местоположения" (и пользователь удалит эти пути), тогда программа для переопределения вызываться не будет, но команда макроса при этом останется вручную изменённой — "bedit" вместо "^C^C_-bedit" (по умолчанию), а в этом случае редактор блоков вызывается не так, как нужно (вызывается окно "Редактирование переопределения блоков" вместо редактора блоков).
Tonic вне форума  
 
Непрочитано 31.01.2020, 19:40
#34
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


А зачем обычному пользователю вообще куда лезть править код, настройки путей к доверенным приложениям и т.п.?
Сергей812 вне форума  
 
Непрочитано 31.01.2020, 19:53
#35
kp+

идущий по граблям
 
Регистрация: 26.05.2005
Сообщений: 5,091


Цитата:
Сообщение от Tonic Посмотреть сообщение
если пользователь решит вдруг удалить лишний код из acaddoc.lsp
Вроде об этом уже писали выше - если пользователь умеет осознанно редактировать acaddoc.lsp, то с большой вероятностью самодельные защиты против него бессильны. Не разберется с ними сам - спросит на форуме Будет смешнее всего, если в этой самой теме
Только организационные меры, только хардкор.

Offtop: Вы, кстати, так и не обозначили конечную цель и "целевую аудиторию" Вашей защиты блоков от редактирования. Что в тех блоках такого ценного, требующего защиты? И неужели среди сотрудников Вашей организации есть такие идиоты, которым нельзя просто сказать - "блоки такие-то редактировать не следует"?
kp+ вне форума  
 
Непрочитано 31.01.2020, 20:50
#36
skkkk


 
Регистрация: 20.03.2008
Сообщений: 2,653


Цитата:
Сообщение от Tonic Посмотреть сообщение
Про "минус" я имел в виду следующее: если пользователь решит вдруг удалить лишний код из acaddoc.lsp
Цитата:
Сообщение от Tonic Посмотреть сообщение
команда макроса при этом останется вручную изменённой — "bedit" вместо "^C^C_-bedit" (по умолчанию)
Если обеспечить автозагрузку кода любым способом, то макрос можно не менять. Макрос все равно запустит код переопределенной лиспом команды, и насколько мне удалось проверить в АС2011 и 2015, - корректно будет отрабатывать, понимая, с каким блоком предстоит работа. Про другие версии ничего сказать не могу.
skkkk вне форума  
 
Автор темы   Непрочитано 01.02.2020, 01:44
#37
Tonic


 
Регистрация: 26.06.2007
Воронеж
Сообщений: 151


skkkk, без изменения макроса не получается: при выборе редактирования блока из контекстного меню вызывается команда "_-bedit", захода в тело функции переопределения не происходит. Пробовал также "на всякий случай" прописывать (помимо кода, представленного в сообщении 30)
Код:
[Выделить все]
 (defun C:_-bedit () (C:BEDIT))
(defun C:_bedit () (C:BEDIT))
Не помогло. И только если изменить макрос с "^C^C_-bedit " на "BEDIT" всё работает, как задумано.
kp+, да ничего особо ценного там нет, просто определённые блоки учитываются при расчёте спецификации, и поступила задача, чтобы раз люди пользуются автоматизацией, не переделывали блоки под свои нужды. В общем, всё это не слишком продумано, учитывая тысячу путей для обхода этих ограничений.
Tonic вне форума  
 
Непрочитано 01.02.2020, 02:10
#38
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


Цитата:
Сообщение от Tonic Посмотреть сообщение
просто определённые блоки учитываются при расчёте спецификации, и поступила задача, чтобы раз люди пользуются автоматизацией, не переделывали блоки под свои нужды. В общем, всё это не слишком продумано, учитывая тысячу путей для обхода этих ограничений.
так почему просто данные для расчета спецификации не прописать в XData? И пускай правят блоки, а если снесут и XData - то и защита от редактирования работать не будет.
Сергей812 вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Защита блока от редактирования с помощью реакторов

Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Лисп для редактирования объектов блока. Можно ли без захода в редактор? RrRR LISP 5 06.08.2018 19:08
Вставка блока. Окно редактирования атрибута. JKF AutoCAD 4 13.03.2018 13:14
Имеется ли возможность ссылаться изнутри при создании блока на его же будущий номер ObjId ? Tyhig AutoCAD 6 14.08.2017 17:56
Вставка блока с помощью иконки RomanS Программирование 50 02.04.2010 11:33
Перевод имени блока в имя переменной и обратно Supermax Программирование 11 14.12.2009 23:26