Возвращаясь к dcl – написание, обработка, отладка

Пока свежо в памяти, решил рассказать, как я разрабатываю функции, использующие dcl-окна.

Допустим, нам необходимо, чтобы функция выводила окошко с определенным нами сообщением и двумя кнопками - OK и Cancel. Для усложнения задачи добавим текстовое поле и флажковый переключатель, который будет менять режим доступности текстового поля.

Итак, прежде всего - создаем временный dcl-файл и прописываем сам диалог. Это мне требуется только для того, чтобы проверить - как окно будет выглядеть в результате. Допустим, создали, проверили - все замечательно.

1
2
3
4
5
6
dlg:dialog{label="Диалог";
  :text{key="msg";}
  :toggle{key="chk_edit";label="Редактировать текст";}
  :edit_box{key="txt_edit";width=50;}
  ok_cancel;
  }

После этого пишется функция, которая будет создавать временный dcl-файл в каталоге %temp% (к примеру) и возвращать полное имя такого файла.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(defun fun_create-dcl-file (/ file handle)
  ;; Возвращает имя файла dcl
  (setq file   (strcat (vl-string-right-trim "\\" (getenv "tmp")) "\\dlg.dcl")
        handle (open file "w")
        ) ;_ end of setq
  (foreach item '("dlg:dialog{label=\"Диалог\";"                " :text{key=\"msg\";}"
                  " :toggle{key=\"chk_edit\";label=\"Редактировать текст\";}"
                  " :edit_box{key=\"txt_edit\";width=50;} "
                  " ok_cancel;"                             " }"
                  )
    (write-line item handle)
    ) ;_ end of foreach
  (close handle)
  file
  ) ;_ end of defun

Теперь приступаем к разработке основной функции.
После стандартных строк

1
2
3
(setq dcl_file (fun_create-dcl-file)
      dcl_id   (load_dialog dcl_file)
      ) ;_ end of setq

по идее должно идти нечто типа

1
(new_dialog "dlg" dcl_id)

Но обратимся к справке (мой вольный перевод):

1
(new_dialog dlgname dcl_id [action [screen-pt]])

Аргументы

dlgname Строка, определяющая создаваемый диалог (в одном dcl-файле может быть описано несколько диалогов; главное, чтобы у них имена были уникальными)
dcl_id Идентификатор, созданный через функцию (load_dialog...)
action Необязательный параметр. Строка, содержащая выражение на языке AutoLISP, являющееся реакцией по умолчанию на изменение любого элемента диалога. Строка становится обязательной, если определяется следующий параметр. Допускается применение пустой строки ("")
screen-pt Координаты двумерной точки, определяющие положение левого верхнего угла окна диалога на экране.

Куски справки, не являющиеся критичными, я пропустил.

То есть получается, что в

1
(new_dialog "dlg" dcl_id)

можно указать какую-то дополнительную "callback"-функцию, которая и будет срабатывать по умолчанию! Отлично, нарисуем?

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

1
2
3
4
5
6
7
8
9
(defun fun_dlg-callback (key value reflist)
                        ;|
*    Функция реакции на элементы диалога
*    Параметры вызова:
  key       ключ элемента диалога
  value     установленное значение
  reflist   ссылка на переменную, в которой храним все данные. Передавать только по ссылке
|;

 ) ;_ end of defun

Если ключ у нас chk_edit, то действия одни, если txt_edit - другие, ну и т.п. Понятно, что используем конструкцию cond:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(defun fun_dlg-callback (key value reflist)
                        ;|
*    Функция реакции на элементы диалога
*    Параметры вызова:
  key       ключ элемента диалога
  value     установленное значение
  reflist   ссылка на переменную, в которой храним все данные. Передавать только по ссылке
|;

  (cond
    ((and (= key "chk_edit") (= value "0"))
     ;; Отжат chk_edit
     (mode_tile "txt_edit" 1) ; txt_edit -> недоступен
     )
    ((and (= key "chk_edit") (= value "1"))
     ;; ch_edit нажат
     (mode_tile "txt_edit" 0) ; txt_edit -> доступен
     )
    ((= key "txt_edit")
     ;; Изменен текст
     )
    ) ;_ end of cond
  ) ;_ end of defun

