Пример LISP программы управления диалоговым окном в Автокад

В этой статье мы рассмотрим пример программного управление диалоговым окном.

В качестве примера мы возьмем диалоговое окно, созданное в предыдущей статье: «Диалоговое окно Автокад»

Диалоговое окно Автокад

Рис. 1.  Диалоговое окно.

В этой статье мы рассмотрим:

Напишем несколько пользовательских функций, которые будут ответом на действия пользователя:

И так приступим.

Откройте Автокад.

Запустите редактор Visual LISP (наберите в командной строке VLIDE и нажмите <Enter>).

Нажмите на кнопку «Новый файл».

Откроется новый файл для набора нашей программы.

Процесс управления диалоговым окном из LISP программы происходит в несколько этапов:

Этапы управления диалоговым окном.

Загрузка диалогового окна.

Сначала нужно загрузить файл диалогового окна (DCL файл)

(load_dialog "d:/MyLisp/Vozduh.dcl")
load_dialog – функция загрузки файла DCL;
"d:/MyLisp/Vozduh.dcl" –  полный путь к файлу DCL.

Функция load_dialog возвращает целое число:

положительное – номер загруженного файла (присваивается при загрузке);
отрицательное – если загрузка не произошла.

Запоминаем номер загруженного DCL файла в переменной dcl_id

(setq dcl_id (load_dialog «d:/MyLisp/Vozduh.dcl»))

Открытия диалогового окна и Проверка существования диалога.

При помощи функции new_dialog, выводим диалоговое окно на экран

(new_dialog "pr_uch" dcl_id)
"pr_uch" -  имя диалога;
dcl_id - номер загруженного DCL-файла,

Функция new_dialog возвращает:

T - если диалоговое окно открылось;
nul - если произошла ошибка открытия.

Добавим проверку существования диалога.

(if (not (new_dialog "pr_uch" dcl_id))(exit))

Если диалога «pr_uch» в файле DCL нет, прерываем выполнение программ при помощи функции (exit)

Действия пользователя.

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

Здесь мы должны запрограммировать реакцию программы на эти действия. Более подробно об этом ниже.

Закрытие диалогового окна.

Закрытие диалогового окна происходит при нажатии кнопки ОК или кнопки Отмена.

Но перед тем, как закрыть диалоговое окно, Мы проверяем, на какую кнопку нажал пользователь:

Если пользователь нажал на кнопку ОК (код кнопки «accept»), закрываем диалоговое окно при помощи функции done_dialog с числом 1

(action_tile "accept" "(done_dialog 1)")

Если пользователь нажал на кнопку Отмена (код кнопки » cancel «), закрываем диалоговое окно при помощи функции done_dialog с числом 0

(action_tile "cancel" "(done_dialog 0)")

При помощи функции start_dialog, читаем, с каким числом был закрыт диалог (на какую кнопку нажал пользователь). Сохраняем это число в переменной ddi

(setq ddi (start_dialog))

Выгрузка диалогового окна.

После того, как окно закрыто, выгружаем файл диалогового окна (DCL файл).

(unload_dialog dcl_id)

Добавим вышесказанное в программу. См. Рис. 1.

Управление диалоговым окном.

Рис. 1. Основные этапы управления диалоговым окном.

Нажмите на кнопку «Загрузить активное окно редактора». В рабочем окне Автокад появится диалоговое окно. См. Рис. 2.

Диалоговое окно Автокад

Рис. 2.   Диалоговое окно.

Далее программа будет ждать действий пользователя.

Что же, может сделать пользователь?

Пользователь может:

  • Поменять форму сечения;
  • Ввести новый расход воздуха м3/ч;
  • Выбрать сечение воздуховода;
  • Нажать на кнопку ОК или Отмена.

Нажмите кнопку ОК или Отмена, чтобы закрыть диалоговое окно и вернуться в редактор Visual LISP.

Давайте для каждого действия  пользователя напишем  пользовательскую функцию.

Начнем с функции изменения формы сечения.

Пользовательская функция изменения формы сечения.

Давайте при помощи функции defun, создадим пользовательскую функцию iz_sech:

(defun iz_sech ()
    <текст пользовательской функции>
)

Далее создадим список сечений воздуховода, которым будет заполняться раскрывающийся список «Сечение  мм:» (код «pop1»):

Если выбрано круглое сечение:

