Цель лекции: приобрести навыки работы в построении диалоговых окон.
Рассмотрим пример программы вычерчивания полого рога с углом изгиба 180 градусов.
(defun c:qrog (/ cenrt1 rad1 diam1 circle1 arc1 rog1 thick1 angle1 endp1 col1) (setq centr1 '(0 0 0)) ; исходная базовая точка (setq rad1 (getreal "Задайте радиус базовой окружности: ")); радиус рога (80) (setq diam1 (getreal "Задайте диаметр направляющей дуги: ")); диаметр изгиба рога (400) (setq thick1 (getreal "Задайте толщину стенки рога: ")); толщина стенки в мм (2) (setq col1 (getint "Задайте индекс цвета: ")); выбор: 0,1,2,3,4,5,6 (setq angle1 (* 55.0 (atan rad1 (* diam1 (/ pi 2))))); угол изгиба рога (command "_view" "_top") ;начинаем со стандартного вида; устанавливаем вид сверху (command "_view" "_swiso"); переходим к северо-западному виду (command "_circle" centr1 rad1 ""); строим базовую окружность (setq circle1 (entlast)); извлекаем имя сущности для базовой окружности (command "_ucs" "_x" "90" ""); поворачиваем ПСК (setq endp1 (list diam1 0.0)); задаем конечную точку дуги (command "_arc" centr1 "e" endp1 "a" "-180" ""); строим дугу изгиба (setq arc1 (entlast)); извлекаем имя сущности для дуги и сохраняем его (command "_ucs" "_x" "-90"); совмещаем плоскость окружности с плоскостью XY (command "extrude" circle1 "" "t" angle1 "p" arc1 ""); строим тело рога (setq rog1 (entlast)); извлекаем имя сущности для рога и сохраняем его (command "_zoom" "e" ""); растягиваем изображение на весь экран (command "_vscurrent" "_r" ""); устанавливаем текущий визуальный стиль - realistic (command "_chprop" "_all" "" "_color" col1 ""); закрашиваем заданным цветом (command "_view" "_bottom" ""); устанавливаем вид снизу (command "_solidedit" "_body" "_shell" rog1 centr1 "" thick1 "" ""); удаляем внутренность рога (command "_erase" arc1 ""); удаляем образующую дугу (princ); тихий выход из программы )
Внешний вид рога показан на рис. 6.1.
(рис 6.1) Рисунок рога
Рог строился путем Shell.
При запуске функции qrog пользователь задавал требуемые параметры по запросам программы:
rad1;diam1;thick1;col1.Требуется вместо запросов создать диалоговое окно для одновременного ввода этих параметров.
Вначале напишем отдельную программу для открытия диалогового окна. В новом чертеже AutoCAD откройте среду Visual LISP по команде Tools - . По команде File - New File создайте новый файл. Наберите в нем следующий текст программы диалога "rog" на языке . Учтите только, что элементы языка чувствительны к регистру. Все ключевые слова, метки и коды элементов должны состоять только из латинских букв, цифр и символа подчеркивания. Начинаться служебные слова должны с латинской буквы.
//Диалоговое окно установки параметров рога
//
rog: dialog{label="Установка параметров рога";
:edit_box{label="Радиус окружности ";key="rad" ;value="0.00"; edit_width=8;}
:edit_box{label="Диаметр дуги, мм";key="diam";value="0.00";edit_width=8;}
:edit_box{label="Толщина стенки, мм";key="thick";value="0.00";edit_width=6;}
:spacer{height=1;}
:edit_box{label="Индекс цвета";key="col";value="0";edit_width=4;}
:spacer{height=1;}
ok_cancel;
}
Сохраните написанное в файле C:\Program Files\AutoCAD2007\Support\Rog.. Папка Support принадлежит к маршрутам файлов поддержки. Проверьте это еще раз, выполнив команду Tools - Options - Files - Support File . Чтобы открыть диалоговое окно на экране, система должна загрузить -файл. Эта загрузка может быть выполнена лишь тогда, когда -файл помещен в данную папку. Иначе нужно указывать полный путь к файлу.
Вся написанная программа называется диалогом. В одном файле может быть несколько диалогов. Рассмотрим структуру программы-диалога.
За двойной чертой // до конца строки размещается комментарий. В нашей программе комментарий занимает первые две строки. Далее программа содержит логически законченные единицы - директивы. Каждая директива описывает один элемент (tile) или способ группировки элементов внутри диалогового окна. Директива должна заканчиваться фигурной скобкой или точкой с запятой. Количество открывающих скобок должно быть равно количеству закрывающих скобок. При описании элементов разделителем служит точка с запятой. Текстовые строки должны быть заключены в кавычки. Между ключевыми словами языка, разделительными символами, метками, числовыми и строковыми значениями может быть любое количество пробелов.
Директивы могут записываться в двух видах:
[<метка>]:<оператор>{<атрибуты>}
<метка>;
Здесь квадратные скобки обозначают необязательность размещенного внутри них элемента. Фигурные скобки и двоеточия являются обычными символами. Метка - идентификатор директивы. Она должна быть уникальной в данном файле.
В листинге программы мы сразу можем выделить директиву описания диалога в целом:
rog: dialog {label="Установка параметров рога";
…
ok_cancel;
}
rog - это метка, имя диалога;
dialog - это оператор, он вызывает свою подпрограмму, выполняющую действия;
label="…"; - эта надпись будет заголовком диалогового окна;
ok_cancel - внизу окна будут размещены кнопки ОК и CANCEL (Отмена).
Внутри директивы dialog размещены четыре однотипные директивы, имеющие следующий вид:
:edit_box{label="Радиус окружности "; key="rad"; value="0.00"; edit_width=8;}
Элементы этих директив описывают следующие понятия:
edit_box - оператор редактируемого текстового поля;label="…"; - эта надпись будет размещена перед текстовым полем;key="rad"; - код диалога;value="0.00"; - значение, которое содержит текстовое поле по умолчанию;edit_width=8; - ширина окна текстового поля в символах шрифта.В листинге программы имеются еще две одинаковые директивы
:spacer{height=1;}
- это пустой элемент, обозначающий пропуск строки;
height=1; - атрибут height показывает высоту пропущенной строки. Единицей измерения является стандартная высота строки текущего шрифта.
Итак, в сохраненном файле "Rog." описано диалоговое окно с именем диалога "rog". Окно должно иметь четыре текстовых поля с видимыми в них значениями по умолчанию.
Составим теперь LISP-функцию, которая позволяла бы загружать (load_dialog) и выгружать (unload_dialog) -файлы, открывать и закрывать окна загруженных диалогов. В редакторе Visual LISP создайте новый файл и наберите в нем следующий текст:
(defun c:show_rog ( / num) (if (< (setq num (load_dialog "rog.dcl")) 0)(exit)) (if (not (new_dialog "rog" num)) (exit)) (start_dialog) (unload_dialog num) (princ) );defun
В первой строке определена функция show_rog c локальной переменной num. В переменной num сохраняется внутренний номер открываемого диалогового окна. Обычно он присваивается всем вновь открываемым диалогам по порядку, начиная с единицы.
Во второй строке записана команда (load_dialog "rog.), загружающая файл rog.. Если полный адрес файла не указан, то система ищет этот файл по стандартному алгоритму поиска файлов поддержки. Если загрузка прошла успешно, то функция load_dialog возвращает положительное целое число, которое присваивается переменной num. Если загрузка не выполнилась, то возвращается отрицательное число. В этом случае выполняется функция exit, прерывающая работу приложения.
В третьей строке проверяется, имеется ли в загруженном -файле rog. диалог с именем "rog", имеющий номер num. Если такого диалога в файле нет, то программа завершается с помощью функции exit. Если такой диалог есть, то активируется диалоговое окно, управление передается функции start_dialog. Эта функция возвращает 1, если пользователь выйдет из диалогового окна с помощью кнопки OK или 0, если пользователь выйдет из диалогового окна с помощью кнопки Cancel.
В пятой строке функция unload_dialog num выгружает файл из оперативной памяти. Возвращаемое значение - nil.
Загрузите файл, перейдите в AutoCAD и наберите в командной строке show_rog. На экране появится диалоговое окно (рис. 6.2).
(рис 6.2) Диалоговое окно
Установите параметры в текстовых полях. Щелкните по кнопке ОК. Окно исчезнет с экрана. Файл rog. выгрузится из оперативной памяти. Чтобы воспользоваться результатами работы с окном, нужна программа, анализирующая введенные величины.
Исключим из программы черчения рога приглашения задать параметры рога и включим обращение к диалогу "rog". На время наладки программы введем печать четырех параметров в отдельных строках.
(defun c:qrog (/ cenrt1 rad1 diam1 circle1 arc1 rog1 thick1 angle1 endp1 col1) (setq centr1 '(0 0 0)) ; исходная базовая точка (if (< (setq num (load_dialog "rog.dcl")) 0) (exit)); загружаем в память файл "rog.dcl" (if (not (new_dialog "rog" num)) (exit)) ;;функция new_dialog проверяет наличие в файле диалога "rog" (action_tile "rad" "(setq rad1 (atof $value))"); присваиваем значение переменной rad1 (terpri); перевод строки (princ rad1); выводим на экран значение переменной rad1 (action_tile "diam" "(setq diam1 (atof $value))"); присваиваем значение переменной diam1 (terpri); перевод строки (princ diam1); выводим на экран значение переменной diam1 (action_tile "thick" "(setq thick1 (atof $value))"); присваиваем значение переменной thick1 (terpri); перевод строки (princ thick1); выводим на экран значение переменной thick1 (action_tile "col" "(setq col1 $value)"); присваиваем значение переменной col1 (terpri) ; перевод строки (princ col1); выводим на экран значение переменной col1 (terpri); перевод строки (start_dialog); возвращает 1 или 0 (unload_dialog num); выгружает окно из памяти (setq angle1 (* 55.0 (atan rad1 (* diam1 (/ pi 2))))); находим угол сужения тела рога (command "_view" "_top") ; начинаем со стандартного вида сверху (command "_view" "_swiso"); переходим к северо-западному виду (command "_circle" centr1 rad1 "") ; строим базовую окружность (setq circle1 (entlast)); извлекаем имя сущности для базовой окружности (command "_ucs" "_x" "90" ""); поворачиваем ПСК (setq endp1 (list diam1 0.0)); находим координаты конечной точки дуги (command "_arc" centr1 "e" endp1 "a" "-180" ""); строим образующую дугу (setq arc1 (entlast)); извлекаем имя сущности для дуги и сохраняем его (command "_ucs" "_x" "-90"); совмещаем плоскость окружности с плоскостью XY (command "extrude" circle1 "" "t" angle1 "p" arc1 ""); создаем тело рога (setq rog1 (entlast)); извлекаем имя сущности для рога и сохраняем его (command "_zoom" "e" ""); растягиваем изображение на весь экран (command "_vscurrent" "_r" "") устанавливаем текущий визуальный стиль realistic (command "_chprop" "_all" "" "_color" col1 ""); закрашиваем цветом col1 (command "_view" "_bottom" ""); устанавливаем вид снизу (command "_solidedit" "_body" "_shell" rog1 centr1 "" thick1 "" ""); делаем в теле рога полость (command "_erase" arc1 ""); удаляем образующую дугу (princ); тихий выход )
Для обработки данных, вводимых в текстовых полях диалогового окна, применена функция action_tile. Она помещена между функциями new_dialog и start_dialog. Функция имеет следующий синтаксис:
(action_tile <код> <выражение>)
<код> - это строка с кодом элемента;
<выражение> - строка с LISP-выражением действия, выполняемого при выборе данного элемента;
Возвращаемое значение Т.
Функция action_tile присваивает значения текстовых полей переменным функции qrog. Текстовые поля различаются по кодам этих полей. Значения полей сохраняются в глобальной переменной $value. Тип сохраненных величин - строковые константы. Чтобы обеспечить возможность дальнейших расчетов, применено преобразование строковых констант в вещественные числа с помощью функции atof.
Технология создания диалоговых окон изложена в предыдущем разделе. Сейчас разберем более подробно отдельные элементы и синтаксис языка с использованием LISP-программ.
Директива описания диалога задает имя, по которому диалоговое окно вызывается из программы на экран. Директива использует ключевое слово dialog:
<имя>:dialog{<атрибуты><элементы>}
В качестве имени диалога может быть использован любой идентификатор, не совпадающий со служебными словами. Имена диалогов в одном сеансе AutoCAD не должны повторяться. Параметр >атрибуты< - это последовательность разделяемых точкой с запятой операций задания атрибутам значений:
<атрибут1>=<значение1>;<атрибут2>=<значение2>;…
Параметр <элементы> является набором директив описания элементов (текстовых полей, кнопок, списков, надписей, флажков и пр.).
Имена атрибутов и элементов должны быть стандартными ключевыми словами. Значения атрибутов могут быть числами или строками, - в зависимости от атрибута. Если директива описывает элемент диалогового окна, то параметр <атрибуты> - это описание атрибутов элемента и их значений, отличных от значений по умолчанию. Если директива является директивой группировки элементов, то она содержит внутри фигурных скобок директивы определения группируемых элементов.
Атрибуты диалога - это различные характеристики окна в целом или его отдельных элементов. В таблице приведены ключевые слова, которые могут быть использованы в качестве атрибутов в директиве описания диалога.
| Атрибут | Описание | Допустимые значения | Значение по умолчанию |
|---|---|---|---|
Label |
Начальный текст заголовка диалогового окна | Строка | " " (пробел) |
Value |
Текущий текст заголовка диалогового окна | Строка | Нет |
Key |
Код диалога | Строка | Нет |
Width |
Ширина окна | Число | Нет |
Height |
Высота окна | Число | Нет |
initial_focus |
Код подсвеченного элемента в диалоговом окне | Строка | Нет |
children_alignment |
Способ выравнивания подчиненных элементов по умолчанию | left, right, centered (для колонок), top, bottom, centered (для рядов) |
left (для колонок), centered (для рядов) |
children_fixed_width |
Фиксация ширины подчиненных элементов по умолчанию | true, false |
false |
children_fixed_height |
Фиксация высоты подчиненных элементов по умолчанию | true, false |
false |
Атрибуты label и value близки по смыслу. Различие между ними состоит в том, что атрибут label влияет на размер окна, а значение атрибута value - не влияет. Атрибут key обеспечивает возможность изменить программно заголовок выводимого диалогового окна. В качестве значения кода диалога могут использоваться только строки.
Атрибут width задает минимальную ширину окна в условных символах. Ширина символа равна средней ширине символа латинского алфавита шрифта по умолчанию. Ширина окна вычисляется системой по размерам заголовка и элементов. Если она получилась меньше, чем задано в значении атрибута width, то она увеличивается. То же самое справедливо для атрибута height, только здесь задается высота окна в количестве условных высот символа шрифта.
Атрибут initial_focus указывает код элемента, который подсвечивается по умолчанию и выполняет действие при нажатии пользователем клавиши ENTER.
Три атрибута с префиксом children задают свойства не самого диалога, а входящих в него элементов. Атрибут children_alignment задает способ, которым система AutoCAD выравнивает элементы, размещенные в диалоговом окне. По умолчанию элементы диалога, расположенные в колонку, выравниваются влево, а элементы, расположенные в ряд, выравниваются по центру. На элементы, у которых задан свой атрибут alignment, значение атрибута children_alignment не влияет.
Атрибуты children_fixed_width и children_fixed_height обычно задают тогда, когда их значение равно true. Это означает, что по умолчанию размеры подчиненных элементов (например, кнопок) не изменяются при выводе диалогового окна. Система не будет растягивать кнопки, а будет лишь изменять расстояния между ними.
В среде Visual LISP имеется способ проверки внешнего вида диалогового окна без загрузки -файла в память системы. Для этого нужно запустить команду Tools - Interface Tools - Preview . Активизируется диалоговое окно, в котором нужно выбрать имя диалога. После этого диалоговое окно отобразится на экране.
Внутри директивы описания диалога размещены директивы описания элементов. Эти директивы записываются в форме:
[<метка>]:<оператор>{<атрибуты>}
Каждый элемент является либо элементом оформления (надписи, слайды и пр.), либо элементом управления (кнопки, текстовые поля, списки и пр.). К элементам управления пользователь имеет доступ с помощью клавиатуры или указателя мыши.
В директивах в качестве значения <оператор> могут использоваться следующие наименования элементов:
button - кнопка;edit_box - редактируемое текстовое поле;errtile - поле для отображения сообщений об ошибках;image - поле с изображением;image_button - кнопка с изображением;list_box - список;popup_list -раскрывающийся список;radio_button - переключатель;radio_column - вертикальная группа переключателей;radio_row - горизонтальная группа переключателей;boxed_radio_column - конка переключателей в рамке;boxed_radio_row - ряд переключателей в рамке;slider - скользящая шкала;toggle - флажок;column - колонка (средство объединения элементов);row - ряд (средство объединения элементов);text - нередактируемое текстовое поле;text_part - часть текста, включаемая в элементы concatenation и paragraph;concatenation - text_part;paragraph - вертикальное соединение элементов text_part и concatenation;spacer - пустой элемент ширины width и высоты height;spacer_0 - элемент c нулевыми значениями ширины width и высоты height;spacer_1 - элемент width и height.В файле base. определены следующие элементы, ссылки на которые очень часто применяются в пользовательских диалоговых окнах:
ok_button - элемент с одной кнопкой ОК;ok_only - элемент в виде колонки с одной кнопкой ОК;ok_cancel - элемент из кнопок OK и Cancel;ok_cancel_help - элемент из кнопок OK, Cancel и Help;ok_ cancel_err - элемент из кнопок OK и Cancel и полем сообщений об ошибках;ok_cancel_help_errtile - элемент из кнопок OK, Cancel, Help и полем сообщений об ошибках;ok_cancel_help_info - элемент из кнопок OK, Cancel, Help и Info.Все эти элементы содержат кнопку выхода из диалогового окна. Ниже приведены коды (keys) стандартных элементов, включенные в элементы с кнопкой выхода.
| Элемент (кнопка) | Код элемента |
|---|---|
OK |
"accept" |
Cancel |
"cancel" |
Help |
"help" |
Info |
"info" |
| Поле сообщений об ошибках | "error" |
При описании элемента нет необходимости перечислять значения всех его атрибутов. Достаточно указать только те атрибуты, значения которых должны отличаться от значений по умолчанию. Большая часть атрибутов (например, label, value, key, width, height и др.) применяется во всех элементах. Однако смысл атрибута в разных элементах может быть различным.
Ниже приведены некоторые часто употребляемые атрибуты
| Атрибут | Описание | Допустимые значения | Область применения | Значения по умолчанию |
|---|---|---|---|---|
Action |
Действия, выполняемые при выборе данного элемента | Строка с текстом |
Элементы управления | " " |
alignment |
Способ выравнивания | left, right, centered; top, bottom, centered |
Все элементы | left, centered |
Color |
Цвет | 0-256 или black, red, yellow, green, cyan, blue, magenta |
image |
7 |
edit_width |
Количество видимых символов в редактируемом поле | Целое число | edit_box |
Максимально возможное |
is_cancel |
Признак срабатывания при нажатии ESC |
true, false |
button (только один элемент) |
false |
is_default |
Признак срабатывания при нажатии ENTER |
true, false |
button (только один элемент) |
false |
Key |
Код элемента | Строка | Все элементы | Нет |
Label |
Начальный заголовок | Строка | Все элементы | " " |
List |
Начальное состояние списка | Строка с элементами списка (разделитель \n) |
list_box, popup_list |
Нет |
multiple_select |
Разрешение множественности выбора | true, false |
list_box |
false |
password_char |
Символ, закрывающий текст вводимого пароля | Символ | Edit_box |
Нет |
Value |
Начальное значение | Строка | Все элементы | Нет |
Для того, чтобы вызвать на экран диалоговое окно, необходимо сначала загрузить -файл, содержащий нужный диалог с описанием окна. Затем нужно открыть диалоговое окно. После завершения в окне всех установок оно должно быть закрыто. После закрытия диалогового окна -файл выгружается из оперативной памяти. Все эти операции выполняются с помощью специальных функций.
Функция load_dialog загружает -файл в оперативную память компьютера. Синтаксис функции:
(load_dialog <файл>)
Аргумент <файл> - текстовая строка (текст в кавычках) с именем файла. Возвращаемое значение - положительное целое число при успешной загрузке. Это число является порядковым номером -файла, загруженного в данном сеансе работы с сиcтемой AutoCAD. Если загрузка не выполнена, то функция возвращает отрицательное число. Если в имени файла не указан полный путь, то система AutoCAD пытается найти файл, просматривая все маршруты файлов поддержки.
Функция unload_dialog выгружает -файл из оперативной памяти компьютера. Синтаксис функции:
(unload_dialog <номер>)
Аргумент <номер> - положительное целое число, которое было возвращено при вызове функции load_dialog. Возвращаемое значение - nil.
Функция new_dialog открывает на экране диалоговое окно, если его диалог уже загружен в оперативную память в составе -файла. Синтаксис функции:
(new_dialog <диалог> <номер> [<действие> [<положение>]])
Аргументы:
load_dialog;LISP-выражением (если нет действия, оставить "");Функция возвращает Т, если диалоговое окно открылось, и nil, если возникла ошибка открытия. Когда по условиям задачи аргумент <положение> должен быть задан, то должен быть задан и аргумент "действие". Это действие будет выполнено только тогда, когда пользователь выбрал элемент, для которого не задано действие с помощью атрибута action или функции action-tile.
Пример:
(new_dialog "cone" num "" (list 111 222)) - открывает диалоговое окно с диалогом cone. Левый верхний угол помещен в точку (111,222). Функция возвращает T.
Функция start_dialog активизирует диалоговое окно и готовит систему AutoCAD к приему действий пользователя в этом окне. Синтаксис:
(start_dialog)
Возвращает целое число, которое было передано в качестве аргумента функции done_dialog. Если приложение закрывает диалоговое окно, а функции done_dialog при этом не передано никакого аргумента, то функция start_dialog возвратит:
ОК;Cancel;term_dialog.Функция done_dialog используется только внутри LISP-выражений в функции action-tile или атрибуте action. Она закрывает диалоговое окно и передает значение, которое будет возвращаемым значением функции start_dialog. Синтаксис:
(done_dialog [<число>])
Аргумент <число> - это положительное целое число, которое станет возвращаемым значением функции start_dialog. Возвращаемое значение - список из двух целых чисел с координатами левого верхнего угла диалогового окна в момент его закрытия.
Пример:
(done_dialog 92) - может вернуть список (220 180), а функция start_dialog при этом вернет 92.
Функция term_dialog закрывает все открытые диалоговые окна так, как будто пользователь вышел из каждого из них, нажимая кнопку Cancel. Синтаксис:
(term_dialog)
Возвращаемое значение - nil.
Если работа приложения прерывается по какой-то причине, а некоторые диалоговые окна остались незакрытыми, то система AutoCAD сама обеспечивает вызов функции term_dialog.
Несколько функций языка LISP управляют элементами и их действиями. Они позволяют выполнять следующие операции:
LISP-выражение, выполняемое при выборе элемента и нажатии клавиши ENTER или щелчке левой клавишей мыши (функция action_tile);mode_tile);get_tile);set_tile);get_attr);client_data_tile).Функция action_tile задает при помощи LISP-выражения действие, которое нужно выполнить системе AutoCAD при выборе элемента или редактировании его содержимого. Синтаксис функции:
(action_tile <код> <выражение>)
Аргументы: <код> - строка с кодом элемента, <выражение> - строка с LISP-выражением. Возвращаемое значение - Т.
Большинство элементов диалогового окна являются элементами управления. Для них должны быть описаны действия, выполняемые системой AutoCAD при выборе пользователем этого элемента. Под выбором элемента имеются в виду, в частности, такие события, вызванные пользователем:
Enter;Button;edit_box;list_box или popup_box;slider .Отклик системы на события окна совершается тогда, когда после операции с одним элементом курсор перейдет к другому элементу или пользователь выйдет из диалогового окна с помощью кнопки выхода.
Такое действие для каждого элемента может быть задано с помощью атрибута action -файла. Значением атрибута может быть строка с LISP-выражением (там не должно быть функции command). Другой вариант задания действия - указание LISP-выражения в строке, передаваемой в качестве аргумента функции action_tile. Обращение к этой функции должно быть записано между вызовами функций new_dialog и start_dialog.
Действие, заданное с помощью аргумента <выражение> функции action_tile аннулирует действие, заданное значением атрибута action этого элемента в -файле. Действие всегда задается через код элемента. Значение атрибута key передается функции action_tile в качестве аргумента <код>.
LISP-выражение в функции action_tile может использовать значения зарезервированных глобальных переменных со следующими именами:
$value - текущее значение рассматриваемого элемента;$key - код рассматриваемого элемента;$reason - тип действия, выполненного над элементом;$data - данные элемента, заданные функцией client_data_tile;$x и $y - координаты указанной точки внутри изображения.Примеры:
(action_tile "accept" "(done_dialog)") - действие кнопки выхода;
(action_tile "Test" ( - проверка значения элемента на отрицательные числа или ноль;
В этом примере длинное LISP-выражение получено сцепкой двух строк. Обратите внимание на то, что внутренние двойные кавычки, необходимые для вызова функции alert, применяются с предшествующим слэшем.
(action_tile "Test" "(setq myTest 1) (saveVars) (done_dialog)")
По событию с элементом "Test" выполняется три действия: переменной myTest присваивается значение 1, запускается функция saveVars и закрывается диалоговое окно. Обратите внимание, что и код и выражение всегда берутся в кавычки.
Функция mode_tile изменяет состояние элемента диалога. Синтаксис:
(mode_tile <код> <состояние>)
Аргументы: <код> - код элемента; <состояние> - целое число от 0 до 4 (см. таблицу). Возвращаемое значение - nil.
| Значение | Действие |
|---|---|
| 0 | Включить элемент |
| 1 | Выключить элемент (сделать недоступным) |
| 2 | Выбрать элемент |
| 3 | Подсветить содержимое элемента |
| 4 | Включить/выключить подсветку изображения |
При выключении элемента его цвет приглушается. Он становится недоступным для пользователя. Чтобы сделать его вновь доступным, его надо включить.
Примеры:
(mode_tile "k1" 1) - выключает элемент с кодом k1;
(mode_tile "k1" 0) - включает элемент с кодом k1.
Функция set_tile позволяет менять содержание диалога, заданное атрибутом value.
(set_tile <код> <значение>)
Аргументы: <код> - код элемента; <значение> - строка с новым значением, присваиваемым атрибуту value данного элемента.
Возвращаемое значение - значение второго аргумента, переданного функции.
Функция get_tile читает содержимое элемента диалога (текущее значение атрибута value). Синтаксис:
(get_tile <код>)
Аргумент - строка с кодом элемента.
Возвращаемое значение - строка с текущим значением атрибута value.
Функция get_attr читает значение атрибута элемента текущего каталога:
(get_attr <код> <атрибут>)
Аргументы: <код> - строка с кодом элемента, <атрибут> - строка с именем атрибута. Возвращаемое значение - строка со значением атрибута элемента.
Пример:
(get_attr "user" "alignment") - возвратит "centered"
Функция client_data_tile связывает с элементом диалогового окна строку с пользовательскими данными. Синтаксис:
(client_data_tile <код> <данные>)
Аргументы: <код> - строка с кодом элемента, <данные> - строка с пользовательскими данными. Возвращаемое значение - nil.
Чтобы обратиться к данным, присоединенным к элементу диалогового окна, нужно прочитать значение переменной $data в функции action_tile. Так можно изменять действие, присвоенное элементу, в зависимости от пользовательских данных.
Пример:
(client_data_tile "user" "2110") - связывает строку 2110 с элементом "user".
Во время работы диалогового окна система AutoCAD формирует значения глобальных переменных, которые называются переменными действия:
$key, $value, $reason, $data, $x, $y.
В них сохраняются некоторые дополнительные данные о состоянии диалогового окна и выполненных в нем действиях пользователя. Переменные используются в LISP-выражениях, задаваемых в качестве второго аргумента функции action_tile. Вне этой функции значения переменных действия не определены.
Пользовательская программа не может изменять значения этих переменных и должна применять их только для чтения. В таблице рассматриваются различные варианты формирования значений переменных действия.
| Переменная | Значение |
|---|---|
$key |
Код элемента (во всех элементах) |
$value |
Значение атрибута Для поля Для Для |
$data |
Строка с пользовательскими данными, привязанными к элементу |
Sreason |
Для элементов edit_box, list_box, image_button и - число с кодом причины прерывания работы с элементом (см. следующую таблицу) |
$x, $y |
Координаты в пикселях указанной пользователем точки внутри изображения для элемента image_button |
Примеры:
(action_tile "user" "(setq nam (strcat \ "Пользователь: \" $value))"); (action_tile "cldat" "(setq tyg (read $data))");
| Значение | Описание |
|---|---|
| 1 | Обычный вариант действия с элементом, в том числе, пользователь выбрал элемент, нажата клавиша ENTER, а элемент имеет значение true атрибута is_default |
| 2 | Для поля edit_box: пользователь вышел из поля, но не завершил редактирование (например, нажал клавишу TAB или выбрал другой элемент) |
| 3 | Для элемента пользователь изменил значение элемента с помощью указателя шкалы, но не завершил ввода |
| 4 | Для элементов list_box и image_button: пользователь выполнил двойной щелчок. Если multiple_selection=false, то это должно означать окончательный выбор. Если multiple_selection=true, то это должно обрабатываться как обычный выбор (значение 1). |
Функция start_list начинает операцию редактирования списка в элементах list_box и popup_list. Синтаксис функции:
(start_list <код>[<операция> [<номер>]])
Аргументы:
<операция> - целое число, обозначающее тип операции:
По умолчанию для второго аргумента действующее значение равно 3, а для третьего аргумента - равно 0. Аргументы в списке нумеруются, начиная с нуля.
Возвращаемое значение - код элемента
Вызов функции start_list является отметкой начала операции формирования или редактирования списка. Вызов функции end_list является отметкой окончания операции. Изменения вносятся с помощью функции add_list и других функций, расположенных между start_list и end_list. Здесь нельзя использовать функцию set_tile.
Примеры:
(start_list "kr2") - указывает начало операции формирования заново списка для элемента диалога с кодом "kr2"; (start_list "kr2" 2) - указывает начало операции добавления новых элементов списка для элемента диалога с кодом "kr2"; (start_list "kr2" 1 14) - указывает начало операции замены элементов списка, начиная с 14, для элемента диалога с кодом "kr2".Функция add_list выполняет операцию редактирования списка в элементах list_box и popup_list. Синтаксис функции:
(add_list <строка>)
Аргументы <строка> - строка, которая добавляется к списку или заменяет элемент списка. Возвращаемое значение - значение аргумента <строка>, если операция выполнена успешно. В случае сбоя возвращается nil.
Тип операции (изменение или добавление) определяется предшествующим вызовом функции start_list.
Пример: (add_list "Деталь 3217-06")
Функция end_list завершает операцию редактирования списка в элементах list_box и popup_list. Синтаксис функции:
(end_list)
Возвращаемое значение nil.
Элементы image и image_button являются графическими полями с прямоугольной зоной. Зона может быть заполнена
Открывает процесс заполнения функция start_image, а завершает процесс заполнения функция end_image. Между ними располагаются функции fill_image, slide_image, vector_image. Не допускается применять функцию set_tile. При указании координат в графическом окне предполагается, что левый верхний угол графического элемента находится в начале координат. Координаты правого нижнего угла могут быть получены с помощью функций dimx_tile и dimy_tile.
Функция start_image открывает процесс заполнения графического элемента. Синтаксис:
(start_image <код>)
Аргумент <код> - значение атрибута key графического элемента. Возвращаемое значение - строка со значением аргумента, если операция выполнена успешно. В случае сбоя возвращается nil.
Функция end_image завершает процесс формирования изображения. Синтаксис:
(end_image)
Возвращаемое значение - nil.
Вызову функции end_image должен обязательно предшествовать вызов функции start_image.
Функция fill_image заполняет прямоугольник внутри графического элемента одним цветом. Синтаксис:
(fill_image <x1> <y1> <ширина> <высота> <цвет>)
Аргументы:
Возвращаемое значение - значение аргумента <цвет>.
Пример: (fill_image 5 6 15 25 1) - заполняет красным (1) цветом прямоугольник с левым верхним углом в точке (5,6) и нижним правым углом в точке (15,25).
Функция slide_image заполняет графический элемент слайдом из отдельного -файла или из библиотеки слайдов. Синтаксис:
(slide_image <x1> <y1> <ширина> <высота> <слайд>)
Аргументы <x1> <y1> <ширина> <высота> аналогичны таковым для функции fill_image. Аргумент <слайд> - строка с именем файла слайда (расширение . не указывается) или с именем библиотеки слайдов (имя слайда из библиотеки указывается в круглых скобках).
Возвращаемое значение - строка со значением аргумента <слайд>.
Примеры:
(slide_image 0 0 50 32 "ring1") - заполняет графический элемент размером 50х30 слайдом из файла ring1..
(slide_image 0 0 50 32 "lib23(nut8)") - заполняет графический элемент размером 50х30 слайдом nut8 из библиотеки слайдов lib23.
Функция vector_image рисует отрезок заданного цвета внутри графического элемента диалогового окна. Синтаксис:
(vector_image <x1> <y1> <x2> <y2> <цвет>)
Аргументы:
Пример:
(vector_image 5 11 33 11 2) - рисует отрезок желтого цвета из точки (5,11) в точку (33, 11).
Функция dimx_tile вычисляет горизонтальный размер графического элемента с данным кодом (точнее, размер элемента минус 1). Синтаксис:
(dimх_tile <код>)
Аргумент <код> - строка с кодом графического элемента. Возвращаемое значение - целое число с номером крайнего правого пикселя элемента (левый крайний пиксель имеет номер ноль).
Пример:
(dimx_tile "igp2") - может вернуть 50 (всего по горизонтали 51 пиксель)
Функция dimy_tile вычисляет вертикальный размер графического элемента с данным кодом (точнее, размер элемента минус 1). Синтаксис:
(dimy_tile <код>)
Аргумент <код> - строка с кодом графического элемента. Возвращаемое значение - целое число с номером крайнего нижнего пикселя элемента (верхний крайний пиксель имеет номер ноль)
Пример: (dimy_tile "igp2") - может вернуть 32 (всего по вертикали будет 33 пикселя).
Установите элементы диалогового окна согласно следующей программе:
// Установки элементов диалогового окна
//
elements: dialog {label="Установка элементов диалогового окна";
:column{:row{:boxed_column{label="Элементы управления";
:row{:boxed_column{label="Поле и выпадающий список";
:edit_box {label="Edit_box";key="txt";value="0.00";edit_width=8;}
:popup_list {label="Popup_list";key="pop";width="8";list="Иванов\nПетров\nСидоров";}}
:boxed_column{label="Кнопка и шкала";
:button {label="Button";key="but";color="1";width="8";}
:slider {label="Slider";}}}
:spacer{height=1;}
:radio_row {label="Ряд переключателей (radio_row)";
:radio_button {label="Radio_button 1";value=1;}
:radio_button {label="Radio_button 2";value=0;}
}
}
:boxed_row{:column{label="Список и флажок";
:list_box {label="List_box";key="list";list="Иванов\nПетров\nСидоров";height="8";}
:toggle {label="Toggle";value=1;}
}
}}
:boxed_row{label="Стандартная кнопка закрытия окна";
ok_cancel_help_info;
}}}
Сохраните файл как Elements. в папке Support.
Создайте файл загрузки:
(defun c:show_elements (/ num ddiag)
(if (< (setq num (load_dialog "elements.dcl")) 0)
(prong
(alert "The Elements.dcl file could not be loaded!") (exit))
)
(if (not (new_dialog "elements" num))
(exit)
)
(start_dialog)
(unload_dialog num)
;;;--- If the user pressed the Cancel button
(if (= ddiag 1)
(princ "\n Window cancelled!")
)
;;;--- If the user pressed the Okay button
(if (= ddiag 2)
(progn
(princ "\n The user pressed Okey!")
)
)
(princ)
) ;_defun
Сохраните файл загрузки как Elements..
Запустите функцию show_elements из командной строки AutoCAD. На экране должно появиться диалоговое окно (рис. 6.3).
(рис 6.3) Элементы диалогового окна
Программа может различить в наших действиях лишь нажатие кнопок ОК и Cancel.
Измените описание диалогового окна в файле rog.:
//Диалоговое окно установки параметров рога
rog: dialog{label="Установка параметров рога";
:edit_box{label="Радиус окружности ";key="rad" ;value="80.00"; edit_width=8;}
:edit_box{label="Диаметр дуги, мм";key="diam";value="400.00";edit_width=8;}
:edit_box{label="Толщина стенки, мм";key="thick";value="1.00";edit_width=6;}
:spacer{height=1;}
:edit_box{label="Индекс цвета";key="col";value="2";edit_width=4;}
:spacer{height=1;}
ok_cancel;
}
А теперь вернитесь к файлу rog.. В функции qrog отклики на события в диалоговом окне описывались с помощью функции action_tile. Значения переменных сохранялись для каждого отдельного элемента. Опробуйте другой способ сохранения указанных данных - по нажатии кнопки ОК. В этом случае можно оставить значения величин по умолчанию, либо отредактировать их в текстовых полях диалогового окна.
Создайте в этом же файле новую функцию save_vars, которая будет вызываться после нажатия кнопки ОК. Содержимое текстовых полей прочитает функция get_tile.
Следует учесть, что в данном случае переменные rad1, diam1, thick1, col1 должны быть общими для функций qrog и save_vars, т.е. глобальными.
(defun save_vars () (setq rad1 (atof (get_tile "rad"))) (setq diam1 (atof (get_tile "diam"))) (setq thick1 (atof (get_tile "thick"))) (setq col1 (get_tile "col")) )
Программа построения рога будет выглядеть следующим образом:
(defun c:qrog (/ cenrt1 circle1 arc1 rog1 angle1 endp1 dial) (setq centr1 '(0 0 0)) ; исходная базовая точка (if (< (setq num (load_dialog "rog.dcl")) 0); загружаем в память файл "rog.dcl" (progn (alert "Файл Rog.dcl не загружен!"); сообщение о неудачной загрузке (exit) )) (if (not (new_dialog "rog" num)); ;; ;;функция new_dialog проверяет наличие в файле диалога "rog" (progn (alert "Диалог Rog не найден!"); сообщение о неудачном поиске файла (exit) )) ;;;If an action event occurs, do this function (action_tile "accept" "(setq dial 2)(save_vars)(done_dialog)"); действия при нажатии ОК (action_tile "cancel" "(setq dial 1)(done_dialog)"); действия при нажатии CANCEL (start_dialog); активизирует диалоговое окно (unload_dialog num); выгружаем окно из памяти (setq angle1 (* 55.0 (atan rad1 (* diam1 (/ pi 2))))); находим угол сужения тела рога (command "_view" "_top") ; начинаем со стандартного вида (command "_view" "_swiso"); переходим к северо-западному виду (command "_circle" centr1 rad1 ""); строим базовую окружность (setq circle1 (entlast)); извлекаем имя сущности для базовой окружности (command "_ucs" "_x" "90" ""); поворачиваем ПСК (setq endp1 (list diam1 0.0)); находим координаты конечной точки дуги (command "_arc" centr1 "e" endp1 "a" "-180" ""); строим дугу изгиба рога (setq arc1 (entlast)); извлекаем имя сущности для дуги и сохраняем его (command "_ucs" "_x" "-90"); совмещаем плоскость окружности с плоскостью XY (command "extrude" circle1 "" "t" angle1 "p" arc1 "");создаем тело рога (setq rog1 (entlast)); извлекаем имя сущности для рога и сохраняем его (command "_zoom" "e" ""); растягиваем изображение на весь экран (command "_vscurrent" "_r" ""); устанавливаем текущий визуальный стиль realistic (command "_chprop" "_all" "" "_color" col1 ""); закрашиваем цветом col1 (command "_view" "_bottom" ""); устанавливаем вид снизу (command "_solidedit" "_body" "_shell" rog1 centr1 "" thick1 "" ""); делаем полость (command "_erase" arc1 ""); удаляем ненужную образующую дугу ;;;If the user pressed the Okey Or Cancel button (if(= dial 2) (alert "Congratulations!")); поздравление при успешном построении (if(= dial 1) (alert "Alas!")); увы! - при неудачном построении (princ); тихий выход )
В качестве варианта введите операции сохранения значений переменных в функцию qrog. Сделайте все переменные save_vars тогда не нужна.
Рассмотрим теперь более подробно работу с отдельными элементами диалоговых окон: с кнопками, со списками, с флажками и с радиокнопками.
Создадим -файл описания диалогового окна с тремя кнопками Button и одной кнопкой Cancel. Каждая из трех кнопок должна выдать послание при нажатии.
Расположите кнопки в колонку друг под другом в две группы:
But:dialog {label="Работа с кнопками Button";
:column{:boxed_column {
:button {key="but1";label="Button1";is_default="false";}
:button {key="but2";label="Button2";is_default="false";}
:button {key="but3";label="Button3";is_default="false";}
}
:boxed_row{ok_cancel; }
}
}
Сохраните файл как But. в папке …\Support.
А теперь составьте файл But. для загрузки -файла и описания сценария отклика на события в диалоговом окне. Он будет состоять из двух функций:
(defun C:But1()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "But.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "But" dcl_id))
(progn
(alert "The But.dcl file could not be loaded!")(exit)
)
)
;;;--- If an action event occurs, do this function
(action_tile "but1" "(doButton 1)")
(action_tile "but2" "(doButton 2)")
(action_tile "but3" "(doButton 3)")
(action_tile "cancel" "(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- Suppress the last echo for a clean exit
(princ)
)
(defun doButton(a)
(cond
((= a 1)(alert "Button 1 was pressed!"))
((= a 2)(alert "Button 2 was pressed!"))
((= a 3)(alert "Button 3 was pressed!"))
)
)
На экране должна быть картинка, подобная рис. 6.4.
(рис 6.4) Диалоговое окно с кнопками
Составьте файл List. с описанием диалогового окна с двумя списками в верхнем ряду и кнопкой ОК и Cancel в нижнем ряду. Сохраните его в папке …\Support.
list: dialog {label = "Работа со списками list_box";
: column {
: boxed_row {: text { key = "text1"; value = "Nothing selected"; }}
: boxed_row {
: list_box {key = "mylist1"; label ="Choose Item"; height = 9; width = 8; multiple_select = false; fixed_width_font = true;
list="Лимон\nЛист\nНебо\nСажа\nСнег\nЯблоко";}
: boxed_row {
: popup_list { key = "mylist2"; label ="Choose Color"; width = 8; multiple_select = false;
fixed_width_font = true; list="red\nyellow\ngreen\ncyan\nwhite\nblack";}}}
: boxed_row {
: button { key = "accept"; label = "Okey "; is_default = true; }
: button { key = "cancel";label = "Cancel "; is_default = false; is_cancel = true; }}
}
}
Заполнение спискoв здесь произведено с помощью атрибута list. Однако, если бы мы написали атрибуты value = "";, то списки были бы пустыми. В этом случае они заполняются при запуске файла List. так, как это показано ниже.
Составьте теперь загрузочный файл List.. Строки, относящиеся к загрузке списков, закомментированы. Если списки уже заполнены, то эти строки можно удалить. Если их раскомментировать, то старое содержимое в списках будет удалено, а новые записи установлены.
(defun C:list () ;;; (setq myList1(list "Лимон" "Лист" "Небо" " Сажа" "Снег" "Яблоко")) ;;; (setq myList2(list "red" "yellow" "green" "cyan" "white" "black")) ;;;--- Load the dcl file (setq dcl_id (load_dialog "list.dcl")) ;;;--- Load the dialog definition if it is not already loaded (if (not (new_dialog "list" dcl_id)) (progn (alert "The List.DCL file could not be loaded!") (exit) ) ) ;;; (start_list "mylist1" 3) ;;; (mapcar 'add_list myList1) ;;; (end_list) ;;; (start_list "mylist2" 3) ;;; (mapcar 'add_list myList2) ;;; (end_list) ;;;--- If an action event occurs, do this function (action_tile "mylist2" "(saveVars)") (action_tile "accept" "(setq ddiag 2)(done_dialog)") (action_tile "cancel" "(setq ddiag 1)(done_dialog)") ;;;--- Display the dialog box (start_dialog) ;;;--- Unload the dialog box (unload_dialog dcl_id) ;;;--- If the user pressed the Cancel button (if(= ddiag 1) (princ "\n List cancelled!") ) ;;;--- If the user pressed the Okay button (if(= ddiag 2) (progn (princ "\n The user pressed Okay!") ) ) (princ)) (defun saveVars () (setq numstrlist (atoi (get_tile "mylist1"))) (princ numstrlist) (setq word_list (cond ((= numstrlist 0) "Лимон") ((= numstrlist 1) "Лист") ((= numstrlist 2) "Небо") ((= numstrlist 3) "Сажа") ((= numstrlist 4) "Снег") ((= numstrlist 5) "Яблоко") (Т "") ) ;_конец cond ) ;_ конец setq (setq numstrpop (atoi (get_tile "mylist2"))) (princ numstrpop) (setq word_pop (cond ((= numstrpop 0) "red") ((= numstrpop 1) "yellow") ((= numstrpop 2) "green") ((= numstrpop 3) "cyan") ((= numstrpop 4) "white") ((= numstrpop 5) "black") (Т "") ) ;_конец cond ) ;_ конец setq (setq myStr (strcat word_list " имеет цвет " word_pop)) (set_tile "text1" myStr) )
В этот же файл занесена функция saveVars, которая определяет отклики на события диалогового окна. Событие состоит в выборе слова в левом списке и слова в правом списке. Оба выбранных слова занесем в строку text по щелчку в правом списке. Если щелкнуть по кнопке ОК, то окно закроется.
При чтении значения списка функция get_tile возвращает номер строки, которые нумеруются с нуля. Поэтому далее нужно в цикле или с помощью функции cond найти соответствие между номером строки и значением элемента.
Диалоговое окно списков показано на рис. 6.5. Выбранная запись отражена в нередактируемом текстовом поле text в верхней части окна.
(рис 6.5) Окно с двумя списками
Составьте программу построения диалогового окна с колонкой флажков. Сохраните файл как …\Support\
Toggle: dialog { label = "Работа с элементами toggle";
: column {: boxed_row {
: text { key = "text1"; value = "Nothing selected"; }}
: boxed_column { label = "Choose your lucky charms:";
: toggle { key = "tog1";label = "Hearts"; value = "0";}
: toggle { key = "tog2";label = "Moons"; value = "0";}
: toggle { key = "tog3";label = "Stars"; value = "0";}
: toggle { key = "tog4";label = "Clovers";value = "0";}
}
: boxed_row {
: button { key = "accept"; label = "Okey "; is_default = true; }
: button { key = "cancel";label = "Cancel "; is_default = false; is_cancel = true; }}
}}
Теперь составьте файл загрузки и обработки . В этом файле создано две функции: chkToggle и :
(defun chkToggle() (setq tog1(atoi(get_tile "tog1"))) // 0 = not chosen 1 = chosen (setq tog2(atoi(get_tile "tog2"))) // 0 = not chosen 1 = chosen (setq tog3(atoi(get_tile "tog3"))) // 0 = not chosen 1 = chosen (setq tog4(atoi(get_tile "tog4"))) // 0 = not chosen 1 = chosen (setq myStr "") (if(= tog1 1)(setq myStr(strcat myStr " Hearts"))) (if(= tog2 1)(setq myStr(strcat myStr " Moons"))) (if(= tog3 1)(setq myStr(strcat myStr " Stars"))) (if(= tog4 1)(setq myStr(strcat myStr " Clovers"))) ;;;--- If nothing was selected... (if(= myStr "")(setq myStr "Nothing Selected!")) ;;;--- Now set the text control to display the string (set_tile "text1" myStr) ) (defun C:Toggle() ;;;--- Load the dcl file (setq dcl_id (load_dialog "Toggle.dcl")) ;;;--- Load the dialog definition if it is not already loaded (if (not (new_dialog "Toggle" dcl_id) ) (exit)) ;;;--- If an action event occurs, do this function (action_tile "tog1" "(chkToggle)") (action_tile "tog2" "(chkToggle)") (action_tile "tog3" "(chkToggle)") (action_tile "tog4" "(chkToggle)") (action_tile "cancel" "(done_dialog)") ;;;--- Display the dialog box (start_dialog) ;;;--- Unload the dialog box (unload_dialog dcl_id) ;;;--- Suppress the last echo for a clean exit (princ))
Ha экране диалоговое окно выглядит так, как на рис. 6.6.
(рис 6.6) Диалоговое окно с флажками
Постройте диалоговое окно с четырьмя переключателями. Из всей группы только один из переключателей может быть выделен. Он должен быть определен при нажатии кнопки ОК.
Составьте -файл для колонки из четырех переключателей. Внизу окна поместите кнопки OK и Cancel. Сохраните файл как С:\Program Files\AutoCAD 2010\Support\Radio.. Файл можно сохранить и в другом каталоге. Тогда загрузить его в чертеж нужно по команде Tools - . Загрузить можно и непосредственно из среды Visual LISP.
Radio : dialog {label = "Переключатели RadioButtons";
: column {
: radio_column {key = "mychoice";
: radio_button {key = "but1"; label = "Apples"; value =1;}
: radio_button {key = "but2"; label = "Oranges";}
: radio_button {key = "but3"; label = "Bananas";}
: radio_button {key = "but4"; label = "Lemons";}
}
: boxed_column {
: button {key = "accept";label = " Okey ";is_default = true;}
: button {key = "cancel";label = " Cancel ";is_default = false;is_cancel = true;}
}}}
Далее создайте -файл загрузки:
(defun C:Radio()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "Radio.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "Radio" dcl_id))
(progn
(alert "The Radio.DCL file could not be loaded!")
(exit)
)
)
;;;--- If an action event occurs, do this function
(action_tile "accept" "(setq ddiag 2)(saveVars)(done_dialog)")
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the user pressed the Cancel button
(if(= ddiag 1)
(princ "\n Radio cancelled!")
)
;;;--- If the user pressed the Okay button
(if(= ddiag 2)
(progn
(princ "\n The user pressed Okay!")
)
)
;;;--- Suppress the last echo for a clean exit
(princ)
)
Загрузите файлы и запустите команду "Radio". На экране появится диалоговое окно, в котором работают лишь кнопки OK и Cancel (рис.6.7):
(рис 6.7) Макет диалогового окна "Radio Buttons"
При нажатии кнопки ОК вызывается функция saveVars, которая запускает сценарий отклика на событие выделения переключателя. Составим эту функцию и поместим ее в -файл:
(defun saveVars()
;;;--- Get the key of the choice made
;;; [ returns "but1" "but2" "but3" or "but4" whichever is selected.]
(setq myChoice(get_tile "mychoice"))
;;;--- Get the value of each item
(setq choice1(atoi(get_tile "but1"))) // 0 = not chosen 1 = chosen
(setq choice2(atoi(get_tile "but2"))) // 0 = not chosen 1 = chosen
(setq choice3(atoi(get_tile "but3"))) // 0 = not chosen 1 = chosen
(setq choice4(atoi(get_tile "but4"))) // 0 = not chosen 1 = chosen
)
(defun C:Radio()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "Radio.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "Radio" dcl_id))
(progn
(alert "The Radio.DCL file could not be loaded!")
(exit)
) )
;;;--- If an action event occurs, do this function
(action_tile "accept" "(setq ddiag 2)(saveVars)(done_dialog)")
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the user pressed the Cancel button
(if(= ddiag 1)
(princ "\n Radio cancelled!")
)
;;;--- If the user pressed the Okey button
(if(= ddiag 2)
(progn
;;;--- Inform the user of his selection using the radio_column data
(princ "\n Using Radio_column data...You chose ")
(cond
((= myChoice "but1")(princ "Apples!"))
((= myChoice "but2")(princ "Oranges!"))
((= myChoice "but3")(princ "Bananas!"))
((= myChoice "but4")(princ "Lemons!"))
)
;;;--- Inform the user of his selection using the radio_buttons data
(princ "\n Using Radio_buttons data...You chose ")
(cond
((= Choice1 1)(princ "Apples!"))
((= Choice2 1)(princ "Oranges!"))
((= Choice3 1)(princ "Bananas!"))
((= Choice4 1)(princ "Lemons!"))
) ) )
;;;--- Suppress the last echo for a clean exit
(princ))
Сейчас попробуем соединить все изложенные выше отдельные сведения о программировании диалоговых окон. Необходимо построить такой -файл, который позволил бы управлять большинством параметров чертежа.
Нарисуем многоугольник или окружность на выбранном нами слое. Выбранные нами опции должны быть сохранены как опции по умолчанию при следующем открытии программы. Если выбран многоугольник, нужно выбрать число сторон в popup_list. Список слоев должен быть помещен в list_box. Выбор фигуры должен производиться радиокнопкой radio_column. В элементе нужно поставить флажки "Save Settings" сохранения опций. Наконец, нам будут нужны кнопки ОК и Cancel.
Список слоев, возможно, будет большим, - для него нужно отвести одну высокую колонку. Остальные элементы следует разместить во вторую колонку. В нижнем ряду будут помещены кнопки ОК и Cancel.
Скопируйте коды элементов из вышележащих материалов лекции.
SAMPLE : dialog {
label = "Sample Dialog Box";
: column {
: row {
: boxed_column {
: radio_column {key = "radios";
: radio_button {label = "Draw Circle";key = "drawcir"; value = "1";}
: radio_button {label = "Draw Polygon"; key = "drawpol"; value = "0";}
}
: popup_list {key = "numsides"; label = "Number of Sides"; width = 25; fixed_width_font = true;}
: toggle {key = "saveset"; label = "Save settings";}
}
: row {
: list_box {label ="Select Layer";key = "layerList";height = 12; width = 10;
multiple_select = false; fixed_width_font = true;value = "";}
}}
: row {
: button {key = "accept";label = " Okey "; is_default = true;}
: button {key = "cancel";label = " Cancel ";is_default = false;is_cancel = true;}
}}}
Сохраните файл как C:\Program Files\AutoCAD 2007\Support\Sample..
Скопируйте далее -файл загрузки и обработки:
(defun C:SAMPLE ()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "SAMPLE.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "SAMPLE" dcl_id))
(progn
(alert "The SAMPLE.DCL file could not be loaded!")
(exit)
)
)
;;;--- If an action event occurs, do this function
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
(action_tile "accept" "(setq ddiag 2)(saveVars)(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the cancel button was pressed - display message
(if (= ddiag 1)
(princ "\n \n ...SAMPLE Cancelled. \n ")
)
;;;--- If the "Okay" button was pressed
(if (= ddiag 2)
(princ "\n \n ...SAMPLE Complete!")
)
;;;--- Suppress the last echo for a clean exit
(princ)
)
Сохраните файл как C:\Program Files\AutoCAD 2007\Support\Sample..
Загрузите файлы и запустите функция Sample. На экране должно появиться диалоговое окно (рис. 6.8)
(рис 6.8) Предварительное построение диалогового окна
Обратите внимание, что списки отсутствуют, а переключатель Draw Circle выделен (значение value=1). В элементе флажок не установлен, так как не задано значение value. Если нажать кнопку Cancel, то окно закроется. Если же нажать кнопку ОК, то будет выдано сообщение об ошибке: функция saveVars не определена.
Прежде всего составим списки числа сторон многоугольника и добавим их к элементу popup_list. Далее составим список слоев и заполним элемент list_box.
Вместо того, чтобы создавать функцию, которая получала бы все имена слоев чертежа, можно просто составить список вручную. Первый путь длиннее, но он более строгий.
Чтение имен слоев чертежа:
;;;--- Set up a list to hold the layer names
(setq layerList(list))
;;;--- Get the first layer name in the drawing
(setq layer(tblnext "LAYER" T))
;;;--- Add the layer name to the list
(setq layerList(append layerList (list(cdr(assoc 2 layer)))))
;;;--- Step though the layer table to get all layers
(while (setq layer(tblnext "LAYER"))
;;;--- Save each layer name in the list
(setq layerList(append layerList (list(cdr(assoc 2 layer)))))
)
Составление списка вручную:
(setq layerList(list "0" "Layer1" " Layer2" " Layer3" " Layer4" " Layer5" "Layer6" " Layer7" " Layer8" " Layer9"))
То же самое для числа сторон многоугольника:
(setq numSides(list "4" "6" "8" "12" "16"))
Добавим эти строки в описание диалога -файла.
;;;--- Add the layer names to the dialog box (start_list "layerlist" 3) (mapcar 'add_list layerList) (end_list) ;;;--- Add the number of sides to the dialog box (start_list "numsides" 3) (mapcar 'add_list numSides) (end_list)
После этого добавление основная LISP-программа должна выглядеть так:
(defun C:SAMPLE ()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "SAMPLE.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "SAMPLE" dcl_id))
(progn
(alert "The SAMPLE.DCL file could not be loaded!")
(exit)
)
)
(setq layerList(list "0" "Layer1" " Layer2" " Layer3" " Layer4" " Layer5" "Layer6" " Layer7" " Layer8" " Layer9"))
(setq numSides(list "4" "6" "8" "12" "16"))
;;;--- Add the layer names to the dialog box
(start_list "layerList" 3)
(mapcar 'add_list layerList)
(end_list)
;;;--- Add the number of sides to the dialog box
(start_list "numsides" 3)
(mapcar 'add_list numSides)
(end_list)
;;;--- If an action event occurs, do this function
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
(action_tile "accept" "(setq ddiag 2)(saveVars)(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the cancel button was pressed - display message
(if (= ddiag 1)
(princ "\n \n ...SAMPLE Cancelled. \n ")
)
;;;--- If the "Okay" button was pressed
(if (= ddiag 2)
(princ "\n \n ...SAMPLE Complete!")
)
;;;--- Suppress the last echo for a clean exit
(princ)
)
Сохраните файлы, загрузите их и запустите команду Sample. На экране должно появиться диалоговое окно со списками (рис. 6.9):
(рис 6.9) Диалоговое окно со списками
Создадим сценарий отклика на события в окне в описании функции SaveVars LISP-файла. При выборе строки в списке функция чтения get_tile возвращает номер строки как строковую константу. На время отладки программы введем распечатки полученных значений переменных. В дальнейшем эти распечатки нужно убрать.
(defun saveVars() (setq radios(get_tile "radios")) ;;;--- Get the number of sides selected from the list (setq numStr(get_tile "numsides")) (if(= numStr "") (setq numSides nil) (setq numSides(nth (atoi numStr) numSides)) ) (princ numSides) (terpri) ;;;--- See if the user wants to save the settings (setq saveSet(atoi(get_tile "saveset"))) (princ saveSet) (terpri) ;;;--- Get the selected item from the layer list (setq sStr(get_tile "layerList")) ;;;--- If the index of the selected item is not "" then something was selected (if(/= sStr "") (progn ;;;--- Something is selected, so convert from string to integer (setq sIndex(atoi sStr)) ;;;--- And get the selected item from the list (setq layerName(nth sIndex layerList)) ) ;;;--- Else, nothing is selected (progn ;;;--- Set the index number to -1 (setq sIndex -1) ;;;--- And set the name of the selected item to nil (setq layerName nil) ) ) (princ layerName) (terpri) )
Если не выделить имя слоя в элементе list_box, то значение его будет nil. Иначе будет выдан примерно такой результат:
Command: sample 6 1 sStr5 sindex5 layerNameLayer5 ...SAMPLE Complete!
При вычерчивании окружности нужно сделать неработающим элемент "Number of Sides" popup_list. Для этого нужно запрограммировать события с радиокнопками таким образом:
;;;--- If an action event occurs, do this function (action_tile "drawcir" "( 1)") (action_tile "drawpol" "(toggleRadio 2)")
При выборе элемента drawcir вызывается функция toggleRadio 1, а при выборе элемента drawpol вызывается функция toggleRadio 2.
Создадим такую функцию с параметром (a) в -программе:
(defun toggleRadio(a) ;if circle is selected (if(= a 1) (mode_tile "numsides" 1) ;disable ;else (mode_tile "numsides" 0) ;enable ) )
По умолчанию в программе должна рисоваться окружность. Поэтому перед выражениями с функциями action_tile нужно добавить строку
(mode_tile "numsides" 1)
Таким образом, когда выделяем кнопку, чтобы нарисовать окружность, numSides popup_list недоступен. Когда же мы собираемся рисовать многоугольник, то элемент установки число сторон становится доступным.
А теперь можно изменить слой:
(setq oldLay(getvar "clayer")) (setvar "clayer" layerName)
Напишем также команды построения окружности и многоугольника
(if(= radios "drawcir") (progn (setq pt(getpoint "\n Center point: ")) (command "circle" pt pause) ) ;;;--- Else draw a polygon (progn (setq pt(getpoint "\n Center Point: ")) (command "polygon" numSides pt "C" pause) ) )
LISP-файл будет выглядеть следующим образом:
(defun C:SAMPLE ()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "Sample.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "sample" dcl_id))
(progn
(alert "The SAMPLE.DCL file could not be loaded!")
(exit)
)
)
(setq layerList (list "0" "Layer1" "Layer2" "Layer3"
"Layer4" "Layer5" "Layer6" " Layer7"
"Layer8" "Layer9"
)
)
(setq numSides (list "4" "6" "8" "12" "16"))
;;;--- Add the layer names to the dialog box
(start_list "layerList" 3)
(mapcar 'add_list layerList)
(end_list)
;;;--- Add the number of sides to the dialog box
(start_list "numsides" 3)
(mapcar 'add_list numSides)
(end_list)
(mode_tile "numsides" 1)
;;;--- If an action event occurs, do this function
(action_tile "drawcir" "(toggleRadio 1)")
(action_tile "drawpol" "(toggleRadio 2)")
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
(action_tile
"accept"
"(setq ddiag 2)(saveVars)(done_dialog)"
)
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the cancel button was pressed - display message
(if (= ddiag 1)
(princ "\n \n ...SAMPLE Cancelled. \n ")
)
;;;--- If the "Okay" button was pressed
(if (= ddiag 2)
(princ "\n \n ...SAMPLE Complete!")
)
;;;--- Suppress the last echo for a clean exit
(princ)
(if(= radios "drawcir")
(progn
(setq pt(getpoint "\n Center point: "))
(command "circle" pt pause)
)
;;;--- Else draw a polygon
(progn
(setq pt(getpoint "\n Center Point: "))
(command "polygon" numSides pt "" pause)
)))
(defun saveVars ()
(setq radios (get_tile "radios"))
;;;--- Get the number of sides selected from the list
(setq numStr (get_tile "numsides"))
(if (= numStr "")
(setq numSides nil)
(setq numSides (nth (atoi numStr) numSides))
)
(princ numSides)
(terpri)
;;;--- See if the user wants to save the settings
(setq saveSet (atoi (get_tile "saveset")))
(princ saveSet)
(terpri)
;;;--- Get the selected item from the layer list
(setq sStr (get_tile "layerList"))
(princ "sStr")
(princ sStr)
(terpri)
;;;--- If the index of the selected item is not "" then something was selected
(if (/= sStr "")
(progn
;;;--- Something is selected, so convert from string to integer
(setq sIndex (atoi sStr))
(princ "sindex")
(princ sIndex)
(terpri)
;;;--- And get the selected item from the list
(setq layerName (nth sIndex layerList))
(princ "layerName")
(princ layerName)
(terpri)
)
;;;--- Else, nothing is selected
(progn
;;;--- Set the index number to -1
(setq sIndex -1)
;;;--- And set the name of the selected item to nil
(setq layerName nil)
) )
(setq oldLay(getvar "clayer"))
(setvar "clayer" layerName)
)
(defun toggleRadio(a)
;if circle is selected
(if(= a 1)
(mode_tile "numsides" 1) ;disable
;else
(mode_tile "numsides" 0) ;enable
)
)
И наконец, займемся кодом сохранения установок по умолчанию. В элементах диалога все значения переменных интерпретируются как строки. В AutoCAD поддерживается 15 пользовательских системных переменных сохранения данных. USERR1 - USERR5 используют действительные числа. USERI1 - USERI5 используют целые числа. USERS1 - USERS5 будут сохранять наши данные как строки. Все эти величины доступны в файле чертежа каждый раз при его открытии.
Первой переменной у нас появляется RADIOS, и она уже имеет строковый тип (setvar "USERS1" radios).
Второй переменной является NUMSIDES - целое число сторон многоугольника. Но при чтении значения (value) элемента нам возвращается номер строки типа string: (setvar "USERS2" numStr).
Третья переменная SAVESET имеет тип integer. Поэтому ее нужно конвертировать (setvar "USERS3" (itoa saveSet)) .
Индекс четвертой переменной LAYERNAME сохраним в виде строки:
(setvar "USERS4" sSTR)
Язык DCL (Dialog Control Language) - специальный язык для создания диалоговых окон.
Директива - логически законченная единица программы диалога.
Элементы управления - части интерфейса диалогового окна, к которым имеет доступ пользователь (кнопки, текстовые поля, списки и пр.).
Функции DCL - встроенные функции языка для проведения действий и операций.
Переменные действия - глобальные переменные, в которых сохраняются некоторые дополнительные данные о состоянии диалогового окна и выполненных в нем действий пользователя. Переменные используются в LISP-выражениях, задаваемых в качестве второго аргумента функции action-tile.
Программы вычерчивания фигур должны иметь возможность изменять значения переменных. Это можно сделать либо в коде, либо по запросам в командной строке в процессе выполнения программы. Но удобнее всего выполнять установки в специальных диалоговых окнах. Технология создания таких окон с помощью языка описана в данной лекции.
DCL -файлы?LISP-файлом?dcl -файла load_dialog?action_tile?list_box и popup_list?LISP-программы, которая запускает сценарий отклика на событие выделения радиокнопки в диалоговом окне.Цель лекции: приобрести навыки работы в построении диалоговых окон.
Рассмотрим пример программы вычерчивания полого рога с углом изгиба 180 градусов.
(defun c:qrog (/ cenrt1 rad1 diam1 circle1 arc1 rog1 thick1 angle1 endp1 col1) (setq centr1 '(0 0 0)) ; исходная базовая точка (setq rad1 (getreal "Задайте радиус базовой окружности: ")); радиус рога (80) (setq diam1 (getreal "Задайте диаметр направляющей дуги: ")); диаметр изгиба рога (400) (setq thick1 (getreal "Задайте толщину стенки рога: ")); толщина стенки в мм (2) (setq col1 (getint "Задайте индекс цвета: ")); выбор: 0,1,2,3,4,5,6 (setq angle1 (* 55.0 (atan rad1 (* diam1 (/ pi 2))))); угол изгиба рога (command "_view" "_top") ;начинаем со стандартного вида; устанавливаем вид сверху (command "_view" "_swiso"); переходим к северо-западному виду (command "_circle" centr1 rad1 ""); строим базовую окружность (setq circle1 (entlast)); извлекаем имя сущности для базовой окружности (command "_ucs" "_x" "90" ""); поворачиваем ПСК (setq endp1 (list diam1 0.0)); задаем конечную точку дуги (command "_arc" centr1 "e" endp1 "a" "-180" ""); строим дугу изгиба (setq arc1 (entlast)); извлекаем имя сущности для дуги и сохраняем его (command "_ucs" "_x" "-90"); совмещаем плоскость окружности с плоскостью XY (command "extrude" circle1 "" "t" angle1 "p" arc1 ""); строим тело рога (setq rog1 (entlast)); извлекаем имя сущности для рога и сохраняем его (command "_zoom" "e" ""); растягиваем изображение на весь экран (command "_vscurrent" "_r" ""); устанавливаем текущий визуальный стиль - realistic (command "_chprop" "_all" "" "_color" col1 ""); закрашиваем заданным цветом (command "_view" "_bottom" ""); устанавливаем вид снизу (command "_solidedit" "_body" "_shell" rog1 centr1 "" thick1 "" ""); удаляем внутренность рога (command "_erase" arc1 ""); удаляем образующую дугу (princ); тихий выход из программы )
Внешний вид рога показан на рис. 6.1.
(рис 6.1) Рисунок рога
Рог строился путем Shell.
При запуске функции qrog пользователь задавал требуемые параметры по запросам программы:
rad1;diam1;thick1;col1.Требуется вместо запросов создать диалоговое окно для одновременного ввода этих параметров.
Вначале напишем отдельную программу для открытия диалогового окна. В новом чертеже AutoCAD откройте среду Visual LISP по команде Tools - . По команде File - New File создайте новый файл. Наберите в нем следующий текст программы диалога "rog" на языке . Учтите только, что элементы языка чувствительны к регистру. Все ключевые слова, метки и коды элементов должны состоять только из латинских букв, цифр и символа подчеркивания. Начинаться служебные слова должны с латинской буквы.
//Диалоговое окно установки параметров рога
//
rog: dialog{label="Установка параметров рога";
:edit_box{label="Радиус окружности ";key="rad" ;value="0.00"; edit_width=8;}
:edit_box{label="Диаметр дуги, мм";key="diam";value="0.00";edit_width=8;}
:edit_box{label="Толщина стенки, мм";key="thick";value="0.00";edit_width=6;}
:spacer{height=1;}
:edit_box{label="Индекс цвета";key="col";value="0";edit_width=4;}
:spacer{height=1;}
ok_cancel;
}
Сохраните написанное в файле C:\Program Files\AutoCAD2007\Support\Rog.. Папка Support принадлежит к маршрутам файлов поддержки. Проверьте это еще раз, выполнив команду Tools - Options - Files - Support File . Чтобы открыть диалоговое окно на экране, система должна загрузить -файл. Эта загрузка может быть выполнена лишь тогда, когда -файл помещен в данную папку. Иначе нужно указывать полный путь к файлу.
Вся написанная программа называется диалогом. В одном файле может быть несколько диалогов. Рассмотрим структуру программы-диалога.
За двойной чертой // до конца строки размещается комментарий. В нашей программе комментарий занимает первые две строки. Далее программа содержит логически законченные единицы - директивы. Каждая директива описывает один элемент (tile) или способ группировки элементов внутри диалогового окна. Директива должна заканчиваться фигурной скобкой или точкой с запятой. Количество открывающих скобок должно быть равно количеству закрывающих скобок. При описании элементов разделителем служит точка с запятой. Текстовые строки должны быть заключены в кавычки. Между ключевыми словами языка, разделительными символами, метками, числовыми и строковыми значениями может быть любое количество пробелов.
Директивы могут записываться в двух видах:
[<метка>]:<оператор>{<атрибуты>}
<метка>;
Здесь квадратные скобки обозначают необязательность размещенного внутри них элемента. Фигурные скобки и двоеточия являются обычными символами. Метка - идентификатор директивы. Она должна быть уникальной в данном файле.
В листинге программы мы сразу можем выделить директиву описания диалога в целом:
rog: dialog {label="Установка параметров рога";
…
ok_cancel;
}
rog - это метка, имя диалога;
dialog - это оператор, он вызывает свою подпрограмму, выполняющую действия;
label="…"; - эта надпись будет заголовком диалогового окна;
ok_cancel - внизу окна будут размещены кнопки ОК и CANCEL (Отмена).
Внутри директивы dialog размещены четыре однотипные директивы, имеющие следующий вид:
:edit_box{label="Радиус окружности "; key="rad"; value="0.00"; edit_width=8;}
Элементы этих директив описывают следующие понятия:
edit_box - оператор редактируемого текстового поля;label="…"; - эта надпись будет размещена перед текстовым полем;key="rad"; - код диалога;value="0.00"; - значение, которое содержит текстовое поле по умолчанию;edit_width=8; - ширина окна текстового поля в символах шрифта.В листинге программы имеются еще две одинаковые директивы
:spacer{height=1;}
- это пустой элемент, обозначающий пропуск строки;
height=1; - атрибут height показывает высоту пропущенной строки. Единицей измерения является стандартная высота строки текущего шрифта.
Итак, в сохраненном файле "Rog." описано диалоговое окно с именем диалога "rog". Окно должно иметь четыре текстовых поля с видимыми в них значениями по умолчанию.
Составим теперь LISP-функцию, которая позволяла бы загружать (load_dialog) и выгружать (unload_dialog) -файлы, открывать и закрывать окна загруженных диалогов. В редакторе Visual LISP создайте новый файл и наберите в нем следующий текст:
(defun c:show_rog ( / num) (if (< (setq num (load_dialog "rog.dcl")) 0)(exit)) (if (not (new_dialog "rog" num)) (exit)) (start_dialog) (unload_dialog num) (princ) );defun
В первой строке определена функция show_rog c локальной переменной num. В переменной num сохраняется внутренний номер открываемого диалогового окна. Обычно он присваивается всем вновь открываемым диалогам по порядку, начиная с единицы.
Во второй строке записана команда (load_dialog "rog.), загружающая файл rog.. Если полный адрес файла не указан, то система ищет этот файл по стандартному алгоритму поиска файлов поддержки. Если загрузка прошла успешно, то функция load_dialog возвращает положительное целое число, которое присваивается переменной num. Если загрузка не выполнилась, то возвращается отрицательное число. В этом случае выполняется функция exit, прерывающая работу приложения.
В третьей строке проверяется, имеется ли в загруженном -файле rog. диалог с именем "rog", имеющий номер num. Если такого диалога в файле нет, то программа завершается с помощью функции exit. Если такой диалог есть, то активируется диалоговое окно, управление передается функции start_dialog. Эта функция возвращает 1, если пользователь выйдет из диалогового окна с помощью кнопки OK или 0, если пользователь выйдет из диалогового окна с помощью кнопки Cancel.
В пятой строке функция unload_dialog num выгружает файл из оперативной памяти. Возвращаемое значение - nil.
Загрузите файл, перейдите в AutoCAD и наберите в командной строке show_rog. На экране появится диалоговое окно (рис. 6.2).
(рис 6.2) Диалоговое окно
Установите параметры в текстовых полях. Щелкните по кнопке ОК. Окно исчезнет с экрана. Файл rog. выгрузится из оперативной памяти. Чтобы воспользоваться результатами работы с окном, нужна программа, анализирующая введенные величины.
Исключим из программы черчения рога приглашения задать параметры рога и включим обращение к диалогу "rog". На время наладки программы введем печать четырех параметров в отдельных строках.
(defun c:qrog (/ cenrt1 rad1 diam1 circle1 arc1 rog1 thick1 angle1 endp1 col1) (setq centr1 '(0 0 0)) ; исходная базовая точка (if (< (setq num (load_dialog "rog.dcl")) 0) (exit)); загружаем в память файл "rog.dcl" (if (not (new_dialog "rog" num)) (exit)) ;;функция new_dialog проверяет наличие в файле диалога "rog" (action_tile "rad" "(setq rad1 (atof $value))"); присваиваем значение переменной rad1 (terpri); перевод строки (princ rad1); выводим на экран значение переменной rad1 (action_tile "diam" "(setq diam1 (atof $value))"); присваиваем значение переменной diam1 (terpri); перевод строки (princ diam1); выводим на экран значение переменной diam1 (action_tile "thick" "(setq thick1 (atof $value))"); присваиваем значение переменной thick1 (terpri); перевод строки (princ thick1); выводим на экран значение переменной thick1 (action_tile "col" "(setq col1 $value)"); присваиваем значение переменной col1 (terpri) ; перевод строки (princ col1); выводим на экран значение переменной col1 (terpri); перевод строки (start_dialog); возвращает 1 или 0 (unload_dialog num); выгружает окно из памяти (setq angle1 (* 55.0 (atan rad1 (* diam1 (/ pi 2))))); находим угол сужения тела рога (command "_view" "_top") ; начинаем со стандартного вида сверху (command "_view" "_swiso"); переходим к северо-западному виду (command "_circle" centr1 rad1 "") ; строим базовую окружность (setq circle1 (entlast)); извлекаем имя сущности для базовой окружности (command "_ucs" "_x" "90" ""); поворачиваем ПСК (setq endp1 (list diam1 0.0)); находим координаты конечной точки дуги (command "_arc" centr1 "e" endp1 "a" "-180" ""); строим образующую дугу (setq arc1 (entlast)); извлекаем имя сущности для дуги и сохраняем его (command "_ucs" "_x" "-90"); совмещаем плоскость окружности с плоскостью XY (command "extrude" circle1 "" "t" angle1 "p" arc1 ""); создаем тело рога (setq rog1 (entlast)); извлекаем имя сущности для рога и сохраняем его (command "_zoom" "e" ""); растягиваем изображение на весь экран (command "_vscurrent" "_r" "") устанавливаем текущий визуальный стиль realistic (command "_chprop" "_all" "" "_color" col1 ""); закрашиваем цветом col1 (command "_view" "_bottom" ""); устанавливаем вид снизу (command "_solidedit" "_body" "_shell" rog1 centr1 "" thick1 "" ""); делаем в теле рога полость (command "_erase" arc1 ""); удаляем образующую дугу (princ); тихий выход )
Для обработки данных, вводимых в текстовых полях диалогового окна, применена функция action_tile. Она помещена между функциями new_dialog и start_dialog. Функция имеет следующий синтаксис:
(action_tile <код> <выражение>)
<код> - это строка с кодом элемента;
<выражение> - строка с LISP-выражением действия, выполняемого при выборе данного элемента;
Возвращаемое значение Т.
Функция action_tile присваивает значения текстовых полей переменным функции qrog. Текстовые поля различаются по кодам этих полей. Значения полей сохраняются в глобальной переменной $value. Тип сохраненных величин - строковые константы. Чтобы обеспечить возможность дальнейших расчетов, применено преобразование строковых констант в вещественные числа с помощью функции atof.
Технология создания диалоговых окон изложена в предыдущем разделе. Сейчас разберем более подробно отдельные элементы и синтаксис языка с использованием LISP-программ.
Директива описания диалога задает имя, по которому диалоговое окно вызывается из программы на экран. Директива использует ключевое слово dialog:
<имя>:dialog{<атрибуты><элементы>}
В качестве имени диалога может быть использован любой идентификатор, не совпадающий со служебными словами. Имена диалогов в одном сеансе AutoCAD не должны повторяться. Параметр >атрибуты< - это последовательность разделяемых точкой с запятой операций задания атрибутам значений:
<атрибут1>=<значение1>;<атрибут2>=<значение2>;…
Параметр <элементы> является набором директив описания элементов (текстовых полей, кнопок, списков, надписей, флажков и пр.).
Имена атрибутов и элементов должны быть стандартными ключевыми словами. Значения атрибутов могут быть числами или строками, - в зависимости от атрибута. Если директива описывает элемент диалогового окна, то параметр <атрибуты> - это описание атрибутов элемента и их значений, отличных от значений по умолчанию. Если директива является директивой группировки элементов, то она содержит внутри фигурных скобок директивы определения группируемых элементов.
Атрибуты диалога - это различные характеристики окна в целом или его отдельных элементов. В таблице приведены ключевые слова, которые могут быть использованы в качестве атрибутов в директиве описания диалога.
| Атрибут | Описание | Допустимые значения | Значение по умолчанию |
|---|---|---|---|
Label |
Начальный текст заголовка диалогового окна | Строка | " " (пробел) |
Value |
Текущий текст заголовка диалогового окна | Строка | Нет |
Key |
Код диалога | Строка | Нет |
Width |
Ширина окна | Число | Нет |
Height |
Высота окна | Число | Нет |
initial_focus |
Код подсвеченного элемента в диалоговом окне | Строка | Нет |
children_alignment |
Способ выравнивания подчиненных элементов по умолчанию | left, right, centered (для колонок), top, bottom, centered (для рядов) |
left (для колонок), centered (для рядов) |
children_fixed_width |
Фиксация ширины подчиненных элементов по умолчанию | true, false |
false |
children_fixed_height |
Фиксация высоты подчиненных элементов по умолчанию | true, false |
false |
Атрибуты label и value близки по смыслу. Различие между ними состоит в том, что атрибут label влияет на размер окна, а значение атрибута value - не влияет. Атрибут key обеспечивает возможность изменить программно заголовок выводимого диалогового окна. В качестве значения кода диалога могут использоваться только строки.
Атрибут width задает минимальную ширину окна в условных символах. Ширина символа равна средней ширине символа латинского алфавита шрифта по умолчанию. Ширина окна вычисляется системой по размерам заголовка и элементов. Если она получилась меньше, чем задано в значении атрибута width, то она увеличивается. То же самое справедливо для атрибута height, только здесь задается высота окна в количестве условных высот символа шрифта.
Атрибут initial_focus указывает код элемента, который подсвечивается по умолчанию и выполняет действие при нажатии пользователем клавиши ENTER.
Три атрибута с префиксом children задают свойства не самого диалога, а входящих в него элементов. Атрибут children_alignment задает способ, которым система AutoCAD выравнивает элементы, размещенные в диалоговом окне. По умолчанию элементы диалога, расположенные в колонку, выравниваются влево, а элементы, расположенные в ряд, выравниваются по центру. На элементы, у которых задан свой атрибут alignment, значение атрибута children_alignment не влияет.
Атрибуты children_fixed_width и children_fixed_height обычно задают тогда, когда их значение равно true. Это означает, что по умолчанию размеры подчиненных элементов (например, кнопок) не изменяются при выводе диалогового окна. Система не будет растягивать кнопки, а будет лишь изменять расстояния между ними.
В среде Visual LISP имеется способ проверки внешнего вида диалогового окна без загрузки -файла в память системы. Для этого нужно запустить команду Tools - Interface Tools - Preview . Активизируется диалоговое окно, в котором нужно выбрать имя диалога. После этого диалоговое окно отобразится на экране.
Внутри директивы описания диалога размещены директивы описания элементов. Эти директивы записываются в форме:
[<метка>]:<оператор>{<атрибуты>}
Каждый элемент является либо элементом оформления (надписи, слайды и пр.), либо элементом управления (кнопки, текстовые поля, списки и пр.). К элементам управления пользователь имеет доступ с помощью клавиатуры или указателя мыши.
В директивах в качестве значения <оператор> могут использоваться следующие наименования элементов:
button - кнопка;edit_box - редактируемое текстовое поле;errtile - поле для отображения сообщений об ошибках;image - поле с изображением;image_button - кнопка с изображением;list_box - список;popup_list -раскрывающийся список;radio_button - переключатель;radio_column - вертикальная группа переключателей;radio_row - горизонтальная группа переключателей;boxed_radio_column - конка переключателей в рамке;boxed_radio_row - ряд переключателей в рамке;slider - скользящая шкала;toggle - флажок;column - колонка (средство объединения элементов);row - ряд (средство объединения элементов);text - нередактируемое текстовое поле;text_part - часть текста, включаемая в элементы concatenation и paragraph;concatenation - text_part;paragraph - вертикальное соединение элементов text_part и concatenation;spacer - пустой элемент ширины width и высоты height;spacer_0 - элемент c нулевыми значениями ширины width и высоты height;spacer_1 - элемент width и height.В файле base. определены следующие элементы, ссылки на которые очень часто применяются в пользовательских диалоговых окнах:
ok_button - элемент с одной кнопкой ОК;ok_only - элемент в виде колонки с одной кнопкой ОК;ok_cancel - элемент из кнопок OK и Cancel;ok_cancel_help - элемент из кнопок OK, Cancel и Help;ok_ cancel_err - элемент из кнопок OK и Cancel и полем сообщений об ошибках;ok_cancel_help_errtile - элемент из кнопок OK, Cancel, Help и полем сообщений об ошибках;ok_cancel_help_info - элемент из кнопок OK, Cancel, Help и Info.Все эти элементы содержат кнопку выхода из диалогового окна. Ниже приведены коды (keys) стандартных элементов, включенные в элементы с кнопкой выхода.
| Элемент (кнопка) | Код элемента |
|---|---|
OK |
"accept" |
Cancel |
"cancel" |
Help |
"help" |
Info |
"info" |
| Поле сообщений об ошибках | "error" |
При описании элемента нет необходимости перечислять значения всех его атрибутов. Достаточно указать только те атрибуты, значения которых должны отличаться от значений по умолчанию. Большая часть атрибутов (например, label, value, key, width, height и др.) применяется во всех элементах. Однако смысл атрибута в разных элементах может быть различным.
Ниже приведены некоторые часто употребляемые атрибуты
| Атрибут | Описание | Допустимые значения | Область применения | Значения по умолчанию |
|---|---|---|---|---|
Action |
Действия, выполняемые при выборе данного элемента | Строка с текстом |
Элементы управления | " " |
alignment |
Способ выравнивания | left, right, centered; top, bottom, centered |
Все элементы | left, centered |
Color |
Цвет | 0-256 или black, red, yellow, green, cyan, blue, magenta |
image |
7 |
edit_width |
Количество видимых символов в редактируемом поле | Целое число | edit_box |
Максимально возможное |
is_cancel |
Признак срабатывания при нажатии ESC |
true, false |
button (только один элемент) |
false |
is_default |
Признак срабатывания при нажатии ENTER |
true, false |
button (только один элемент) |
false |
Key |
Код элемента | Строка | Все элементы | Нет |
Label |
Начальный заголовок | Строка | Все элементы | " " |
List |
Начальное состояние списка | Строка с элементами списка (разделитель \n) |
list_box, popup_list |
Нет |
multiple_select |
Разрешение множественности выбора | true, false |
list_box |
false |
password_char |
Символ, закрывающий текст вводимого пароля | Символ | Edit_box |
Нет |
Value |
Начальное значение | Строка | Все элементы | Нет |
Для того, чтобы вызвать на экран диалоговое окно, необходимо сначала загрузить -файл, содержащий нужный диалог с описанием окна. Затем нужно открыть диалоговое окно. После завершения в окне всех установок оно должно быть закрыто. После закрытия диалогового окна -файл выгружается из оперативной памяти. Все эти операции выполняются с помощью специальных функций.
Функция load_dialog загружает -файл в оперативную память компьютера. Синтаксис функции:
(load_dialog <файл>)
Аргумент <файл> - текстовая строка (текст в кавычках) с именем файла. Возвращаемое значение - положительное целое число при успешной загрузке. Это число является порядковым номером -файла, загруженного в данном сеансе работы с сиcтемой AutoCAD. Если загрузка не выполнена, то функция возвращает отрицательное число. Если в имени файла не указан полный путь, то система AutoCAD пытается найти файл, просматривая все маршруты файлов поддержки.
Функция unload_dialog выгружает -файл из оперативной памяти компьютера. Синтаксис функции:
(unload_dialog <номер>)
Аргумент <номер> - положительное целое число, которое было возвращено при вызове функции load_dialog. Возвращаемое значение - nil.
Функция new_dialog открывает на экране диалоговое окно, если его диалог уже загружен в оперативную память в составе -файла. Синтаксис функции:
(new_dialog <диалог> <номер> [<действие> [<положение>]])
Аргументы:
load_dialog;LISP-выражением (если нет действия, оставить "");Функция возвращает Т, если диалоговое окно открылось, и nil, если возникла ошибка открытия. Когда по условиям задачи аргумент <положение> должен быть задан, то должен быть задан и аргумент "действие". Это действие будет выполнено только тогда, когда пользователь выбрал элемент, для которого не задано действие с помощью атрибута action или функции action-tile.
Пример:
(new_dialog "cone" num "" (list 111 222)) - открывает диалоговое окно с диалогом cone. Левый верхний угол помещен в точку (111,222). Функция возвращает T.
Функция start_dialog активизирует диалоговое окно и готовит систему AutoCAD к приему действий пользователя в этом окне. Синтаксис:
(start_dialog)
Возвращает целое число, которое было передано в качестве аргумента функции done_dialog. Если приложение закрывает диалоговое окно, а функции done_dialog при этом не передано никакого аргумента, то функция start_dialog возвратит:
ОК;Cancel;term_dialog.Функция done_dialog используется только внутри LISP-выражений в функции action-tile или атрибуте action. Она закрывает диалоговое окно и передает значение, которое будет возвращаемым значением функции start_dialog. Синтаксис:
(done_dialog [<число>])
Аргумент <число> - это положительное целое число, которое станет возвращаемым значением функции start_dialog. Возвращаемое значение - список из двух целых чисел с координатами левого верхнего угла диалогового окна в момент его закрытия.
Пример:
(done_dialog 92) - может вернуть список (220 180), а функция start_dialog при этом вернет 92.
Функция term_dialog закрывает все открытые диалоговые окна так, как будто пользователь вышел из каждого из них, нажимая кнопку Cancel. Синтаксис:
(term_dialog)
Возвращаемое значение - nil.
Если работа приложения прерывается по какой-то причине, а некоторые диалоговые окна остались незакрытыми, то система AutoCAD сама обеспечивает вызов функции term_dialog.
Несколько функций языка LISP управляют элементами и их действиями. Они позволяют выполнять следующие операции:
LISP-выражение, выполняемое при выборе элемента и нажатии клавиши ENTER или щелчке левой клавишей мыши (функция action_tile);mode_tile);get_tile);set_tile);get_attr);client_data_tile).Функция action_tile задает при помощи LISP-выражения действие, которое нужно выполнить системе AutoCAD при выборе элемента или редактировании его содержимого. Синтаксис функции:
(action_tile <код> <выражение>)
Аргументы: <код> - строка с кодом элемента, <выражение> - строка с LISP-выражением. Возвращаемое значение - Т.
Большинство элементов диалогового окна являются элементами управления. Для них должны быть описаны действия, выполняемые системой AutoCAD при выборе пользователем этого элемента. Под выбором элемента имеются в виду, в частности, такие события, вызванные пользователем:
Enter;Button;edit_box;list_box или popup_box;slider .Отклик системы на события окна совершается тогда, когда после операции с одним элементом курсор перейдет к другому элементу или пользователь выйдет из диалогового окна с помощью кнопки выхода.
Такое действие для каждого элемента может быть задано с помощью атрибута action -файла. Значением атрибута может быть строка с LISP-выражением (там не должно быть функции command). Другой вариант задания действия - указание LISP-выражения в строке, передаваемой в качестве аргумента функции action_tile. Обращение к этой функции должно быть записано между вызовами функций new_dialog и start_dialog.
Действие, заданное с помощью аргумента <выражение> функции action_tile аннулирует действие, заданное значением атрибута action этого элемента в -файле. Действие всегда задается через код элемента. Значение атрибута key передается функции action_tile в качестве аргумента <код>.
LISP-выражение в функции action_tile может использовать значения зарезервированных глобальных переменных со следующими именами:
$value - текущее значение рассматриваемого элемента;$key - код рассматриваемого элемента;$reason - тип действия, выполненного над элементом;$data - данные элемента, заданные функцией client_data_tile;$x и $y - координаты указанной точки внутри изображения.Примеры:
(action_tile "accept" "(done_dialog)") - действие кнопки выхода;
(action_tile "Test" ( - проверка значения элемента на отрицательные числа или ноль;
В этом примере длинное LISP-выражение получено сцепкой двух строк. Обратите внимание на то, что внутренние двойные кавычки, необходимые для вызова функции alert, применяются с предшествующим слэшем.
(action_tile "Test" "(setq myTest 1) (saveVars) (done_dialog)")
По событию с элементом "Test" выполняется три действия: переменной myTest присваивается значение 1, запускается функция saveVars и закрывается диалоговое окно. Обратите внимание, что и код и выражение всегда берутся в кавычки.
Функция mode_tile изменяет состояние элемента диалога. Синтаксис:
(mode_tile <код> <состояние>)
Аргументы: <код> - код элемента; <состояние> - целое число от 0 до 4 (см. таблицу). Возвращаемое значение - nil.
| Значение | Действие |
|---|---|
| 0 | Включить элемент |
| 1 | Выключить элемент (сделать недоступным) |
| 2 | Выбрать элемент |
| 3 | Подсветить содержимое элемента |
| 4 | Включить/выключить подсветку изображения |
При выключении элемента его цвет приглушается. Он становится недоступным для пользователя. Чтобы сделать его вновь доступным, его надо включить.
Примеры:
(mode_tile "k1" 1) - выключает элемент с кодом k1;
(mode_tile "k1" 0) - включает элемент с кодом k1.
Функция set_tile позволяет менять содержание диалога, заданное атрибутом value.
(set_tile <код> <значение>)
Аргументы: <код> - код элемента; <значение> - строка с новым значением, присваиваемым атрибуту value данного элемента.
Возвращаемое значение - значение второго аргумента, переданного функции.
Функция get_tile читает содержимое элемента диалога (текущее значение атрибута value). Синтаксис:
(get_tile <код>)
Аргумент - строка с кодом элемента.
Возвращаемое значение - строка с текущим значением атрибута value.
Функция get_attr читает значение атрибута элемента текущего каталога:
(get_attr <код> <атрибут>)
Аргументы: <код> - строка с кодом элемента, <атрибут> - строка с именем атрибута. Возвращаемое значение - строка со значением атрибута элемента.
Пример:
(get_attr "user" "alignment") - возвратит "centered"
Функция client_data_tile связывает с элементом диалогового окна строку с пользовательскими данными. Синтаксис:
(client_data_tile <код> <данные>)
Аргументы: <код> - строка с кодом элемента, <данные> - строка с пользовательскими данными. Возвращаемое значение - nil.
Чтобы обратиться к данным, присоединенным к элементу диалогового окна, нужно прочитать значение переменной $data в функции action_tile. Так можно изменять действие, присвоенное элементу, в зависимости от пользовательских данных.
Пример:
(client_data_tile "user" "2110") - связывает строку 2110 с элементом "user".
Во время работы диалогового окна система AutoCAD формирует значения глобальных переменных, которые называются переменными действия:
$key, $value, $reason, $data, $x, $y.
В них сохраняются некоторые дополнительные данные о состоянии диалогового окна и выполненных в нем действиях пользователя. Переменные используются в LISP-выражениях, задаваемых в качестве второго аргумента функции action_tile. Вне этой функции значения переменных действия не определены.
Пользовательская программа не может изменять значения этих переменных и должна применять их только для чтения. В таблице рассматриваются различные варианты формирования значений переменных действия.
| Переменная | Значение |
|---|---|
$key |
Код элемента (во всех элементах) |
$value |
Значение атрибута Для поля Для Для |
$data |
Строка с пользовательскими данными, привязанными к элементу |
Sreason |
Для элементов edit_box, list_box, image_button и - число с кодом причины прерывания работы с элементом (см. следующую таблицу) |
$x, $y |
Координаты в пикселях указанной пользователем точки внутри изображения для элемента image_button |
Примеры:
(action_tile "user" "(setq nam (strcat \ "Пользователь: \" $value))"); (action_tile "cldat" "(setq tyg (read $data))");
| Значение | Описание |
|---|---|
| 1 | Обычный вариант действия с элементом, в том числе, пользователь выбрал элемент, нажата клавиша ENTER, а элемент имеет значение true атрибута is_default |
| 2 | Для поля edit_box: пользователь вышел из поля, но не завершил редактирование (например, нажал клавишу TAB или выбрал другой элемент) |
| 3 | Для элемента пользователь изменил значение элемента с помощью указателя шкалы, но не завершил ввода |
| 4 | Для элементов list_box и image_button: пользователь выполнил двойной щелчок. Если multiple_selection=false, то это должно означать окончательный выбор. Если multiple_selection=true, то это должно обрабатываться как обычный выбор (значение 1). |
Функция start_list начинает операцию редактирования списка в элементах list_box и popup_list. Синтаксис функции:
(start_list <код>[<операция> [<номер>]])
Аргументы:
<операция> - целое число, обозначающее тип операции:
По умолчанию для второго аргумента действующее значение равно 3, а для третьего аргумента - равно 0. Аргументы в списке нумеруются, начиная с нуля.
Возвращаемое значение - код элемента
Вызов функции start_list является отметкой начала операции формирования или редактирования списка. Вызов функции end_list является отметкой окончания операции. Изменения вносятся с помощью функции add_list и других функций, расположенных между start_list и end_list. Здесь нельзя использовать функцию set_tile.
Примеры:
(start_list "kr2") - указывает начало операции формирования заново списка для элемента диалога с кодом "kr2"; (start_list "kr2" 2) - указывает начало операции добавления новых элементов списка для элемента диалога с кодом "kr2"; (start_list "kr2" 1 14) - указывает начало операции замены элементов списка, начиная с 14, для элемента диалога с кодом "kr2".Функция add_list выполняет операцию редактирования списка в элементах list_box и popup_list. Синтаксис функции:
(add_list <строка>)
Аргументы <строка> - строка, которая добавляется к списку или заменяет элемент списка. Возвращаемое значение - значение аргумента <строка>, если операция выполнена успешно. В случае сбоя возвращается nil.
Тип операции (изменение или добавление) определяется предшествующим вызовом функции start_list.
Пример: (add_list "Деталь 3217-06")
Функция end_list завершает операцию редактирования списка в элементах list_box и popup_list. Синтаксис функции:
(end_list)
Возвращаемое значение nil.
Элементы image и image_button являются графическими полями с прямоугольной зоной. Зона может быть заполнена
Открывает процесс заполнения функция start_image, а завершает процесс заполнения функция end_image. Между ними располагаются функции fill_image, slide_image, vector_image. Не допускается применять функцию set_tile. При указании координат в графическом окне предполагается, что левый верхний угол графического элемента находится в начале координат. Координаты правого нижнего угла могут быть получены с помощью функций dimx_tile и dimy_tile.
Функция start_image открывает процесс заполнения графического элемента. Синтаксис:
(start_image <код>)
Аргумент <код> - значение атрибута key графического элемента. Возвращаемое значение - строка со значением аргумента, если операция выполнена успешно. В случае сбоя возвращается nil.
Функция end_image завершает процесс формирования изображения. Синтаксис:
(end_image)
Возвращаемое значение - nil.
Вызову функции end_image должен обязательно предшествовать вызов функции start_image.
Функция fill_image заполняет прямоугольник внутри графического элемента одним цветом. Синтаксис:
(fill_image <x1> <y1> <ширина> <высота> <цвет>)
Аргументы:
Возвращаемое значение - значение аргумента <цвет>.
Пример: (fill_image 5 6 15 25 1) - заполняет красным (1) цветом прямоугольник с левым верхним углом в точке (5,6) и нижним правым углом в точке (15,25).
Функция slide_image заполняет графический элемент слайдом из отдельного -файла или из библиотеки слайдов. Синтаксис:
(slide_image <x1> <y1> <ширина> <высота> <слайд>)
Аргументы <x1> <y1> <ширина> <высота> аналогичны таковым для функции fill_image. Аргумент <слайд> - строка с именем файла слайда (расширение . не указывается) или с именем библиотеки слайдов (имя слайда из библиотеки указывается в круглых скобках).
Возвращаемое значение - строка со значением аргумента <слайд>.
Примеры:
(slide_image 0 0 50 32 "ring1") - заполняет графический элемент размером 50х30 слайдом из файла ring1..
(slide_image 0 0 50 32 "lib23(nut8)") - заполняет графический элемент размером 50х30 слайдом nut8 из библиотеки слайдов lib23.
Функция vector_image рисует отрезок заданного цвета внутри графического элемента диалогового окна. Синтаксис:
(vector_image <x1> <y1> <x2> <y2> <цвет>)
Аргументы:
Пример:
(vector_image 5 11 33 11 2) - рисует отрезок желтого цвета из точки (5,11) в точку (33, 11).
Функция dimx_tile вычисляет горизонтальный размер графического элемента с данным кодом (точнее, размер элемента минус 1). Синтаксис:
(dimх_tile <код>)
Аргумент <код> - строка с кодом графического элемента. Возвращаемое значение - целое число с номером крайнего правого пикселя элемента (левый крайний пиксель имеет номер ноль).
Пример:
(dimx_tile "igp2") - может вернуть 50 (всего по горизонтали 51 пиксель)
Функция dimy_tile вычисляет вертикальный размер графического элемента с данным кодом (точнее, размер элемента минус 1). Синтаксис:
(dimy_tile <код>)
Аргумент <код> - строка с кодом графического элемента. Возвращаемое значение - целое число с номером крайнего нижнего пикселя элемента (верхний крайний пиксель имеет номер ноль)
Пример: (dimy_tile "igp2") - может вернуть 32 (всего по вертикали будет 33 пикселя).
Установите элементы диалогового окна согласно следующей программе:
// Установки элементов диалогового окна
//
elements: dialog {label="Установка элементов диалогового окна";
:column{:row{:boxed_column{label="Элементы управления";
:row{:boxed_column{label="Поле и выпадающий список";
:edit_box {label="Edit_box";key="txt";value="0.00";edit_width=8;}
:popup_list {label="Popup_list";key="pop";width="8";list="Иванов\nПетров\nСидоров";}}
:boxed_column{label="Кнопка и шкала";
:button {label="Button";key="but";color="1";width="8";}
:slider {label="Slider";}}}
:spacer{height=1;}
:radio_row {label="Ряд переключателей (radio_row)";
:radio_button {label="Radio_button 1";value=1;}
:radio_button {label="Radio_button 2";value=0;}
}
}
:boxed_row{:column{label="Список и флажок";
:list_box {label="List_box";key="list";list="Иванов\nПетров\nСидоров";height="8";}
:toggle {label="Toggle";value=1;}
}
}}
:boxed_row{label="Стандартная кнопка закрытия окна";
ok_cancel_help_info;
}}}
Сохраните файл как Elements. в папке Support.
Создайте файл загрузки:
(defun c:show_elements (/ num ddiag)
(if (< (setq num (load_dialog "elements.dcl")) 0)
(prong
(alert "The Elements.dcl file could not be loaded!") (exit))
)
(if (not (new_dialog "elements" num))
(exit)
)
(start_dialog)
(unload_dialog num)
;;;--- If the user pressed the Cancel button
(if (= ddiag 1)
(princ "\n Window cancelled!")
)
;;;--- If the user pressed the Okay button
(if (= ddiag 2)
(progn
(princ "\n The user pressed Okey!")
)
)
(princ)
) ;_defun
Сохраните файл загрузки как Elements..
Запустите функцию show_elements из командной строки AutoCAD. На экране должно появиться диалоговое окно (рис. 6.3).
(рис 6.3) Элементы диалогового окна
Программа может различить в наших действиях лишь нажатие кнопок ОК и Cancel.
Измените описание диалогового окна в файле rog.:
//Диалоговое окно установки параметров рога
rog: dialog{label="Установка параметров рога";
:edit_box{label="Радиус окружности ";key="rad" ;value="80.00"; edit_width=8;}
:edit_box{label="Диаметр дуги, мм";key="diam";value="400.00";edit_width=8;}
:edit_box{label="Толщина стенки, мм";key="thick";value="1.00";edit_width=6;}
:spacer{height=1;}
:edit_box{label="Индекс цвета";key="col";value="2";edit_width=4;}
:spacer{height=1;}
ok_cancel;
}
А теперь вернитесь к файлу rog.. В функции qrog отклики на события в диалоговом окне описывались с помощью функции action_tile. Значения переменных сохранялись для каждого отдельного элемента. Опробуйте другой способ сохранения указанных данных - по нажатии кнопки ОК. В этом случае можно оставить значения величин по умолчанию, либо отредактировать их в текстовых полях диалогового окна.
Создайте в этом же файле новую функцию save_vars, которая будет вызываться после нажатия кнопки ОК. Содержимое текстовых полей прочитает функция get_tile.
Следует учесть, что в данном случае переменные rad1, diam1, thick1, col1 должны быть общими для функций qrog и save_vars, т.е. глобальными.
(defun save_vars () (setq rad1 (atof (get_tile "rad"))) (setq diam1 (atof (get_tile "diam"))) (setq thick1 (atof (get_tile "thick"))) (setq col1 (get_tile "col")) )
Программа построения рога будет выглядеть следующим образом:
(defun c:qrog (/ cenrt1 circle1 arc1 rog1 angle1 endp1 dial) (setq centr1 '(0 0 0)) ; исходная базовая точка (if (< (setq num (load_dialog "rog.dcl")) 0); загружаем в память файл "rog.dcl" (progn (alert "Файл Rog.dcl не загружен!"); сообщение о неудачной загрузке (exit) )) (if (not (new_dialog "rog" num)); ;; ;;функция new_dialog проверяет наличие в файле диалога "rog" (progn (alert "Диалог Rog не найден!"); сообщение о неудачном поиске файла (exit) )) ;;;If an action event occurs, do this function (action_tile "accept" "(setq dial 2)(save_vars)(done_dialog)"); действия при нажатии ОК (action_tile "cancel" "(setq dial 1)(done_dialog)"); действия при нажатии CANCEL (start_dialog); активизирует диалоговое окно (unload_dialog num); выгружаем окно из памяти (setq angle1 (* 55.0 (atan rad1 (* diam1 (/ pi 2))))); находим угол сужения тела рога (command "_view" "_top") ; начинаем со стандартного вида (command "_view" "_swiso"); переходим к северо-западному виду (command "_circle" centr1 rad1 ""); строим базовую окружность (setq circle1 (entlast)); извлекаем имя сущности для базовой окружности (command "_ucs" "_x" "90" ""); поворачиваем ПСК (setq endp1 (list diam1 0.0)); находим координаты конечной точки дуги (command "_arc" centr1 "e" endp1 "a" "-180" ""); строим дугу изгиба рога (setq arc1 (entlast)); извлекаем имя сущности для дуги и сохраняем его (command "_ucs" "_x" "-90"); совмещаем плоскость окружности с плоскостью XY (command "extrude" circle1 "" "t" angle1 "p" arc1 "");создаем тело рога (setq rog1 (entlast)); извлекаем имя сущности для рога и сохраняем его (command "_zoom" "e" ""); растягиваем изображение на весь экран (command "_vscurrent" "_r" ""); устанавливаем текущий визуальный стиль realistic (command "_chprop" "_all" "" "_color" col1 ""); закрашиваем цветом col1 (command "_view" "_bottom" ""); устанавливаем вид снизу (command "_solidedit" "_body" "_shell" rog1 centr1 "" thick1 "" ""); делаем полость (command "_erase" arc1 ""); удаляем ненужную образующую дугу ;;;If the user pressed the Okey Or Cancel button (if(= dial 2) (alert "Congratulations!")); поздравление при успешном построении (if(= dial 1) (alert "Alas!")); увы! - при неудачном построении (princ); тихий выход )
В качестве варианта введите операции сохранения значений переменных в функцию qrog. Сделайте все переменные save_vars тогда не нужна.
Рассмотрим теперь более подробно работу с отдельными элементами диалоговых окон: с кнопками, со списками, с флажками и с радиокнопками.
Создадим -файл описания диалогового окна с тремя кнопками Button и одной кнопкой Cancel. Каждая из трех кнопок должна выдать послание при нажатии.
Расположите кнопки в колонку друг под другом в две группы:
But:dialog {label="Работа с кнопками Button";
:column{:boxed_column {
:button {key="but1";label="Button1";is_default="false";}
:button {key="but2";label="Button2";is_default="false";}
:button {key="but3";label="Button3";is_default="false";}
}
:boxed_row{ok_cancel; }
}
}
Сохраните файл как But. в папке …\Support.
А теперь составьте файл But. для загрузки -файла и описания сценария отклика на события в диалоговом окне. Он будет состоять из двух функций:
(defun C:But1()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "But.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "But" dcl_id))
(progn
(alert "The But.dcl file could not be loaded!")(exit)
)
)
;;;--- If an action event occurs, do this function
(action_tile "but1" "(doButton 1)")
(action_tile "but2" "(doButton 2)")
(action_tile "but3" "(doButton 3)")
(action_tile "cancel" "(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- Suppress the last echo for a clean exit
(princ)
)
(defun doButton(a)
(cond
((= a 1)(alert "Button 1 was pressed!"))
((= a 2)(alert "Button 2 was pressed!"))
((= a 3)(alert "Button 3 was pressed!"))
)
)
На экране должна быть картинка, подобная рис. 6.4.
(рис 6.4) Диалоговое окно с кнопками
Составьте файл List. с описанием диалогового окна с двумя списками в верхнем ряду и кнопкой ОК и Cancel в нижнем ряду. Сохраните его в папке …\Support.
list: dialog {label = "Работа со списками list_box";
: column {
: boxed_row {: text { key = "text1"; value = "Nothing selected"; }}
: boxed_row {
: list_box {key = "mylist1"; label ="Choose Item"; height = 9; width = 8; multiple_select = false; fixed_width_font = true;
list="Лимон\nЛист\nНебо\nСажа\nСнег\nЯблоко";}
: boxed_row {
: popup_list { key = "mylist2"; label ="Choose Color"; width = 8; multiple_select = false;
fixed_width_font = true; list="red\nyellow\ngreen\ncyan\nwhite\nblack";}}}
: boxed_row {
: button { key = "accept"; label = "Okey "; is_default = true; }
: button { key = "cancel";label = "Cancel "; is_default = false; is_cancel = true; }}
}
}
Заполнение спискoв здесь произведено с помощью атрибута list. Однако, если бы мы написали атрибуты value = "";, то списки были бы пустыми. В этом случае они заполняются при запуске файла List. так, как это показано ниже.
Составьте теперь загрузочный файл List.. Строки, относящиеся к загрузке списков, закомментированы. Если списки уже заполнены, то эти строки можно удалить. Если их раскомментировать, то старое содержимое в списках будет удалено, а новые записи установлены.
(defun C:list () ;;; (setq myList1(list "Лимон" "Лист" "Небо" " Сажа" "Снег" "Яблоко")) ;;; (setq myList2(list "red" "yellow" "green" "cyan" "white" "black")) ;;;--- Load the dcl file (setq dcl_id (load_dialog "list.dcl")) ;;;--- Load the dialog definition if it is not already loaded (if (not (new_dialog "list" dcl_id)) (progn (alert "The List.DCL file could not be loaded!") (exit) ) ) ;;; (start_list "mylist1" 3) ;;; (mapcar 'add_list myList1) ;;; (end_list) ;;; (start_list "mylist2" 3) ;;; (mapcar 'add_list myList2) ;;; (end_list) ;;;--- If an action event occurs, do this function (action_tile "mylist2" "(saveVars)") (action_tile "accept" "(setq ddiag 2)(done_dialog)") (action_tile "cancel" "(setq ddiag 1)(done_dialog)") ;;;--- Display the dialog box (start_dialog) ;;;--- Unload the dialog box (unload_dialog dcl_id) ;;;--- If the user pressed the Cancel button (if(= ddiag 1) (princ "\n List cancelled!") ) ;;;--- If the user pressed the Okay button (if(= ddiag 2) (progn (princ "\n The user pressed Okay!") ) ) (princ)) (defun saveVars () (setq numstrlist (atoi (get_tile "mylist1"))) (princ numstrlist) (setq word_list (cond ((= numstrlist 0) "Лимон") ((= numstrlist 1) "Лист") ((= numstrlist 2) "Небо") ((= numstrlist 3) "Сажа") ((= numstrlist 4) "Снег") ((= numstrlist 5) "Яблоко") (Т "") ) ;_конец cond ) ;_ конец setq (setq numstrpop (atoi (get_tile "mylist2"))) (princ numstrpop) (setq word_pop (cond ((= numstrpop 0) "red") ((= numstrpop 1) "yellow") ((= numstrpop 2) "green") ((= numstrpop 3) "cyan") ((= numstrpop 4) "white") ((= numstrpop 5) "black") (Т "") ) ;_конец cond ) ;_ конец setq (setq myStr (strcat word_list " имеет цвет " word_pop)) (set_tile "text1" myStr) )
В этот же файл занесена функция saveVars, которая определяет отклики на события диалогового окна. Событие состоит в выборе слова в левом списке и слова в правом списке. Оба выбранных слова занесем в строку text по щелчку в правом списке. Если щелкнуть по кнопке ОК, то окно закроется.
При чтении значения списка функция get_tile возвращает номер строки, которые нумеруются с нуля. Поэтому далее нужно в цикле или с помощью функции cond найти соответствие между номером строки и значением элемента.
Диалоговое окно списков показано на рис. 6.5. Выбранная запись отражена в нередактируемом текстовом поле text в верхней части окна.
(рис 6.5) Окно с двумя списками
Составьте программу построения диалогового окна с колонкой флажков. Сохраните файл как …\Support\
Toggle: dialog { label = "Работа с элементами toggle";
: column {: boxed_row {
: text { key = "text1"; value = "Nothing selected"; }}
: boxed_column { label = "Choose your lucky charms:";
: toggle { key = "tog1";label = "Hearts"; value = "0";}
: toggle { key = "tog2";label = "Moons"; value = "0";}
: toggle { key = "tog3";label = "Stars"; value = "0";}
: toggle { key = "tog4";label = "Clovers";value = "0";}
}
: boxed_row {
: button { key = "accept"; label = "Okey "; is_default = true; }
: button { key = "cancel";label = "Cancel "; is_default = false; is_cancel = true; }}
}}
Теперь составьте файл загрузки и обработки . В этом файле создано две функции: chkToggle и :
(defun chkToggle() (setq tog1(atoi(get_tile "tog1"))) // 0 = not chosen 1 = chosen (setq tog2(atoi(get_tile "tog2"))) // 0 = not chosen 1 = chosen (setq tog3(atoi(get_tile "tog3"))) // 0 = not chosen 1 = chosen (setq tog4(atoi(get_tile "tog4"))) // 0 = not chosen 1 = chosen (setq myStr "") (if(= tog1 1)(setq myStr(strcat myStr " Hearts"))) (if(= tog2 1)(setq myStr(strcat myStr " Moons"))) (if(= tog3 1)(setq myStr(strcat myStr " Stars"))) (if(= tog4 1)(setq myStr(strcat myStr " Clovers"))) ;;;--- If nothing was selected... (if(= myStr "")(setq myStr "Nothing Selected!")) ;;;--- Now set the text control to display the string (set_tile "text1" myStr) ) (defun C:Toggle() ;;;--- Load the dcl file (setq dcl_id (load_dialog "Toggle.dcl")) ;;;--- Load the dialog definition if it is not already loaded (if (not (new_dialog "Toggle" dcl_id) ) (exit)) ;;;--- If an action event occurs, do this function (action_tile "tog1" "(chkToggle)") (action_tile "tog2" "(chkToggle)") (action_tile "tog3" "(chkToggle)") (action_tile "tog4" "(chkToggle)") (action_tile "cancel" "(done_dialog)") ;;;--- Display the dialog box (start_dialog) ;;;--- Unload the dialog box (unload_dialog dcl_id) ;;;--- Suppress the last echo for a clean exit (princ))
Ha экране диалоговое окно выглядит так, как на рис. 6.6.
(рис 6.6) Диалоговое окно с флажками
Постройте диалоговое окно с четырьмя переключателями. Из всей группы только один из переключателей может быть выделен. Он должен быть определен при нажатии кнопки ОК.
Составьте -файл для колонки из четырех переключателей. Внизу окна поместите кнопки OK и Cancel. Сохраните файл как С:\Program Files\AutoCAD 2010\Support\Radio.. Файл можно сохранить и в другом каталоге. Тогда загрузить его в чертеж нужно по команде Tools - . Загрузить можно и непосредственно из среды Visual LISP.
Radio : dialog {label = "Переключатели RadioButtons";
: column {
: radio_column {key = "mychoice";
: radio_button {key = "but1"; label = "Apples"; value =1;}
: radio_button {key = "but2"; label = "Oranges";}
: radio_button {key = "but3"; label = "Bananas";}
: radio_button {key = "but4"; label = "Lemons";}
}
: boxed_column {
: button {key = "accept";label = " Okey ";is_default = true;}
: button {key = "cancel";label = " Cancel ";is_default = false;is_cancel = true;}
}}}
Далее создайте -файл загрузки:
(defun C:Radio()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "Radio.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "Radio" dcl_id))
(progn
(alert "The Radio.DCL file could not be loaded!")
(exit)
)
)
;;;--- If an action event occurs, do this function
(action_tile "accept" "(setq ddiag 2)(saveVars)(done_dialog)")
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the user pressed the Cancel button
(if(= ddiag 1)
(princ "\n Radio cancelled!")
)
;;;--- If the user pressed the Okay button
(if(= ddiag 2)
(progn
(princ "\n The user pressed Okay!")
)
)
;;;--- Suppress the last echo for a clean exit
(princ)
)
Загрузите файлы и запустите команду "Radio". На экране появится диалоговое окно, в котором работают лишь кнопки OK и Cancel (рис.6.7):
(рис 6.7) Макет диалогового окна "Radio Buttons"
При нажатии кнопки ОК вызывается функция saveVars, которая запускает сценарий отклика на событие выделения переключателя. Составим эту функцию и поместим ее в -файл:
(defun saveVars()
;;;--- Get the key of the choice made
;;; [ returns "but1" "but2" "but3" or "but4" whichever is selected.]
(setq myChoice(get_tile "mychoice"))
;;;--- Get the value of each item
(setq choice1(atoi(get_tile "but1"))) // 0 = not chosen 1 = chosen
(setq choice2(atoi(get_tile "but2"))) // 0 = not chosen 1 = chosen
(setq choice3(atoi(get_tile "but3"))) // 0 = not chosen 1 = chosen
(setq choice4(atoi(get_tile "but4"))) // 0 = not chosen 1 = chosen
)
(defun C:Radio()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "Radio.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "Radio" dcl_id))
(progn
(alert "The Radio.DCL file could not be loaded!")
(exit)
) )
;;;--- If an action event occurs, do this function
(action_tile "accept" "(setq ddiag 2)(saveVars)(done_dialog)")
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the user pressed the Cancel button
(if(= ddiag 1)
(princ "\n Radio cancelled!")
)
;;;--- If the user pressed the Okey button
(if(= ddiag 2)
(progn
;;;--- Inform the user of his selection using the radio_column data
(princ "\n Using Radio_column data...You chose ")
(cond
((= myChoice "but1")(princ "Apples!"))
((= myChoice "but2")(princ "Oranges!"))
((= myChoice "but3")(princ "Bananas!"))
((= myChoice "but4")(princ "Lemons!"))
)
;;;--- Inform the user of his selection using the radio_buttons data
(princ "\n Using Radio_buttons data...You chose ")
(cond
((= Choice1 1)(princ "Apples!"))
((= Choice2 1)(princ "Oranges!"))
((= Choice3 1)(princ "Bananas!"))
((= Choice4 1)(princ "Lemons!"))
) ) )
;;;--- Suppress the last echo for a clean exit
(princ))
Сейчас попробуем соединить все изложенные выше отдельные сведения о программировании диалоговых окон. Необходимо построить такой -файл, который позволил бы управлять большинством параметров чертежа.
Нарисуем многоугольник или окружность на выбранном нами слое. Выбранные нами опции должны быть сохранены как опции по умолчанию при следующем открытии программы. Если выбран многоугольник, нужно выбрать число сторон в popup_list. Список слоев должен быть помещен в list_box. Выбор фигуры должен производиться радиокнопкой radio_column. В элементе нужно поставить флажки "Save Settings" сохранения опций. Наконец, нам будут нужны кнопки ОК и Cancel.
Список слоев, возможно, будет большим, - для него нужно отвести одну высокую колонку. Остальные элементы следует разместить во вторую колонку. В нижнем ряду будут помещены кнопки ОК и Cancel.
Скопируйте коды элементов из вышележащих материалов лекции.
SAMPLE : dialog {
label = "Sample Dialog Box";
: column {
: row {
: boxed_column {
: radio_column {key = "radios";
: radio_button {label = "Draw Circle";key = "drawcir"; value = "1";}
: radio_button {label = "Draw Polygon"; key = "drawpol"; value = "0";}
}
: popup_list {key = "numsides"; label = "Number of Sides"; width = 25; fixed_width_font = true;}
: toggle {key = "saveset"; label = "Save settings";}
}
: row {
: list_box {label ="Select Layer";key = "layerList";height = 12; width = 10;
multiple_select = false; fixed_width_font = true;value = "";}
}}
: row {
: button {key = "accept";label = " Okey "; is_default = true;}
: button {key = "cancel";label = " Cancel ";is_default = false;is_cancel = true;}
}}}
Сохраните файл как C:\Program Files\AutoCAD 2007\Support\Sample..
Скопируйте далее -файл загрузки и обработки:
(defun C:SAMPLE ()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "SAMPLE.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "SAMPLE" dcl_id))
(progn
(alert "The SAMPLE.DCL file could not be loaded!")
(exit)
)
)
;;;--- If an action event occurs, do this function
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
(action_tile "accept" "(setq ddiag 2)(saveVars)(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the cancel button was pressed - display message
(if (= ddiag 1)
(princ "\n \n ...SAMPLE Cancelled. \n ")
)
;;;--- If the "Okay" button was pressed
(if (= ddiag 2)
(princ "\n \n ...SAMPLE Complete!")
)
;;;--- Suppress the last echo for a clean exit
(princ)
)
Сохраните файл как C:\Program Files\AutoCAD 2007\Support\Sample..
Загрузите файлы и запустите функция Sample. На экране должно появиться диалоговое окно (рис. 6.8)
(рис 6.8) Предварительное построение диалогового окна
Обратите внимание, что списки отсутствуют, а переключатель Draw Circle выделен (значение value=1). В элементе флажок не установлен, так как не задано значение value. Если нажать кнопку Cancel, то окно закроется. Если же нажать кнопку ОК, то будет выдано сообщение об ошибке: функция saveVars не определена.
Прежде всего составим списки числа сторон многоугольника и добавим их к элементу popup_list. Далее составим список слоев и заполним элемент list_box.
Вместо того, чтобы создавать функцию, которая получала бы все имена слоев чертежа, можно просто составить список вручную. Первый путь длиннее, но он более строгий.
Чтение имен слоев чертежа:
;;;--- Set up a list to hold the layer names
(setq layerList(list))
;;;--- Get the first layer name in the drawing
(setq layer(tblnext "LAYER" T))
;;;--- Add the layer name to the list
(setq layerList(append layerList (list(cdr(assoc 2 layer)))))
;;;--- Step though the layer table to get all layers
(while (setq layer(tblnext "LAYER"))
;;;--- Save each layer name in the list
(setq layerList(append layerList (list(cdr(assoc 2 layer)))))
)
Составление списка вручную:
(setq layerList(list "0" "Layer1" " Layer2" " Layer3" " Layer4" " Layer5" "Layer6" " Layer7" " Layer8" " Layer9"))
То же самое для числа сторон многоугольника:
(setq numSides(list "4" "6" "8" "12" "16"))
Добавим эти строки в описание диалога -файла.
;;;--- Add the layer names to the dialog box (start_list "layerlist" 3) (mapcar 'add_list layerList) (end_list) ;;;--- Add the number of sides to the dialog box (start_list "numsides" 3) (mapcar 'add_list numSides) (end_list)
После этого добавление основная LISP-программа должна выглядеть так:
(defun C:SAMPLE ()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "SAMPLE.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "SAMPLE" dcl_id))
(progn
(alert "The SAMPLE.DCL file could not be loaded!")
(exit)
)
)
(setq layerList(list "0" "Layer1" " Layer2" " Layer3" " Layer4" " Layer5" "Layer6" " Layer7" " Layer8" " Layer9"))
(setq numSides(list "4" "6" "8" "12" "16"))
;;;--- Add the layer names to the dialog box
(start_list "layerList" 3)
(mapcar 'add_list layerList)
(end_list)
;;;--- Add the number of sides to the dialog box
(start_list "numsides" 3)
(mapcar 'add_list numSides)
(end_list)
;;;--- If an action event occurs, do this function
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
(action_tile "accept" "(setq ddiag 2)(saveVars)(done_dialog)")
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the cancel button was pressed - display message
(if (= ddiag 1)
(princ "\n \n ...SAMPLE Cancelled. \n ")
)
;;;--- If the "Okay" button was pressed
(if (= ddiag 2)
(princ "\n \n ...SAMPLE Complete!")
)
;;;--- Suppress the last echo for a clean exit
(princ)
)
Сохраните файлы, загрузите их и запустите команду Sample. На экране должно появиться диалоговое окно со списками (рис. 6.9):
(рис 6.9) Диалоговое окно со списками
Создадим сценарий отклика на события в окне в описании функции SaveVars LISP-файла. При выборе строки в списке функция чтения get_tile возвращает номер строки как строковую константу. На время отладки программы введем распечатки полученных значений переменных. В дальнейшем эти распечатки нужно убрать.
(defun saveVars() (setq radios(get_tile "radios")) ;;;--- Get the number of sides selected from the list (setq numStr(get_tile "numsides")) (if(= numStr "") (setq numSides nil) (setq numSides(nth (atoi numStr) numSides)) ) (princ numSides) (terpri) ;;;--- See if the user wants to save the settings (setq saveSet(atoi(get_tile "saveset"))) (princ saveSet) (terpri) ;;;--- Get the selected item from the layer list (setq sStr(get_tile "layerList")) ;;;--- If the index of the selected item is not "" then something was selected (if(/= sStr "") (progn ;;;--- Something is selected, so convert from string to integer (setq sIndex(atoi sStr)) ;;;--- And get the selected item from the list (setq layerName(nth sIndex layerList)) ) ;;;--- Else, nothing is selected (progn ;;;--- Set the index number to -1 (setq sIndex -1) ;;;--- And set the name of the selected item to nil (setq layerName nil) ) ) (princ layerName) (terpri) )
Если не выделить имя слоя в элементе list_box, то значение его будет nil. Иначе будет выдан примерно такой результат:
Command: sample 6 1 sStr5 sindex5 layerNameLayer5 ...SAMPLE Complete!
При вычерчивании окружности нужно сделать неработающим элемент "Number of Sides" popup_list. Для этого нужно запрограммировать события с радиокнопками таким образом:
;;;--- If an action event occurs, do this function (action_tile "drawcir" "( 1)") (action_tile "drawpol" "(toggleRadio 2)")
При выборе элемента drawcir вызывается функция toggleRadio 1, а при выборе элемента drawpol вызывается функция toggleRadio 2.
Создадим такую функцию с параметром (a) в -программе:
(defun toggleRadio(a) ;if circle is selected (if(= a 1) (mode_tile "numsides" 1) ;disable ;else (mode_tile "numsides" 0) ;enable ) )
По умолчанию в программе должна рисоваться окружность. Поэтому перед выражениями с функциями action_tile нужно добавить строку
(mode_tile "numsides" 1)
Таким образом, когда выделяем кнопку, чтобы нарисовать окружность, numSides popup_list недоступен. Когда же мы собираемся рисовать многоугольник, то элемент установки число сторон становится доступным.
А теперь можно изменить слой:
(setq oldLay(getvar "clayer")) (setvar "clayer" layerName)
Напишем также команды построения окружности и многоугольника
(if(= radios "drawcir") (progn (setq pt(getpoint "\n Center point: ")) (command "circle" pt pause) ) ;;;--- Else draw a polygon (progn (setq pt(getpoint "\n Center Point: ")) (command "polygon" numSides pt "C" pause) ) )
LISP-файл будет выглядеть следующим образом:
(defun C:SAMPLE ()
;;;--- Load the dcl file
(setq dcl_id (load_dialog "Sample.dcl"))
;;;--- Load the dialog definition if it is not already loaded
(if (not (new_dialog "sample" dcl_id))
(progn
(alert "The SAMPLE.DCL file could not be loaded!")
(exit)
)
)
(setq layerList (list "0" "Layer1" "Layer2" "Layer3"
"Layer4" "Layer5" "Layer6" " Layer7"
"Layer8" "Layer9"
)
)
(setq numSides (list "4" "6" "8" "12" "16"))
;;;--- Add the layer names to the dialog box
(start_list "layerList" 3)
(mapcar 'add_list layerList)
(end_list)
;;;--- Add the number of sides to the dialog box
(start_list "numsides" 3)
(mapcar 'add_list numSides)
(end_list)
(mode_tile "numsides" 1)
;;;--- If an action event occurs, do this function
(action_tile "drawcir" "(toggleRadio 1)")
(action_tile "drawpol" "(toggleRadio 2)")
(action_tile "cancel" "(setq ddiag 1)(done_dialog)")
(action_tile
"accept"
"(setq ddiag 2)(saveVars)(done_dialog)"
)
;;;--- Display the dialog box
(start_dialog)
;;;--- Unload the dialog box
(unload_dialog dcl_id)
;;;--- If the cancel button was pressed - display message
(if (= ddiag 1)
(princ "\n \n ...SAMPLE Cancelled. \n ")
)
;;;--- If the "Okay" button was pressed
(if (= ddiag 2)
(princ "\n \n ...SAMPLE Complete!")
)
;;;--- Suppress the last echo for a clean exit
(princ)
(if(= radios "drawcir")
(progn
(setq pt(getpoint "\n Center point: "))
(command "circle" pt pause)
)
;;;--- Else draw a polygon
(progn
(setq pt(getpoint "\n Center Point: "))
(command "polygon" numSides pt "" pause)
)))
(defun saveVars ()
(setq radios (get_tile "radios"))
;;;--- Get the number of sides selected from the list
(setq numStr (get_tile "numsides"))
(if (= numStr "")
(setq numSides nil)
(setq numSides (nth (atoi numStr) numSides))
)
(princ numSides)
(terpri)
;;;--- See if the user wants to save the settings
(setq saveSet (atoi (get_tile "saveset")))
(princ saveSet)
(terpri)
;;;--- Get the selected item from the layer list
(setq sStr (get_tile "layerList"))
(princ "sStr")
(princ sStr)
(terpri)
;;;--- If the index of the selected item is not "" then something was selected
(if (/= sStr "")
(progn
;;;--- Something is selected, so convert from string to integer
(setq sIndex (atoi sStr))
(princ "sindex")
(princ sIndex)
(terpri)
;;;--- And get the selected item from the list
(setq layerName (nth sIndex layerList))
(princ "layerName")
(princ layerName)
(terpri)
)
;;;--- Else, nothing is selected
(progn
;;;--- Set the index number to -1
(setq sIndex -1)
;;;--- And set the name of the selected item to nil
(setq layerName nil)
) )
(setq oldLay(getvar "clayer"))
(setvar "clayer" layerName)
)
(defun toggleRadio(a)
;if circle is selected
(if(= a 1)
(mode_tile "numsides" 1) ;disable
;else
(mode_tile "numsides" 0) ;enable
)
)
И наконец, займемся кодом сохранения установок по умолчанию. В элементах диалога все значения переменных интерпретируются как строки. В AutoCAD поддерживается 15 пользовательских системных переменных сохранения данных. USERR1 - USERR5 используют действительные числа. USERI1 - USERI5 используют целые числа. USERS1 - USERS5 будут сохранять наши данные как строки. Все эти величины доступны в файле чертежа каждый раз при его открытии.
Первой переменной у нас появляется RADIOS, и она уже имеет строковый тип (setvar "USERS1" radios).
Второй переменной является NUMSIDES - целое число сторон многоугольника. Но при чтении значения (value) элемента нам возвращается номер строки типа string: (setvar "USERS2" numStr).
Третья переменная SAVESET имеет тип integer. Поэтому ее нужно конвертировать (setvar "USERS3" (itoa saveSet)) .
Индекс четвертой переменной LAYERNAME сохраним в виде строки:
(setvar "USERS4" sSTR)
Язык DCL (Dialog Control Language) - специальный язык для создания диалоговых окон.
Директива - логически законченная единица программы диалога.
Элементы управления - части интерфейса диалогового окна, к которым имеет доступ пользователь (кнопки, текстовые поля, списки и пр.).
Функции DCL - встроенные функции языка для проведения действий и операций.
Переменные действия - глобальные переменные, в которых сохраняются некоторые дополнительные данные о состоянии диалогового окна и выполненных в нем действий пользователя. Переменные используются в LISP-выражениях, задаваемых в качестве второго аргумента функции action-tile.
Программы вычерчивания фигур должны иметь возможность изменять значения переменных. Это можно сделать либо в коде, либо по запросам в командной строке в процессе выполнения программы. Но удобнее всего выполнять установки в специальных диалоговых окнах. Технология создания таких окон с помощью языка описана в данной лекции.
DCL -файлы?LISP-файлом?dcl -файла load_dialog?action_tile?list_box и popup_list?LISP-программы, которая запускает сценарий отклика на событие выделения радиокнопки в диалоговом окне.Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.