Теперь надо каким-то манером менять reflist. Понятно, что reflist - список из точечных пар ("ключ элемента диалога" . "значение элемента диалога"). Если пара с таким ключом в списке есть, то надо менять ее значение. Если нет - то добавить. Чтобы не множить код, создадим отдельную функцию:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(defun fun_add-or-subst (lst key value)
                        ;|
*    Добавление или замена точечной пары
*    Параметры вызова:
  lst    обрабатываемый список
  key    ключ
  value  значение
|;

  (if (assoc key lst)
    (subst (cons key value)
           (assoc key lst)
           lst
           ) ;_ end of subst
    (cons (list (cons key value)) lst)
    ) ;_ end of if
  ) ;_ end of defun

Теперь меняем fun_dlg-callback (в целях демонстрации добавлены alert'ы):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(defun fun_dlg-callback (key value reflist)
                        ;|
*    Функция реакции на элементы диалога
*    Параметры вызова:
  key       ключ элемента диалога
  value     установленное значение
  reflist   ссылка на переменную, в которой храним все данные. Передавать только по ссылке
|;

  (cond
    ((and (= key "chk_edit") (= value "0"))
     ;; Отжат chk_edit
     (mode_tile "txt_edit" 1) ; txt_edit -> недоступен
     (set reflist (fun_add-or-subst (eval reflist) key t))
     (alert "chk_edit -> 0")
     )
    ((and (= key "chk_edit") (= value "1"))
     ;; ch_edit нажат
     (mode_tile "txt_edit" 0) ; txt_edit -> доступен
     (set reflist (fun_add-or-subst (eval reflist) key nil))
     (alert "chk_edit -> 1")
     )
    ((= key "txt_edit")
     ;; Изменен текст
     (set reflist (fun_add-or-subst (eval reflist) key (vl-string-trim " " value)))
     (set_tile "msg" (strcat (cdr (assoc "msg" (eval reflist))) " " (cdr (assoc key (eval reflist)))))
     (alert "txt_edit")
     )
    ) ;_ end of cond
  ) ;_ end of defun

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(defun fun_dlg-execute (/ dcl_file dcl_id dcl_lst dcl_res)
                       ;|
*    Собственно вызов диалога
|;

  (setq dcl_file (fun_create-dcl-file)
        dcl_id   (load_dialog dcl_file)
        dcl_lst  '(("chk_edit" . "1") ("txt_edit" . "Введите текст") ("msg" . "Сообщение:"))
        ) ;_ end of setq
  (new_dialog "dlg" dcl_id "(fun_dlg-callback $key $value 'dcl_lst)")
  (action_tile "accept" "(done_dialog 1)")
  (action_tile "cancel" "(done_dialog 0)")
  (foreach item dcl_lst
    (set_tile (car item) (cdr item))
    (fun_dlg-callback (car item) (cdr item) 'dcl_lst)
    ) ;_ end of foreach
  (setq dcl_res (start_dialog))
  (unload_dialog dcl_id)
  (if (= dcl_res 1)
    (alert "Была нажата OK")
    (alert "Была нажата Отмена (Cancel)")
    ) ;_ end of if
  ) ;_ end of defun

Что дает такой подход?

  1. Код достаточно легко расширять: достаточно в callback прописать обработку нового ключа
  2. Отладка кода перестает быть мучительной и слабовыполнимой задачей: в callback ставится точка останова и все!

P.S. Коды отдельно не выкладываю - статья носит характер шпаргалки ;)

Размещено в AutoCAD, Код LISP, Функции LISP · Метки: , ,



Комментарии