(setq plist_K (list "100" "125" "160" "200" "250" "315" "400" "450" "500"
"600" "710" "800" "900" "1000" "1125" "1250" "1400" "1500"))

Сохраняем список в переменной plist_K.

Если выбрано прямоугольное сечение:

(setq plist_P (list "100x100" "150x100" "150x150" "200x100" "200x150" "200x200"
"250x100" "250x150" "250x200" "250x250" "300x100" "300x150"))

Сохраняем список в переменной plist_Р.

Заполнение раскрывающегося списка происходит в три строчки:

Начанаем операцию редактирования:

(start_list "pop1")

«pop1» – код раскрывающегося списка

Редактирование списка:

(mapcar 'add_list plist_K)

Функция mapcar считываем значения элементов списка plist_K и при помощи функции add_list, добавляет их в раскрывающийся список.

Завершаем операцию редактирования

(end_list)

В основную программу добавляем вызов нашей пользовательской функции:

(iz_sech)

Добавляем все, вышесказанное, в программу. См. Рис. 3.

Управление диалоговым окном.

Рис. 3.  Заполнение раскрывающегося списка

Нажмите на кнопку «Загрузить активное окно редактора». В рабочем окне Автокад появится диалоговое окно. Щелкните по стрелке раскрывающегося списка. Мы видим, что список заполнен. См. Рис. 4.

Управление диалоговым окном.

Рис. 4. Диалоговое окно.

Нажмите кнопку ОК, чтобы закрыть диалоговое окно и вернуться в редактор Visual LISP.

Пользователь может выбрать и прямоугольную форму сечения воздуховода.

Как определить, что выбрал пользователь?

Считываем значение радиокнопки «Круглый» (код «rb_K»)

(get_tile "rb_K")
Если возвращаемое значение будет равно "1" – то выбрано круглое сечение
Если "0" – то выбрано прямоугольное сечение

Добавим условие проверки возвращаемого значения, и в зависимости от этого заполняем раскрывающийся список круглыми или прямоугольными сечениями

Поскольку при определенном условии нужно выполнить несколько выражений добавляем функцию prong.

Условие:

(if (eq (get_tile "rb_K") "1")

Выражения, которые выполнятся, если (get_tile «rb_K») равно «1»:

(progn
  (start_list "pop1")
  (mapcar 'add_list plist_K)
  (end_list)
); end prong

Иначе, если (get_tile «rb_K») неравно «1», будет выполнена группа выражений:

(progn
  (start_list "pop1")
  (mapcar 'add_list plist_P)
  (end_list)
); end prong

Окончание условия:

); end if

Строка в основной программе:

(iz_sech)

будет выполнена после загрузки диалогового окна.

Чтобы пользовательская функция iz_sech выполнялась при выборе радиокнопки, в основную программу добавляем следующие строки:

При выборе круглого сечения (код радиокнопки «rb_K»):

(action_tile "rb_K" "(iz_sech)")

При выборе прямоугольного сечения (код радиокнопки «rb_Р»):

(action_tile "rb_Р" "(iz_sech)")

В результате получим, следующее. См. Рис. 5.

Управление диалоговым окном.

Рис. 5. Пользовательская функция изменения формы сечения

Нажмите на кнопку «Загрузить активное окно редактора». В рабочем окне Автокад появится диалоговое окно. Пощелкайте по переключателям формы сечения. Мы видим, что раскрывающийся список меняет свои значения. См. Рис. 6.

Управление диалоговым окном.

Рис. 6. Диалоговое окно.

Нажмите кнопку ОК, чтобы закрыть диалоговое окно и вернуться в редактор Visual LISP.

Пользовательская функция расчета скорости.

Теперь давайте, создадим функцию, которая будет считать скорость движения воздуха в воздуховоде.

При помощи функции defun, создадим пользовательскую функцию ras_v:

(defun ras_v ()
  <текст пользовательской функции>
)

Формула, по которой считается скорость движения воздуха:

Скорость м/с = Расход воздуха м3/ч / Площадь сечения воздуховода м2 / 3600

Определяем значение поля «Расход м3/ч»

Вначале давайте считаем из диалогового окна значение поля «Расход м3/ч» (код поля  «eb_L»):

(get_tile "eb_L")

Возвращает строку:

“150”

Чтобы, преобразовать строку  “150” в число 150, используем функцию atoi:

(atoi (get_tile "eb_L"))

Результат сохраняем в переменной L:

(setq L (atoi (get_tile "eb_L")))

Определяем текущее значение раскрывающегося списка «Сечение мм» (когда выбрано круглое сечение).

Затем, определим текущее значение раскрывающегося списка «Сечение мм» (код “рор1”):

(get_tile "pop1")

Возвращает строковое значение номера элемента: “0”

(“0” – выбран первый элемент списка;
“1” – выбран второй элемент списка; и так далее)

Преобразуем строковое значение в число:

(atoi (get_tile "pop1"))

Возвращает число 0.

При помощи функции nth считываем значение элемента списка по его порядковому номеру

(nth (atoi (get_tile "pop1")) plist_K)

Возвращает строковое значение элемента “100”.

Преобразуем строковое значение в число:

(atoi (nth (atoi (get_tile "pop1")) plist_K))

Возвращает число — 100 (диаметр круглого воздуховода мм).

Результат сохраняем в переменной Raz:

(setq Raz (atoi (nth (atoi (get_tile "pop1")) plist)))

Определяем скорость для круглого сечения.

Площадь  поперечного сечения круглого воздуховода равна квадрату диаметра умноженному на Пи и деленное на 4.

S = d*d*π/4

Подставляем это в формулу для расчета скорости, делаем преобразования и получаем, что скорость равна:

(/ (* 40000 L) 36 (* Raz Raz pi))

Возвращает: числовое значение скорости.

Чтобы показать это значение в поле «Скорость м/с», нужно сначала при помощи функции rtos  преобразовать его в строковое значение:

(rtos (/ (* 40000 L) 36 (* Raz Raz pi)))

А затем поставить его в поле «Скорость м/с» (код поля «eb_V»)

(set_tile "eb_V" (rtos (/ (* 40000 L) 36 (* Raz Raz pi))))
set_tile – функция которая меняет содержимое поля;
"eb_V" – код поля;
(rtos (/ (* 40000 L) 36 (* Raz Raz pi))) – новое значение поля.

Чтобы, скорость считалась сразу после загрузки диалогового окна, добавляем в основную программу вызов пользовательской функции расчета скорости:

(ras_v)

Чтобы пользовательская функция (ras_v) выполнялась при изменении текущего значения раскрывающегося списка (код списка “pop1”), добавляем строку:

(action_tile «pop1» «(ras_v)»)

Теперь наша программа выглядит так. См. Рис. 7.

Управление диалоговым окном.

Рис. 7.  Расчет скорости при выборе круглого сечения.

Нажмите на кнопку «Загрузить активное окно редактора». В рабочем окне Автокад появится диалоговое окно. Скорость движения воздуха сосчитана с данными по умолчанию. Измените значения в раскрывающимся списке «Сечения мм».  Мы видим, что значение скорости меняется. См. Рис. 8.

Управление диалоговым окном.

Рис. 8.  Диалоговое окно.

Нажмите кнопку ОК, чтобы закрыть диалоговое окно и вернуться в редактор Visual LISP.

Определяем текущее значение раскрывающегося списка «Сечение мм» (когда выбрано прямоугольное сечение)

Определяем текущее значение раскрывающегося списка «Сечение мм» (код “рор1”):

(get_tile "pop1")

Возвращает строковое значение номера элемента: “0”

(“0” – выбран первый элемент списка;
“1” – выбран второй элемент списка; и так далее)

Преобразуем строковое значение в число:

(atoi (get_tile "pop1"))

Возвращает число 0.

При помощи функции nth считываем значение элемента списка по его порядковому номеру

(nth (atoi (get_tile "pop1")) plist_P)))

Возвращает строковое значение элемента “100×100”.

Сохраняем значение элемента списка в переменной RazP:

(setq RazP (nth (atoi (get_tile "pop1")) plist_P))

При помощи функции vl-string-search, определяем местоположение символа «х»:

(vl-string-search "x" RazP)

Возвращает число 3 (отсчет начинается с 0).

Сохраняем местоположение символа «х» в переменной n:

(setq n (vl-string-search "x" RazP))

При помощи функции substr извлекаем из текстовой строки ширину воздуховода:

(substr RazP 1 n)
RazP – строковое значение, из которой происходит извлечение;
1 – номер местоположения начального символа (отсчет начинается с 1);
n – номер местоположения конечного символа

Возвращает строковое значение : “100”

Преобразуем строковое значение в число и сохраняем его в переменной Raz:

(setq Raz (atoi(substr RazP 1 n)))

Возвращает число — 100 (ширина прямоугольного воздуховода мм).

Затем, извлекаем из текстовой строки высоту воздуховода:

(substr RazP (+ n 2))
RazP – строковое значение, из которой происходит извлечение;
(+ n 2) – номер местоположения начального символа (отсчет начинается с 1);

Если  номер местоположения конечного символа не указан, функция substr возвращает остаток RazP, начиная с местоположения (+ n 2).

Возвращает строковое значение : “100”

Преобразуем строковое значение в число и сохраняем его в переменной Н:

(setq H (atoi (substr RazP (+ n 2))))

Определяем скорость для прямоугольного сечения.

Площадь  поперечного сечения прямоугольного воздуховода равна произведению ширины на высоту:

S= Raz*Н

Подставляем это в формулу для расчета скорости, делаем преобразования и получаем, что скорость равна:

(/ (* 10000 L) 36.0 (* Raz H))

Возвращает: числовое значение скорости.

Чтобы показать это значение в поле «Скорость м/с», нужно сначала при помощи функции rtos  преобразовать его в строковое значение:

(rtos (/ (* 10000 L) 36.0 (* Raz H)))

А затем поставить его в поле «Скорость м/с» (код поля «eb_V»)

(set_tile "eb_V" (rtos (/ (* 10000 L) 36.0 (* Raz H))))
set_tile – функция которая меняет содержимое поля;
"eb_V" – код поля;
(rtos (/ (* 10000 L) 36.0 (* Raz H))) – новое значение поля.

Каким способом рассчитывать скорость зависит от того, в каком положение находиться переключатель формы сечения (Круглый или Прямоугольный)

Добавляем условие:

(if (eq (get_tile "rb_K") "1")

Выражения, которые выполнятся, если (get_tile «rb_K») равно «1»:

(progn
  <Расчет скорости для круглого сечения>
); end prong

Иначе, если (get_tile «rb_K») неравно «1», будет выполнена группа выражений:

(progn
  <Расчет скорости для прямоугольного сечения>
); end prong

Окончание условия:

); end if

Чтобы, скорость считалась при изменении формы сечения, в основной программе добавим пользовательскую функцию (ras_v) в строки:

(action_tile "rb_K" "(iz_sech)")
(action_tile "rb_P" "(iz_sech)")

И получим:

(action_tile "rb_K" "(iz_sech) (ras_v)")
(action_tile "rb_P" "(iz_sech) (ras_v)")

Чтобы, скорость считалась при изменении расхода (код поля «eb_L»), добавим строку:

(action_tile "eb_L" "(ras_v)")

(скорость рассчитывается только при выходе из поля «eb_L»)

Добавим все выше сказанное в программу. См. Рис. 9.

Управление диалоговым окном.

Рис. 9.  Пользовательская функция расчета скорости.

Нажмите на кнопку «Загрузить активное окно редактора». В рабочем окне Автокад появится диалоговое окно. Поменяйте форму сечения. Сечение измениться. Скорость будет пересчитана. См. Рис. 10.

Управление диалоговым окном.

Рис. 10. Диалоговое окно.

Поменяете значение в поле «Расход м3/ч:». Перейдите в поле «Скорость м/с:», Скорость будет пересчитана. См. Рис. 11.

Управление диалоговым окном.

Рис. 11. Диалоговое окно.

Нажмите кнопку ОК, чтобы закрыть диалоговое окно и вернуться в редактор Visual LISP.

Пользовательская функция для кнопки ОК.

Сейчас после нажатия кнопки ОК у нас закрывается диалоговое окно, переменной ddi присваивается значение 1 и больше ничего не происходит.

Давайте напишем пользовательскую функцию которая будет рисовать воздуховод согласно значению в раскрывающемся списке «Сечение мм». Для этого мы возьмем код программы рассмотренной в статье: «Мультилиния в Автокаде».

См. Рис.12.

Управление диалоговым окном.

Рис. 12.  Создание стиля мультилинии. Вставка мультилинии.

Пользовательскую функцию создания стиля мультилинии SMLK  оставим без изменения. А программу команды вставки мультилинии, переделаем в пользовательскую функцию. Для этого:

  • Уберем «с:»;
  • Перенесем Di из временных рабочих переменных в аргументы функции;
  • Удаляем строку: (setq Di (getreal «\nВведите размер воздуховода :»))

См. Рис. 13.

Управление диалоговым окном.

Рис. 13.  Делаем из команды Vml пользовательскую функцию.

Для того чтобы, вызвать пользовательскую функцию вставки мультилинии, используем следующее выражение:

(Vml <ширина мультилинии>)

Чтобы, после нажатия на кнопку ОК, нарисовать мультилинию, в основную программу добавляем строку:

(if (= ddi 1) (Vml Raz))

Если переменная ddi равна 1, то будет выполнена функция Vml, где в качестве ширины мультилинии я подставил значение переменной Raz.

Напомню, что переменная ddi показывает нам, какую кнопку нажал пользователь (ОК или Отмена):

Если ddi=1 – нажата кнопка ОК;
Если ddi=0 – нажата кнопка Отмена.

Добавляем выше сказанное в программу. См. Рис. 14.

Управление диалоговым окном.

Рис. 14. Пользовательская функция вставки мультилинии.

Нажмите на кнопку «Загрузить активное окно редактора». В рабочем окне Автокад появится диалоговое окно. Можете поменять любые исходные данные. Затем нажмите на кнопку ОК.

В командной строке появится запрос: «Укажите первую точку :»

Укажите любую точку в рабочем окне Автокад.

На запрос: «Укажите вторую точку :» – Укажите вторую точку.

Программа построит мультилинию шириной указанной в раскрывающемся списке.

См. Рис. 15.

Управление диалоговым окном.

Рис. 15. Мультилиния (воздуховод круглого сечения).

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

Сделайте копию пользовательской функции SMLK и внесите следующие изменения:

  • Имя функции меняем на SMLP (вместо SMLK)
  • VENK везде меняем на VENP
  • Цвет центральной линии (62 . 6) меняем на (62 . 3)

См. Рис. 16.

Управление диалоговым окном.

Рис. 16. Добавляем новый стиль мультилинии.

Чтобы после закрытия диалогового окна знать, какая форма сечения была выбрана пользователем, добавим перемену kodS в функцию iz_sech.

Если выбрано круглое сечение, присвоим переменной значение «vozK»:

(setq kodS "vozK")

Если прямоугольное, присвоим переменной значение «vozР»:

(setq kodS "vozР")

См. Рис. 17.

Управление диалоговым окном.

Рис. 17. Добавляем переменную kodS.

В пользовательскую функцию вставки мультилинии Vml, добавим функцию создания стиля мультилинии для прямоугольного воздуховода:

(SMLP)

И вместо строки:

(setvar "CMLSTYLE" "VenK")

Которая делает текущим стиль мультилинии «VenK».

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

(if (eq kodS "vozK") (setvar "CMLSTYLE" "VenK"))
(if (eq kodS "vozP") (setvar "CMLSTYLE" "VenP"))

См. Рис. 18.

Управление диалоговым окном.

Рис. 18. Стиль, в зависимости от значения переменной.

Нажмите на кнопку «Загрузить активное окно редактора». В рабочем окне Автокад появится диалоговое окно. Выберите прямоугольное сечение и нажмите на кнопку ОК. На запросы в командной строке укажите две точки. Программа нарисует мультилинию в другом стиле. См. Рис. 19.

Управление диалоговым окном.

Рис. 19. Мультилиния (прямоугольный воздуховод).

В AutoLISP по умолчанию все создаваемые переменные глобальные, т. е. они будут храниться в памяти программы AutoCAD, после завершения команды (пока Вы не закроете Автокад).

Чтобы сделать их локальными, их добавляют в описание функции defun. И тогда после завершения команды, они не болтаются в памяти AutoCAD.

Поэтому теперь, когда программа отлажена, давайте во всех функциях defun, перечислим временные рабочие переменные.

В функцию изменения сечения временные переменные не добавляем.

(defun iz_sech (/)
  <текст пользовательской функции>
)

См. Рис. 20.

Управление диалоговым окном.

Рис. 20. Функция изменения сечения.

Переменные plist_К, plist_P, kodS используются за пределами этой функции.

В функцию расчета скорости добавляем переменные L RazP n H:

(defun ras_v (/ L RazP n H)
  <текст пользовательской функции>
)

См. Рис. 21.

Управление диалоговым окном.

Рис. 21. Функция расчета скорости.

Переменная Raz используются за пределами этой функции.

В функцию вставки мультилинии, добавляем переменные p1 p2 Cml.

См. Рис. 22.

Управление диалоговым окном.

Рис. 22. Функция вставки мультилинии.

Основную программу, при помощи функции defun, преобразуем в команду Автокад:

В начале программы добавим строку, в которой придумаем имя новой команды pr_uch и перечислим все временные переменные dcl_id ddi. Сюда же добавляем все переменные, которые были созданы в пользовательских функциях, и использовались после их завершения Raz plist_K plist_P kodS:

(defun c: pr_uch (/dcl_id ddi Raz plist_K plist_P kodS)
  <наша программа>
); end_defun

В конце программы добавим закрывающую скобку.

См. Рис. 23.

Рис. 23. Основная программа.

Рис. 23. Основная программа.

Давайте сохраним программу под именем pr_uch.lsp.

Теперь, чтобы запустить нашу программу:

Нажимаем на кнопку: «Загрузить активное окно редактора«;

Переходим в Автокад;

В командной строке вводим pr_ush и нажимаем <Enter>.

Окончательный вариант программы. См. Рис. 24.

Управление диалоговым окном.

Рис. 24. Окончательный вариант программы.

Программный код:

;---------------------- Функция изменения сечения ------------------------------
(defun iz_sech (/)
  (setq plist_K (list "100" "125" "160" "200" "250" "315" "400" "450" "500"
  "600" "710" "800" "900" "1000" "1125" "1250" "1400" "1500"))
  (setq plist_P (list "100x100" "150x100" "150x150" "200x100" "200x150" "200x200"
  "250x100" "250x150" "250x200" "250x250" "300x100" "300x150"))
 
  (if (eq (get_tile "rb_K") "1")
    (progn
      (start_list "pop1")
        (mapcar 'add_list plist_K);заполнение значениями из списка
      (end_list)
      (setq kodS "vozK")
    ); end progn
    (progn
      (start_list "pop1")
        (mapcar 'add_list plist_P);заполнение значениями из списка
      (end_list)
      (setq kodS "vozP")
    ); end progn
  ); end if
); end defun
;---------------------- Функция расчета скорости ---------------------------------
(defun ras_v (/ L RazP n H)
  (setq L (atoi (get_tile "eb_L")));Считываем и запоминаем расход
  (if (eq (get_tile "rb_K") "1")
    (progn
      (setq Raz (atoi (nth (atoi (get_tile "pop1")) plist_K)))
      (set_tile "eb_V" (rtos (/ (* 40000 L) 36 (* Raz Raz pi))))
    ); end progn
    (progn
      (setq RazP (nth (atoi (get_tile "pop1")) plist_P))
      (setq n (vl-string-search "x" RazP))
      (setq Raz (atoi (substr RazP 1 n))) 
      (setq H (atoi(substr RazP (+ n 2))))
      (set_tile "eb_V" (rtos (/ (* 10000 L) 36.0 (* Raz H))))
    ); end progn
  ); end if
); end defun
;----------- Функция создания стиля мильтилинии для круглого сечения -------------
(defun SMLK (/ mlDict mlList)
  (if (= nil (member (cons 3 "VENK")(dictsearch (namedobjdict) "ACAD_MLINESTYLE"))) 
  (progn
    (setq mlDict (cdr(assoc -1(dictsearch (namedobjdict) "ACAD_MLINESTYLE"))))
    (setq mlList '((0 . "MLINESTYLE")(102 . "{ACAD_REACTORS")(102 . "}")
       (100 . "AcDbMlineStyle")
       (2 . "VenK")
       (70 . 272)
       (3 . "Воздуховод") 
       (51 . 1.5708)
       (52 . 1.5708)
       (71 . 3)
       (49 . 0.5)
       (62 . 256) 
       (6 . "BYLAYER")
       (49 . 0.0)
       (62 . 6)
       (6 . "ОСЕВАЯ")
       (49 . -0.5)
       (62 . 256)
       (6 . "BYLAYER"))
    ); end setq
    (dictadd mlDict "VenK" (entmakex mlList))
   ); end progn
 ); end if
); end defun
;------ Функция создания стиля мильтилинии для прямоугольного сечения ------------
(defun SMLP (/ mlDict mlList)
  (if (= nil (member (cons 3 "VENP")(dictsearch (namedobjdict) "ACAD_MLINESTYLE"))) 
    (progn
      (setq mlDict (cdr(assoc -1(dictsearch (namedobjdict) "ACAD_MLINESTYLE"))))
      (setq mlList '((0 . "MLINESTYLE")(102 . "{ACAD_REACTORS")(102 . "}")
         (100 . "AcDbMlineStyle")
         (2 . "VenK")
         (70 . 272)
         (3 . "Воздуховод") 
         (51 . 1.5708)
         (52 . 1.5708)
         (71 . 3)
         (49 . 0.5)
         (62 . 256) 
         (6 . "BYLAYER")
         (49 . 0.0)
         (62 . 3)
         (6 . "ОСЕВАЯ")
         (49 . -0.5)
         (62 . 256)
         (6 . "BYLAYER"))
      ); end setq
      (dictadd mlDict "VenP" (entmakex mlList))
    ); end progn
  ); end if
); end defun
;----------------- Функция вставки мультилинии ---------------------------------
(defun Vml ( Di / p1 p2 Cml) 
  (setq p1 (getpoint "\nУкажите первую точку :"))
  (setq p2 (getpoint "\nУкажите вторую точку :" p1))
  (SMLK)
  (SMLP)
  (setq Cml (getvar "CMLSTYLE"))
  (if (eq kodS "vozK") (setvar "CMLSTYLE" "VenK"))
  (if (eq kodS "vozP") (setvar "CMLSTYLE" "VenP"))
  (command "_mline" "_J" "_Z" "_S" Di p1 p2 "")
  (setvar "CMLSTYLE" Cml)
); end defun
;------------------------ Основная программа ----------------------------------
(defun c:pr_uch (/ dcl_id ddi Raz plist_K plist_P kodS)
  ;--------- Диалоговое окно ------------
  (setq dcl_id (load_dialog "d:/MyLisp/Vozduh.dcl")); загружаем диалог (файл DCL)
  (if (not (new_dialog "pr_uch" dcl_id))(exit)) ; проверка существования диалога
  (iz_sech)
  (ras_v)
  (action_tile "rb_K" "(iz_sech) (ras_v)")
  (action_tile "rb_P" "(iz_sech) (ras_v)")
  (action_tile "pop1" "(ras_v)")
  (action_tile "eb_L" "(ras_v)")
  (action_tile "accept" "(done_dialog 1)");Если нажата кнопка "аccept"
  (action_tile "cancel" "(done_dialog 0)");Если нажата кнопка "cancel"
  (setq ddi (start_dialog))
 
  (unload_dialog dcl_id) ; выгрузить Диалоговое окно
  ;--------------------------------------
  (if (= ddi 1) (Vml Raz))
); end defun
;--------------------------------------------------------------------------------

И так мы рассмотрели основные этапы управления диалоговым окном из LISP программы.

Если у Вас появились вопросы, задавайте их в комментариях.

Если Вы нашли что-то полезное на моем сайте не забудьте порекомендовать статью в социальных сетях.

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

Хотите получать информацию о выходе новых статей. Оформляйте подписку.

До новых встреч.

«Автор: Михаил Орлов»

Также на эту тему Вы можете почитать:

9 комментарии на “Пример LISP программы управления диалоговым окном в Автокад

  1. Дмитрий 25.03.2016 08:18

    Очень тяжелый пример для меня оказался. Я его упростил в своих целях и всё равно ошибки, не могу понять где рыть!

  2. Светлана 11.04.2016 12:11

    Михаил, спасибо. Пример отработала весь. Почти всё получалось с первого раза. Очень нравится, что даете обстоятельное описание действий.
    В программном коде и в коде на рисунке 24 есть небольшие разногласия. Тексты различаются первой строкой основной программы, где дается описание переменных. Программа со строкой

    (defun c:pr_uch (/ dcl_id ddi Raz)

    НЕ выполняется. А программа со строкой

    (defun c:pr_uch (/ dcl_id ddi Raz plist_K plist_P kodS)

    работает.

    • Михаил Орлов 15.04.2016 13:39

      Не достающие переменные

      plist_K plist_P kodS

      в коде стояли в функциях

      (defun ras_v (/ L RazP n H plist_K plist_P)

      и

      (defun Vml ( Di / p1 p2 Cml kodS)

      В общем вариант в коде немного другой, но тоже правильный. Чтобы везде было однообразно, исправил чтобы было как на Рис. 24

  3. Дмитрий 01.12.2016 18:13

    Добрый вечер. А как записать код окна DCL при нажатии вместо OK и Отмена на крестик.
    Спасибо

  4. Светлана 02.03.2017 14:25

    Здравствуйте, Михаил. Еще раз хочу поблагодарить за Ваши уроки. Сильно помогают. На этом уроке «просидела» ни один день. Создавала на примере своё окно. Создала. Работает. Почти всё замечательно. НО. Как сделать, чтобы при открытии окна учитывались значения, которые хранятся в текстовом файле (например). Т.е. в примере окно всегда открывается с Круглым сечением, Сечение мм 100. Надо присвоить значение элементам окна, прочитав информацию из файла. Прочесть информацию из файла я смогла. А вот присвоить, как и когда не получается. Может подскажете, где почитать-посмотреть или сможете сами написать код для примера. Спасибо. С уважением.

  5. Надежда 10.05.2018 04:58

    Добрый день, Михаил! Огромное спасибо за Ваши уроки! Нигде не находила более понятных и подробных объяснений!
    Хотела спросить, есть ли примеры программ с вложенными окнами? На каком этапе должно происходить считывание значений параметров из второго окна?

    • Михаил Орлов 06.06.2018 20:30
      dia1:dialog{label = "Диалоговое окно первого уровня";
            :spacer {height=1;}
            :edit_box {label = "Данные из 1-го окна :"; key = "dan1";}      
            :spacer {height=1;}
            :button {label = "Вызвать следующие окно" ; key = "b1";}      
          ok_cancel;
      }// end dia1
      //---------------------------------------------------------------
      dia2:dialog{label = "Диалоговое окно второго уровня";
            :spacer {height=1;}
            :edit_box {label = "Данные из 2-го окна :"; key = "dan2";}      
            :spacer {height=1;}      
          ok_button;
      }// end dia2
      //****************************************************************
      ;------- открываем 2-е окно -----------------
      (defun opendia2 (dc /)
        (if (null (new_dialog "dia2" dc)) (exit))
        (action_tile "accept" "(read_kanali) (done_dialog 3)")
      
        (start_dialog)
      ); end defun
      ;-------------------------------------------
      
      ;------- запоминаем данные из 2-го окно ----
      (defun read_kanali ()
        (setq dan2 (get_tile "dan2"))  
      ); end defun
      ;-------------------------------------------
      
      ;------- запоминаем данные из 1-го окно ----
      (defun read_dan1 ()
        (setq dan1 (get_tile "dan1"))  
      ); end defun
      ;-------------------------------------------
      
      
      ;******************************************************
      (defun c:opendia1 (/ dcl_id ddi dan1 dan2)
        ;ДИАГОЛОВОЕ ОКНО 1
        ;==========================================================================================
        (setq dcl_id (load_dialog "C:\\1_Work\\Lisp\\2_окна\\twodia.DCL"));загружаем далоговое окно
        (if (null (new_dialog "dia1" dcl_id)) (exit))  
      
        (action_tile "b1" "(opendia2 dcl_id)")
        (action_tile "accept" "(read_dan1) (done_dialog 1)");Если нажата кнопка "аccept"
        (action_tile "cancel" "(done_dialog 0)");Если нажата кнопка "cancel"
        (setq ddi (start_dialog))
         
        (unload_dialog dcl_id) ; выгрузить Диалоговое окно
        ;==========================================================================================
        (if (= ddi 0) (exit))
      
        (princ (strcat "\ndan1 = " dan1))  
        (princ (strcat "\ndan2 = " dan2))
        (princ)
      ); end defun
      ;******************************************************
  6. Надежда 09.10.2020 09:36

    Добрый день!
    Спасибо за Ваши уроки!
    Подскажите пожалуйста, есть ли примеры как выполнять в одной программе команды, описанные в другой файле лисп?

Оставить комментарий

Ваш mail не будет опубликован.

Вы можете использовать HTML теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>