Программирование диалоговых окон на языке DCL
Цель лекции: приобрести навыки работы в построении диалоговых окон.
Технология программирования диалогов
Постановка задачи
Рассмотрим пример программы вычерчивания полого рога с углом изгиба 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.
Рог строился путем экструзии базовой окружности вдоль дуги с раствором 180 градусов. Угол сужения брался равным углу сужения подобного прямого конуса. Полость в роге выполнялась с помощью команды Shell.
При запуске функции qrog пользователь задавал требуемые параметры по запросам программы:
- радиус базовой окружности rad1;
- диаметр направляющей дуги diam1;
- толщину стенки рога thick1;
- индекс цвета col1.
Требуется вместо запросов создать диалоговое окно для одновременного ввода этих параметров.
Создание DCL-файла
Вначале напишем отдельную программу для открытия диалогового окна. В новом чертеже AutoCAD откройте среду Visual LISP по команде Tools - AutoLISP - Visual LISP Editor. По команде File - New File создайте новый файл. Наберите в нем следующий текст программы диалога "rog" на языке DCL. Учтите только, что элементы языка DCL чувствительны к регистру. Все ключевые слова, метки и коды элементов должны состоять только из латинских букв, цифр и символа подчеркивания. Начинаться служебные слова должны с латинской буквы.
//Диалоговое окно установки параметров рога // 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.dcl. Папка Support принадлежит к маршрутам файлов поддержки. Проверьте это еще раз, выполнив команду Tools - Options - Files - Support File Search Path. Чтобы открыть диалоговое окно на экране, система должна загрузить DCL-файл. Эта загрузка может быть выполнена лишь тогда, когда DCL-файл помещен в данную папку. Иначе нужно указывать полный путь к файлу.
Составление директив
Вся написанная программа называется диалогом. В одном файле может быть несколько диалогов. Рассмотрим структуру программы-диалога.
За двойной чертой // до конца строки размещается комментарий. В нашей программе комментарий занимает первые две строки. Далее программа содержит логически законченные единицы - директивы. Каждая директива описывает один элемент (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;}
spacer - это пустой элемент, обозначающий пропуск строки;
height=1; - атрибут height показывает высоту пропущенной строки. Единицей измерения является стандартная высота строки текущего шрифта.
Итак, в сохраненном файле "Rog.dcl" описано диалоговое окно с именем диалога "rog". Окно должно иметь четыре текстовых поля с видимыми в них значениями по умолчанию.
Файл загрузки диалога
Составим теперь LISP-функцию, которая позволяла бы загружать (load_dialog) и выгружать (unload_dialog) DCL-файлы, открывать и закрывать окна загруженных диалогов. В редакторе 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.dcl"), загружающая файл rog.dcl. Если полный адрес файла не указан, то система ищет этот файл по стандартному алгоритму поиска файлов поддержки. Если загрузка прошла успешно, то функция load_dialog возвращает положительное целое число, которое присваивается переменной num. Если загрузка не выполнилась, то возвращается отрицательное число. В этом случае выполняется функция exit, прерывающая работу приложения.
В третьей строке проверяется, имеется ли в загруженном DCL-файле rog.dcl диалог с именем "rog", имеющий номер num. Если такого диалога в файле нет, то программа завершается с помощью функции exit. Если такой диалог есть, то активируется диалоговое окно, управление передается функции start_dialog. Эта функция возвращает 1, если пользователь выйдет из диалогового окна с помощью кнопки OK или 0, если пользователь выйдет из диалогового окна с помощью кнопки Cancel.
В пятой строке функция unload_dialog num выгружает файл из оперативной памяти. Возвращаемое значение - nil.
Загрузите файл, перейдите в AutoCAD и наберите в командной строке show_rog. На экране появится диалоговое окно (рис. 6.2).
Установите параметры в текстовых полях. Щелкните по кнопке ОК. Окно исчезнет с экрана. Файл rog.dcl выгрузится из оперативной памяти. Чтобы воспользоваться результатами работы с окном, нужна программа, анализирующая введенные величины.
Обработка вводимых данных
Исключим из программы черчения рога приглашения задать параметры рога и включим обращение к диалогу "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.