Опубликован: 21.02.2012 | Доступ: свободный | Студентов: 2061 / 499 | Оценка: 4.20 / 4.40 | Длительность: 19:35:00
Специальности: Разработчик аппаратуры
Лекция 6:

Программирование диалоговых окон на языке DCL

Составление списка вручную:

(setq layerList(list "0" "Layer1" " Layer2" " Layer3" " Layer4" " Layer5" "Layer6" " Layer7" " Layer8" " Layer9"))

То же самое для числа сторон многоугольника:

(setq numSides(list "4" "6" "8" "12" "16"))

Добавим эти строки в описание диалога DCL-файла.

;;;--- 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) в AutoLisp-программе:

(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 описана в данной лекции.

Вопросы

  1. Где нужно сохранять DCL-файлы?
  2. Через какой атрибут директивы устанавливается связь диалога с LISP-файлом?
  3. Что возвращает функция загрузки dcl-файла load_dialog?
  4. Каково назначение функции action_tile?
  5. Какие функции производят операции редактирования списков в элементах list_box и popup_list?
  6. Составьте алгоритм работы LISP-программы, которая запускает сценарий отклика на событие выделения радиокнопки в диалоговом окне.
Алексей Тимонин
Алексей Тимонин
Алексей Потапкин
Алексей Потапкин

Здравствуйте.

Подскажите, пожалуйста, каким образом можно передать параметры в макрос написанный в Autocad на VBA? Например, есть процедура, которая отрисовывает заштрихованный прямоугольник (см. ниже). Как её изменить, чтобы на входе от пользователя требовалось ввести также в качестве параметров координаты углов прямоугольника?

Public Sub DrawHatchedBox()

...

End Sub