Есть 19 коммент. к “Возвращаясь к dcl – написание, обработка, отладка”
  1. Vladimir_Sergeevich пишет:

    Нашел маленькую ошибочку в fun_add-or-subst
    при добавлении нового элемента (cons (list (cons key value)) lst) будет работать неадекватно
    тут надо (append (list (cons key value)) lst)
    И по теме в целом:
    Хотел написать простенькое окошко с радиокнопками и ни в какую не получалось вытащить указанный вариант, но не об этом хочу спросить. Идею то общую понял.
    Как то не хватает понимания как dcl взаимодействует с lisp, а именно с возвращает значения. У Полещука все туманно, а тут стало еще запущенней. В итоге пошел по другому пути, но разобраться бы не помешало для общего развития.

  2. Кулик Алексей aka kpblc пишет:

    Да, сорри, ступил :)

    А так-то ситуация проста до ужаса: в отдельную ссылку передаем по значению ключ контрола, его значение - тоже по значению; и общий список всех установленных контролов - но уже по ссылке. И вот этот последний параметр и меняем.
    Можно заменить немного работу: передавать только ключ и значение, а менять "глобальный" список. Может быть, такой код будет проще понять:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    (defun fun_add-or-subst (lst key value)
                            ;|
    *    Добавление или замена точечной пары
    *    Параметры вызова:
      lst    обрабатываемый список
      key    ключ
      value  значение
    |;

      (if (assoc key lst)
        (subst (cons key value)
               (assoc key lst)
               lst
               ) ;_ end of subst
        (cons (cons key value) lst)
        ) ;_ end of if
      ) ;_ end of defun

    (defun fun_dlg-callback (key value)
                            ;|
    *    Функция реакции на элементы диалога
    *    Параметры вызова:
      key       ключ элемента диалога
      value     установленное значение
      reflist   ссылка на переменную, в которой храним все данные. Передавать только по ссылке
    |;

      (cond
        ((and (= key "chk_edit") (= value "0"))
         ;; Отжат chk_edit
         (mode_tile "txt_edit" 1) ; txt_edit -> недоступен
         (setq dcl_lst (fun_add-or-subst dcl_lst key t))
         (alert "chk_edit -> 0")
         )
        ((and (= key "chk_edit") (= value "1"))
         ;; ch_edit нажат
         (mode_tile "txt_edit" 0) ; txt_edit -> доступен
         (setq dcl_lst (fun_add-or-subst dcl_lst key nil))
         (alert "chk_edit -> 1")
         )
        ((= key "txt_edit")
         ;; Изменен текст
         (setq dcl_lst (fun_add-or-subst dcl_lst key (vl-string-trim " " value)))
         (set_tile "msg" (strcat (cdr (assoc "msg" dcl_lst)) " " (cdr (assoc key dcl_lst))))
         (alert "txt_edit")
         )
        ) ;_ end of cond
      ) ;_ end of defun

    (defun fun_dlg-execute (/ dcl_file dcl_id dcl_lst dcl_res)
                           ;|
    *    Собственно вызов диалога
    |;

      (setq dcl_file (fun_create-dcl-file)
            dcl_id   (load_dialog dcl_file)
            dcl_lst  '(("chk_edit" . "1") ("txt_edit" . "Введите текст") ("msg" . "Сообщение:"))
            ) ;_ end of setq
      (new_dialog "dlg" dcl_id "(fun_dlg-callback $key $value)")
      (action_tile "accept" "(done_dialog 1)")
      (action_tile "cancel" "(done_dialog 0)")
      (foreach item dcl_lst
        (set_tile (car item) (cdr item))
        (fun_dlg-callback (car item) (cdr item))
        ) ;_ end of foreach
      (setq dcl_res (start_dialog))
      (unload_dialog dcl_id)
      (if (= dcl_res 1)
        (alert "Была нажата OK")
        (alert "Была нажата Отмена (Cancel)")
        ) ;_ end of if
      ) ;_ end of defun

    (defun fun_create-dcl-file (/ file handle)
      ;; Возвращает имя файла dcl
      (setq file   (strcat (vl-string-right-trim "\" (getenv "tmp")) "\\dlg.dcl")
            handle (open file "
    w")
            ) ;_ end of setq
      (foreach item '("
    dlg:dialog{label="Диалог";"                   " :text{key="msg";}"
                      " :toggle{key="chk_edit";label="Редактировать текст";}"
                      " :edit_box{key="txt_edit";width=50;} "        " ok_cancel;"
                      " }"
                      )
        (write-line item handle)
        ) ;_ end of foreach
      (close handle)
      file
      ) ;_ end of defun

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

  3. Vladimir_Sergeevich пишет:

    Насколько я понимаю сейчас механизм:
    -при изменении любого параметра в диалоговом окне каждый раз вызываются все функции между (new_dialog... и (start_dialog), в том числе и fun_dlg-callback
    -если нажаты ок/отмена - окно закрывается
    -при изменении текста меняется список (set reflist (fun_add-or-subst (eval reflist) key (vl-string-trim " " value)))
    или во втором варианте напрямую (setq dcl_lst (fun_add-or-subst dcl_lst key nil))
    Но вот привязать это к своей ситуации не получается. у меня 4 радиокнопки '(("culvert1" . 1) ("culvert2" . 0) ("culvert3" . 0) ("culvert4" . 0)) ;;первая включена по умолчанию
    Сколько не переключаю варианты возвращает то же самое. Подозреваю, что надо обращаться не к :radio_button, а к :radio_column, но у него вроде как нет значений key и value. (по крайней мере в примерах Полещука не показаны)
    Где я не прав?

  4. Кулик Алексей aka kpblc пишет:

    Нет, неправильно :)
    При вызове (new_dialog...) по умолчанию прописывается реакция на все контролы. Потом принудительно прописываются "уникальные" реакции (action_tile ).
    При обработке диалога вызывается соответствующая фунция. При клике на чекбоксе - fun_dlg-callback, в которую передается как раз ключ нажатого контрола и его текущее значение (сейчас говорю про второй код). И уже fun_dlg-callback обрабатывает все что надо и как надо. Утрируя и упрощая, можно получить следующее:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    (defun fun_add-or-subst (lst key value)
                            ;|
    *    Добавление или замена точечной пары
    *    Параметры вызова:
      lst    обрабатываемый список
      key    ключ
      value  значение
    |;

      (if (assoc key lst)
        (subst (cons key value)
               (assoc key lst)
               lst
               ) ;_ end of subst
        (cons (cons key value) lst)
        ) ;_ end of if
      ) ;_ end of defun

    (defun fun_dlg-callback (key value reflist)
                            ;|
    *    Функция реакции на элементы диалога
    *    Параметры вызова:
      key       ключ элемента диалога
      value     установленное значение
      reflist   ссылка на переменную, в которой храним все данные. Передавать только по ссылке
    |;

      (cond
        ((= key "op1")
         (set reflist (fun_add-or-subst reflist "key" 1))
         )
        ((= key "op2")
         (set reflist (fun_add-or-subst reflist "key" 2))
         )
        ((= key "op3")
         (set reflist (fun_add-or-subst reflist "key" 3))
         )
        ((= key "op4")
         (set reflist (fun_add-or-subst reflist "key" 4))
         )
        ) ;_ end of cond
      ) ;_ end of defun

    (defun fun_dlg-execute (/ dcl_file dcl_id dcl_lst dcl_res)
                           ;|
    *    Собственно вызов диалога
    |;

      (setq dcl_file (fun_create-dcl-file)
            dcl_id   (load_dialog dcl_file)
            dcl_lst  '(("opt1" . "1"))
            ) ;_ end of setq
      (new_dialog "dlg" dcl_id "(fun_dlg-callback $key $value 'dcl_lst)")
      (action_tile "accept" "(done_dialog 1)")
      (action_tile "cancel" "(done_dialog 0)")
      (foreach item dcl_lst
        (set_tile (car item) (cdr item))
        (fun_dlg-callback (car item) (cdr item) 'dcl_lst)
        ) ;_ end of foreach
      (setq dcl_res (start_dialog))
      (unload_dialog dcl_id)
      (if (= dcl_res 1)
        (alert "Была нажата OK")
        (alert "Была нажата Отмена (Cancel)")
        ) ;_ end of if
      ) ;_ end of defun

    (defun fun_create-dcl-file (/ file handle)
      ;; Возвращает имя файла dcl
      (setq file   (strcat (vl-string-right-trim "\" (getenv "tmp")) "\\dlg.dcl")
            handle (open file "
    w")
            ) ;_ end of setq
      (foreach item '("
    dlg:dialog{label="Диалог";"
                      " :text{key="msg";}"
                      " :radio_button{key="opt1";label="Radio 1";}"
                      " :radio_button{key="opt2";label="Radio 2";}"
                      " :radio_button{key="opt3";label="Radio 3";}"
                      " :radio_button{key="opt4";label="Radio 4";}"
                      " ok_cancel;"
                      " }"
                      )
        (write-line item handle)
        ) ;_ end of foreach
      (close handle)
      file
      ) ;_ end of defun

  5. Vladimir_Sergeevich пишет:

    А... как то я упустил из виду строчку (new_dialog "dlg" dcl_id "(fun_dlg-callback $key $value 'dcl_lst)") и у себя пустую строку загнал.
    Зато сходу другой косяк. на каждую трубу прописано:
    ((and (= key "culvert1") (= value "1"))
    ;; выбран первый
    (setq dlg_lst (sad-add-or-subst dlg_lst key value))

    )
    ((and (= key "culvert1") (= value "0"))
    ;; выбран первый
    (setq dlg_lst (sad-add-or-subst dlg_lst key value))[cc lang="lisp"]
    при нажатии на радиокнопку значение меняется на 1 у нажатого и не обнуляется у того что был раньше. в итоге, понажимав "в раздумьях" все варианты, получаю ((culvert1 . 1) (culvert2 . 1) (culvert3 . 1) (culvert4 . 1)) - то есть выбраны все варианты XD
    Получается надо не условие для кнопки со значением 0, а при назначении одной принудительно сбрасывать остальные при выборе
    Судя по всему тут уже надо не списком оперировать, точнее для всех радиокнопок предусмотреть один элемент списка с кучей возможных вариантов.
    В общем все заработало :-) хоть уже конкретно этого окна не надо, потому как уже дописал автоматическое определение типа трубы по содержимому чертежа.
    Спасибо за пояснения.

  6. Кулик Алексей aka kpblc пишет:

    Ну писал я на бегу ))) принцип понятен? :)

  7. Vladimir_Sergeevich пишет:

    Одного не понял.

    1
    2
    3
    4
     (foreach item dcl_lst
        (set_tile (car item) (cdr item))
        (fun_dlg-callback (car item) (cdr item) 'dcl_lst)
        ) ;_ end of foreach

    Зачем тут нужен (fun_dlg-callback (car item) (cdr item) 'dcl_lst), если он прописан в (new_dialog...
    У себя закомментировал - результат не поменялся...

  8. Кулик Алексей aka kpblc пишет:

    А если в dcl_lst поменять '(("opt1" . "1")) на '(("opt3" . "1")) ? :)
    Это просто установка начальных значений диалога )))

  9. Vladimir_Sergeevich пишет:

    кажись доперло :-)
    То есть тут для каждого set_tile сразу же и fun_dlg-callback следом. Мне он особо и нужен был в моем случае - начальные параметры заданы прямо в dcl и set_tile не использовался.

  10. Кулик Алексей aka kpblc пишет:

    ИМХО самое неудачное решение. Стартовые значения могут быть прочитаны из реестра, из стороннего файла, могут задаваться вообще на основе каких-то параметров - ну не править же каждый раз текст диалога?

  11. Vladimir_Sergeevich пишет:

    Что еще раз доказывает, что не дорос я еще до серьезного программирования. До идеи запоминать значения сам как то не допер. :-)

  12. Кулик Алексей aka kpblc пишет:

    Ну, "мы все учились понемногу" :) Я тоже не сразу до такого дошел ))

  13. Кулик Алексей aka kpblc пишет:

    Во, пока вспомнил: я здесь где-то расписывал варианты хранения данных между функциями, файлами и сессиями AutoCAD. Может быть, будет полезным.

  14. Vladimir_Sergeevich пишет:

    Алексей, спасибо за наводку. Как надо будет - поищу. Пока что такой необходимости не было. Я между делом читал "САПР на базе..." там тоже был раздел посвящен, представление имею что искать надо.

  15. gomer пишет:

    При всем уважении, но статья - бред от начала до конца.
    Во-первых, создание диалога налету - параноидальный мусор. Достаточно скомпилировать код в vlx-модуль и диалог никуда не потеряется.
    Во-вторых, call-back функция заменяет, чуть более, чем полностью, action_tile, которая становится абсолютно не нужна...
    В-третьих,
    (foreach item dcl_lst
    (set_tile (car item) (cdr item))
    (fun_dlg-callback (car item) (cdr item) 'dcl_lst)
    ) ;_ end of foreach
    Этот бред я вообще не понял... call-back функция вызывается всего один раз перед стартом диалога!
    В-четвертых, call-back- функция не нуждается ни в каких параметрах. Есть встроенные переменные $key и т.д. Причем при открытии диалога $key всегда равен nil. Достаточно в call-back функцию добавить проверку (null $key), чтоб заполнять диалог прямо в call-back функции.
    В-пятых, в call-back функции должны быть описаны только управляющие элементы: всегда кнопки, в отдельных случаях списки, радиокнопки и чекбоксы. А не все подряд...
    В итоге весь код диалога сосредоточен в call-back функции, а для вызова ее достаточно 5 строчек, которые можно оформить в виде библиотечной функции в 1 строчку.

    Все это описано в справке, поэтому я не вижу причин для подобного велосипедостроения.

  16. Кулик Алексей aka kpblc пишет:

    Прежде всего - предоставляется один lsp. Кроме того, при совместной компиляции нескольких сотен lsp, некоторые из которых используют диалоги, делать vlx нерентабельно. Сейчас dcl у меня создаются именно "на лету", в некоторых случаях они формируются на основе внешних данных. Очень удобно.

    call-back функция вызывается всего один раз перед стартом диалога!

    Кто сказал? Она вызывается ровно так же, как и любая другая функция.

    call-back- функция не нуждается ни в каких параметрах.

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

    в call-back функции должны быть описаны только управляющие элементы: всегда кнопки, в отдельных случаях списки, радиокнопки и чекбоксы. А не все подряд…

    И снова - кто это сказал? С чего бы вдруг мне не описать в функции, которую я разрабатываю то, что лично мне нужно? Странный подход - "нельзя потому что нельзя". Можно! :)

    Все это описано в справке, поэтому я не вижу причин для подобного велосипедостроения.

    Ок, бога ради. Тот принцип, который я описал и который использую, на данный момент оправдывает все вложения.

  17. Кулик Алексей aka kpblc пишет:

    О, в качестве иллюстрации: http://forum.dwg.ru/showpost.php?p=1435329&postcount=66 (код не смотрел, не до того). Если бы построение диалога шло "на лету", вопросов бы вообще не возникло никаких.
    P.S. Я в принципе не доверяю vlx / fas кодам, предоставляемым без исходников. А если есть исходники - тут же перекомпилирую.

  18. gomer пишет:

    kpblc, то,что твой код работает, не делает его оптимальным. Смотри ниже то, о чем я написал, и сравнивай. Если убрать функцию создания файла, то станется кода с гулькин хвост.

    (defun fun_dlg-execute
    (/ dcl_file dcl_id dcl_lst dcl_res dcl_proc)

    (defun dcl_proc ()
    (cond
    ((null $key)
    (set_tile "opt" "opt1")
    (set_tile "msg" "Выбери опцию")
    )

    ((= $key "cancel")
    (done_dialog 0)
    )

    ((= $key "accept")
    (setq dcl_lst (list (get_tile "opt")))
    (done_dialog 1)
    )

    ) ;_ end of cond
    ) ;_ end of defun

    (setq dcl_file (fun_create-dcl-file)
    dcl_id (load_dialog dcl_file)
    ) ;_ end of setq

    (new_dialog "dlg" dcl_id "(dcl_proc)")
    (dcl_proc)
    (setq dcl_res (start_dialog))
    (unload_dialog dcl_id)

    (if (= dcl_res 1)
    (alert "Была нажата OK")
    (alert "Была нажата Отмена (Cancel)")
    ) ;_ end of if

    dcl_lst

    ) ;_ end of defun

    (defun fun_create-dcl-file (/ file handle)
    ;; Возвращает имя файла dcl
    (setq file (strcat (vl-string-right-trim "\\" (getenv "tmp"))
    "\\dlg.dcl"
    )
    handle (open file "w")
    ) ;_ end of setq
    (foreach item '("dlg:dialog{label=\"Диалог\";"
    " :text{key=\"msg\";}"
    " :boxed_radio_column{key =\"opt\";"
    " :radio_button{key=\"opt1\";label=\"Radio 1\";}"
    " :radio_button{key=\"opt2\";label=\"Radio 2\";}"
    " :radio_button{key=\"opt3\";label=\"Radio 3\";}"
    " :radio_button{key=\"opt4\";label=\"Radio 4\";}}"
    " ok_cancel;"
    "}"
    )
    (write-line item handle)
    ) ;_ end of foreach
    (close handle)
    file
    ) ;_ end of defun

  19. Кулик Алексей aka kpblc пишет:

    Ок. Фактически мы с тобой спорим ни о чем. У тебя в callback-функции используется "почти глобальные" переменные $key, $value и dcl_lst. Если от них попытатся избавиться, то получится примерно мое творчество. Да, action для accept и cancel я прописываю в функции вызова диалога - извини, привычка. А в остальном - что в лоб, что по лбу. ИМХО абсолютно одинаковые коды.

Поделитесь своим мнением


Я не робот.