明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 21848|回复: 55

[原创] 出错处理的点滴经验

  [复制链接]
发表于 2007-3-30 17:22:00 | 显示全部楼层 |阅读模式
               出错处理函数的浅析
                       暨
           Acet-error-init 的“解密”
======================================================================
【文    章】  caoyin·LongfinTools
【引用资源】  部分 Lisp 的源代码来自 AutoCAD R14 BONUS
              Copyright (C) 1997 by Autodesk, Inc.
======================================================================
■■■■ 0 前言
    自一年前邂逅明经通道以来,开始学习 LISP ,收获真的不少。虽然自己的
水平还十分浅薄,但仍欣慰之至。
    我收集并总结了 LISP 出错处理函数的点滴经验,与大家分享。希望能得到
大家的指点和批评。
■■■■ 1 浅析定义出错处理函数的常犯的错误
    ■■ 1.1 概念及其编程应用的意义
      
            我们知道 *error*  函数是用来执行程序出错时进行相关错误处理
        的特殊函数操作。就调用方式而言,大家都很熟悉。所以我们要讨论的
        不是技术问题,而是它对我们编程应用的意义。
            一个完整的程序应该具备一个周全的出错处理。因此,出错处理函
        数我们就会频繁的使用。怎样让我们自定义的出错处理能够应对各种各
        样的出错情况呢?
            通常我们的出错处理函数会分为三部分来定义:
        a. 定义初始化设置,如保存 *error* 的当前值,将自定义的出错函数
        赋名为 *error*,放置 UNDO 的开始标记,保存系统变量信息并设置新
        值等等。★这部分通常被放在程序的开始。
        b. 定义自己的 *error*,在出错时自动激活该函数。执行必要的 UNDO
        恢复,系统变量恢复,初始化设置中的全局变量恢复以及其他的图形操
        作等。
        c. 定义正常退出的恢复设置。★这部分通常被放在程序的结束。
        基本的格式如下:
        ;;------------------------------------------------------------
        ;;例1    这是大多数人的写法
        (defun xxx-begin (varlst / cmd)
          (setq cmd (getvar "cmdecho"))
          (setvar "cmdecho" 0)
          (command "_.undo" "_begin");放置UNDO开始标记
          (setvar "cmdecho" cmd)
          (setq $savvarlst (mapcar '(lambda (x)
                                     (list x (getvar x))
                                    )
                                   varlst
                           )         ;系统变量保存及设置
                $olderr    *error*   ;保存 *error* 的当前值
                *error*    xxx-error ;自定义的出错函数赋名为 *error*
          )
          ;...
        )
        (defun xxx-error (msg)
          (princ msg)                ;打印出错信息
          (xxx-end)                  ;调用自定义函数 xxx-end
          ;...                       ;其他出错处理
        )
        (defun xxx-end (/ cmd)
          (if $savvarlst
            (mapcar '(lambda (x)
                      (apply 'setvar x)
                     )
                    $savvarlst
            )                        ;系统变量恢复到初始设置
          )
          (setq *error*    $olderr   ;*error* 恢复到初始设置
                $savvarlst nil       ;全局变量设置为 nil
                $olderr    nil
          )
          (setq cmd (setvar "cmdecho"))
          (setvar "cmdecho" 0)
          (command "_undo" "_end")   ;放置 UNDO 的结束标志
          (setvar "cmdecho" cmd)
          (princ)
        )
        ;;------------------------------------------------------------
        看上去似乎可以了,但在一些特定的情况下还会出错,它仍然不具备通
        用性。
            我们在下面具体分析。

    ■■ 1.2 通用性及出错可能性分析
            我们在出错处理函数要完成的基本任务,通常包括以下几个要素,
        大家可以检验一下自己写的出错函数能否胜任以下要求。
        a. 系统变量设置
            ◇当程序被用户取消或出现错误而中止能否恢复。
            ◇中途设置的(非在初始时设置的)的系统变量,当程序被用户取消
              或出现错误而中止能否恢复。
              用上面(例1)的函数举例如下:
              ;例2---------------------------------------------------
              (defun c:test (/ os)
                (xxx-begin '("cmdecho" "skpoly" "cecolor"))
                (setvar "cmdecho" 0)
                (setvar "skpoly" 1)
                (setvar "cecolor" "1")
                ;...
                (setq os (getvar "osmode"))
                (setvar "osmode" 3333)
                ;...
                ;;出错点,在此按 ESC
                ;...
                (setvar "osmode" os)
                (xxx-end)
              )
              ;-------------------------------------------------------
              在运行以上程序时用户按下 "ESC" ,相信 "cmdecho" "skpoly"
              "cecolor" 能够恢复原值,但 "osmode" 就不行了。
              --------------------------------------------------------
              问:为什么不在初试时的函数中设置?
              答:假如在复杂程序中可能会套嵌调用初始化函数,然 *error*
                  设置只能有一个。
                  (defun c:test (/ ttt)
                    (xxx-begin '("cmdecho" "skpoly" "cecolor"))
                    ...
                    (defun ttt ()
                      (xxx-begin '("osmode"))
                      ...
                    )
                    ...
                  )
              问:为什么不在 xxx-error 中补充定义?
              答:补充定义的 xxx-error 只能适用当前的程序。我们要求的是
                  能够在任意的程序中调用,这就是我讲的“通用性”。
              ---------------------------------------------------------
              其实我们只要把例2中的
                (setq os (getvar "osmode"))
                (setvar "osmode" 3333)
                ...
                ***出错点
                ...
                (setvar "osmode" os)
              改成:
                (setq $savvarlst
                      (cons (list "osmode" (getvar "osmode"))
                            $savvarlst
                      )
                )
                (setvar "osmode" 3333)
                ;...
                ;;出错点,在此按 ESC
                ;...
              就行了,这我们在后面讨论。
        b. UNDO 设置
            谈论 UNDO 设置之前我们可能有必要来了解一下系统变量 UNDOCTL
        的相关设置。下面是 AUTOCAD 的帮助:
        ---------------------------------------------------------------
        (只读)
        类型      整数
        保存位置  尚未保存
        初始值    21
        指示 UNDO 命令的“自动”、“控制”和“编组”选项的状态。 系统将
        使用下列位码值之和将该设置存储为一个位码:
        0    UNDO 关闭
        1    UNDO 打开
        2    只能放弃一条命令
        4    打开“自动”
        8    一个编组处于当前活动状态
        16   将缩放和平移操作编组为单个操作
        ---------------------------------------------------------------
        看完上面的帮助,我们来用(例1)中的函数来作测试:
        ;例3-----------------------------------------------------------
        ;我们先作如下操作:
        (command "_.undo" "_control" "_none")
        ;然后我们来测试
         (xxx-begin '())
        ;结果返回命令行操作错误信息:"无效的选项关键字。"
        ;--------------------------------------------------------------
        为什么呢?其实错误在于 xxx-begin 函数中的
            (command "_.undo" "_begin")
        因为我们执行了
            (command "_.undo" "_control" "_none")
        操作之后 UNDO 命令的关键字发生了变化,如下:
           “输入 UNDO 控制选项 [全部(A)/无(N)/一个(O)/合并(C)] <全部>:”

        所以我们需要根据系统变量 UNDOCTL 的值,而对症下药。然而由于该变量
        为只读属性,SETVAR 对它无效。所以我们必须通过命令行操作来完成相关
        设置。

        c. 程序出错后的操作
            同样以上面的例1的函数为例:
        ;例4-------------------------------------------------------------
         (defun c:test (/ p1 p2 e p3)
           (xxx-begin '("osmode"))
           (initget 1)
           (setq p1 (getpoint "\n指定点1: "))
           (initget 1)
           (setq p2 (getpoint p1 "\n指定点2: "))
           (command "_.line" p1 p2 "")
           (setq e (entlast))
           (redraw e 3)
           (initget 1)
           (setq p3 (getpoint p2 "\n指定点3 (或在此按 ESC): ")) ;;出错点
           (command "_.line" p2 p3 "")
           (redraw e 4)
           (xxx-end)
         )
         ;---------------------------------------------------------------
         正常运行例4的程序第一个对象被高亮显示后被恢复,而中途出错的则无法
         恢复。

         d. 先选后执行的功能
             我们知道当 (= 1 (logand 1 (getvar "pickfirst")))  返回 T 的情
         况下我们可以先选择对象,而后执行命令操作。如命令 MOVE、COPY 等。
         但是例1的函数在此则无法实现。为什么呢?
             原来我们先选后,然后执行 xxx-begin 中的
         (command "_.undo" "_begin")
         后先选的对象被取消了。
             ActiveX 的方法不失为一种好方法:
         ;---------------------------------------------------------------
         ;初始时
         (setq $acaddoc (vla-get-activedocument (vlax-get-acad-object)))
         (vla-startundomark $acaddoc)
         ;结束时
         (if $acaddoc
           (progn (vla-endundomark $acaddoc) (setq $acaddoc nil))
         )
         ;---------------------------------------------------------------
         上面的方法优劣参半:
             优点--是既能够实现先选后执行的功能,又避免了系统变量 cmdecho
                   的设置。
             缺点--它在理论上等价于
                   (command "_undo" "_begin") 和
                   (command "_undo" "_end")
                   也存在我们在例 3 中的问题。
         于是我们只能在调用 xxx-begin 开始加上以下代码:
         (if (= 1 (logand 1 (getvar "pickfirst")))
           (setq ss (ssgetfirst))
         )
         而在调用 xxx-begin 结束加上以下代码:
         (if (apply 'or ss)
           (apply 'sssetfirst ss)
         )


■■■■ 2 Acet-error-init Acet-error Acet-error-restore 的“解密”
    ■■ 2.1 本程序根据 AutoCAD R14 BONUS 的源码修改,源程序中有不少 bug
         这里做了修正。
    ■■ 源代码
  1. ;;; ┏━━━┳━━━━━━━━━━━━━━━━━━━┓
  2. ;;; ┃  LT: ┃ 出错处理函数                         ┃
  3. ;;; ┗━━━┻━━━━━━━━━━━━━━━━━━━┛
  4. ;;  曹饮整理修改
  5. ;;____________________________________________________________________________________________________
  6. ;; 〓 (lt:error-init lst) 〓
  7. ;;  [功能] 出错处理初始化
  8. ;;  [参数] lst---表(元素1 元素2 元素3)
  9. ;;               元素1:  包含系统变量及其值的列表
  10. ;;               元素2:  nil--->不操作
  11. ;;                       0----->放置 UNDO 的 BEGIN 和 END 标志
  12. ;;                       1或T-->放置 UNDO 的 BEGIN 和 END 标志,但出错时 UNDO 回操作前状态
  13. ;;               元素3:  出错时执行的特殊操作
  14. (defun lt:error-init (lst / ss varl untag reset bar)
  15.   (if (= 1 (logand 1 (getvar "pickfirst")))
  16.     (progn
  17.       (setq ss (ssgetfirst))
  18.       (if (not (apply 'or ss)) (setq ss nil))
  19.     )
  20.   )
  21.   (mapcar 'set '(varl untag reset bar) lst)
  22.   (setq $lt-alive$ (if (not $lt-alive$) 1 (1+ $lt-alive$)))
  23.   (if (and (> $lt-alive$ 1)
  24.            (= "*LTErr*" (last $lt-error$))
  25.       )
  26.     (progn
  27.       (setq *error* lt:error $lt-alive$ 1)
  28.       (lt:error-restore)
  29.       (setq $lt-alive$ 1)
  30.     )
  31.   )
  32.   (if (<= $lt-alive$ 0)
  33.     (progn
  34.       (setq $lt-alive$ 0)
  35.       (lt:error-restore)
  36.       (setq $lt-alive$ 1)
  37.     )
  38.   )
  39.   (if (= $lt-alive$ 1)
  40.     (progn
  41.       (setq $lt-olderror$ *error*)
  42.       (if (or (not (listp $lt-error$))
  43.               (/= "*LTErr*" (last $lt-error$))
  44.           )
  45.         (setq $lt-error$ (list "*LTErr*"))
  46.       )
  47.       (if (or (= (type (car $lt-error$)) 'list)
  48.               (= "*LTErr*" (car $lt-error$))
  49.           )
  50.         (setq $lt-error$ (cons untag $lt-error$))
  51.         (setq $lt-error$ (cons untag (cdr $lt-error$)))
  52.       )
  53.       (if untag
  54.         (lt:undo-init T)
  55.         (setq $lt-undoctl$ nil)
  56.       )
  57.     )
  58.   )
  59.   (lt:sysvar-set (car lst))
  60.   (if (= $lt-alive$ 1)
  61.     (progn
  62.       (setq *error* lt:error)
  63.       (if reset (setq $lt-error$ (append (reverse (cdr (reverse $lt-error$)))
  64.                                          (list reset (last $lt-error$))
  65.                                  )
  66.                 )
  67.       )
  68.     )
  69.   )
  70.   (if ss (apply 'sssetfirst ss))
  71. )
  72. ;;____________________________________________________________________________________________________
  73. ;; 〓 (lt:error msg) 〓
  74. ;;  [功能] 出错处理
  75. ;;  [参数] msg---出错信息。在通常情况下,*ERROR* 函数会根据不同出错情况,而自动返回出错信息,如:“函数
  76. ;;               被取消”。
  77. ;;               所以本程序需要用户可以通过定义全局变量 $lt-errormsg$ 而改变默认出错信息:
  78. ;;               (1) 为字符串---打印 $lt-errormsg$ 的内容,如:(setq $lt-errormsg$ "程序出错")))
  79. ;;               (2) 为表达式---通过执行表达式而获取 msg 的值。如:
  80. ;;                              (if (= msg "函数被取消") (setq msg "用户中止"))
  81. ;;                              但表达式应以表的方式来传递给程序,即在表达式前面加上一个单引号 “'”。
  82. ;;                              (setq $lt-errormsg$ '(if (= msg "函数被取消") (setq msg "用户中止")))
  83. ;;               (3) 为 T ------显示默认出错信息
  84. ;;               (4) 为 nil-----不显示出错信息
  85. (defun lt:error (msg)
  86.   (if (and (listp $lt-error$) (= "*LTErr*" (last $lt-error$)))
  87.     (progn
  88.       (mapcar 'eval (cdr (reverse (cdr $lt-error$))))
  89.       (setq $lt-error$ (list (car $lt-error$) (last $lt-error$)))
  90.     )
  91.   )
  92.   (cond
  93.     ((= (type $lt-errormsg$) 'list) (eval $lt-errormsg$))
  94.     ((= (type $lt-errormsg$) 'str) (setq msg $lt-errormsg$))
  95.     ((not $lt-errormsg$) (setq msg nil))
  96.   )
  97.   (if msg (princ msg))
  98.   (while (not (= (getvar "cmdnames") "")) (command))
  99.   (if (and (or (= (car $lt-error$) 1) (= (car $lt-error$) T))
  100.            $lt-undoctl$
  101.       )
  102.     (progn
  103.       (lt:sysvar-set '("cmdecho" 0))
  104.       (while (not (wcmatch (getvar "cmdnames") "*UNDO*"))
  105.         (command "_.undo")
  106.       )
  107.       (command "_end")
  108.       (command "_.undo" "1")
  109.       (while (not (= (getvar "cmdnames") "")) (command))
  110.     )
  111.   )
  112.   (setq $lt-alive$ 1)
  113.   (lt:sysvar-restore)
  114.   (setq $lt-alive$ 0)
  115.   (lt:undo-restore)
  116.   (if $lt-olderror$
  117.     (setq *error* $lt-olderror$ $lt-olderror$ nil)
  118.   )
  119.   (princ)
  120. )
  121. ;;____________________________________________________________________________________________________
  122. ;; 〓 (lt:error-restore) 〓
  123. ;;  [功能] 出错处理恢复
  124. (defun lt:error-restore ()
  125.   (setq $lt-alive$ (1- $lt-alive$)
  126.         $lt-error$ (cons (car $lt-error$)
  127.                          (reverse (cons (last $lt-error$)
  128.                                         (cddr (reverse (cdr $lt-error$)))
  129.                                   )
  130.                          )
  131.                    )
  132.   )
  133.   (if (>= $lt-alive$ 0)
  134.     (lt:sysvar-restore)
  135.     (setq $lt-varlist$ nil)
  136.   )
  137.   (if (<= $lt-alive$ 0)
  138.     (progn
  139.       (lt:undo-restore)
  140.       (if $lt-olderror$ (setq *error* $lt-olderror$ $lt-olderror$ nil))
  141.     )
  142.   )
  143.   (princ)
  144. )
  145. ;;____________________________________________________________________________________________________
  146. ;; 〓 (lt:sysvar-set lst) 〓
  147. ;;  [功能] 系统变量设置
  148. ;;  [参数] lst---表。0 和偶数位置的元素:系统变量
  149. ;;                   奇数位置的元素:    要设置的系统变量值,对应该元素之前的系统变量。
  150. ;;                   格式:              '(系统变量1 系统变量值1 系统变量2 系统变量值2 ...)
  151. ;;  [返回] 表。表的长度等于 $lt-varlist$ 值为 nil 之后运行 lt:sysvar-set 函数的次数。
  152. ;;         每个表元素具备以下格式:((系统变量1 系统变量值1) (系统变量2 系统变量值2) ...)
  153. (defun lt:sysvar-set (lst / lst3 a n b lst2)
  154.   (setq lst3 (car $lt-varlist$) n -2)
  155.   (repeat (/ (length lst) 2)
  156.     (setq a    (strcase (nth (setq n (+ n 2)) lst))
  157.           b    (nth (1+ n) lst)
  158.           lst2 (append lst2 (list (list a (getvar a))))
  159.     )
  160.     (if (and $lt-varlist$ (not (assoc a lst3)))
  161.       (setq lst3 (append lst3 (list (list a (getvar a)))))
  162.     )
  163.     (setvar a b)
  164.   )
  165.   (if $lt-varlist$
  166.     (setq $lt-varlist$ (append (list lst3) (cdr $lt-varlist$) (list lst2)))
  167.     (setq $lt-varlist$ (list lst2))
  168.   )
  169. )
  170. ;;____________________________________________________________________________________________________
  171. ;; 〓 (lt:sysvar-restore) 〓
  172. ;;  [功能] 系统变量恢复
  173. ;;  [说明] 必须确保变量 $lt-varlist$ 存在,该变量在运行 lt:sysvar-set 函数时设置;
  174. ;;         当变量 $lt-alive$ 小于等于 0 时,依次恢复到 lt:sysvar-set 函数最近设置点
  175. ;;         当变量 $lt-alive$ 大于 0  或为 nil时,本程序恢复到 lt:sysvar-set 函数第一个设置点,且
  176. ;;         设置变量 $lt-alive$ 为 nil。
  177. ;;  [返回] 变量 $lt-alive$ 的当前值
  178. (defun lt:sysvar-restore (/ lst)
  179.   (if (<= $lt-alive$ 0)
  180.     (setq lst (car $lt-varlist$) $lt-varlist$ (list lst))
  181.     (setq lst (last $lt-varlist$))
  182.   )
  183.   (mapcar '(lambda (x) (apply 'setvar x)) lst)
  184.   (setq $lt-varlist$ (reverse (cdr (reverse $lt-varlist$))))
  185. )
  186. ;;____________________________________________________________________________________________________
  187. ;; 〓 (lt:undo-init varset) 〓
  188. ;;  [功能] UNDO 初始化设置,及放置开始(begin)标记
  189. ;;  [参数] varset---为 T   时:将返回值赋于全局变量 $lt-undoctl$
  190. ;;                  为 nil 时:忽略值赋
  191. ;;  [返回] 初始化前系统变量 "undoctl" 的值
  192. (defun lt:undo-init (varset / x y z)
  193.   (defun x () (getvar "undoctl"))
  194.   (defun y (i) (= (logand i (x)) i))
  195.   (lt:sysvar-set '("cmdecho" 0))
  196.   (setq z (x))
  197.   (if (or (= (x) 0) (= (x) 16)) (command "_.undo" "_all"))
  198.   (if (or (not (y 1)) (y 2)) (command "_.undo" "_control" "_all"))
  199.   (if (y 4) (command "_.undo" "_auto" "_off"))
  200.   (while (y 8) (command "_.undo" "_end"))
  201.   (while (not (y 8)) (command "_.undo" "_begin"))
  202.   (lt:sysvar-restore)
  203.   (if (= varset T) (setq $lt-undoctl$ z) z)
  204. )
  205. ;;____________________________________________________________________________________________________
  206. ;; 〓 (lt:undo-restore) 〓
  207. ;;  [功能] UNDO 恢复设置,及放置结束(end)标记放置
  208. ;;  [说明] 必须确保变量 $lt-undoctl$ 存在,即表示开始(begin)标记已经放置且保存 UNDO 初始化前的
  209. ;;         "undoctl" 变量值
  210. (defun lt:undo-restore (/ x)
  211.   (if $lt-undoctl$
  212.     (progn
  213.       (defun x (i val) (= (logand i val) i))
  214.       (lt:sysvar-set '("cmdecho" 0))
  215.       (while (= 8 (logand 8 (getvar "undoctl"))) (command "_.undo" "_end"))
  216.       (if (/= $lt-undoctl$ (getvar "undoctl"))
  217.         (progn
  218.           (cond
  219.             ((= 0 $lt-undoctl$) (command "_.undo" "_control" "_none"))
  220.             ((x 2 $lt-undoctl$) (command "_.undo" "_control" "_one"))
  221.           )
  222.           (if (x 4 $lt-undoctl$) (command "_.undo" "_auto" "_on"))
  223.         )
  224.       )
  225.       (if (not (x 2 (getvar "undoctl"))) (lt:sysvar-restore))
  226.       (setq $lt-undoctl$ nil)
  227.     )
  228.   )
  229. )
    ■■ 2.2 测试以程序
  1. (defun c:test (/ p1 p2 e p3 p4)
  2.   (lt:error-init (list '("cmdecho" 0 "cecolor" "1") ;;初始时设置的变量
  3.                        0                            ;;
  4.                        '(if e (redraw e 4))         ;;如果出错,取消亮显
  5.                  )
  6.   )
  7.   (princ "\n测试开始!!")
  8.   (initget 1)
  9.   (setq p1 (getpoint "\n点1: "))
  10.   (initget 1)
  11.   (setq p2 (getpoint p1 "\n点2: "))
  12.   (lt:sysvar-set '("osmode" 0))
  13.   (command "_.line" p1 p2 "")
  14.   (setq e (entlast))
  15.   (redraw e 3)      ;;亮显
  16.   (initget 1)
  17.   (setq p3 (getpoint "\n点3(在这里按取消): "))
  18.   (initget 1)
  19.   (setq p4 (getpoint p3 "\n点4: "))
  20.   (command "_.line" p3 p4 "")
  21.   (lt:error-restore)
  22. )

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
有关其中的参数说明及全局变量说明明天再发

评分

参与人数 2威望 +1 明经币 +5 金钱 +70 贡献 +5 激情 +5 收起 理由
wowan1314 + 50 相当有价值的文章!感谢
mccad + 1 + 5 + 20 + 5 + 5 【精华】好文章

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下

本帖被以下淘专辑推荐:

发表于 2007-3-30 18:19:00 | 显示全部楼层
不错,可以
发表于 2007-3-30 19:44:00 | 显示全部楼层
谢谢LZ分享经验
 楼主| 发表于 2007-3-31 09:31:00 | 显示全部楼层

接一楼:

以上共提供了 7 个函数,以下是参数和全局变量的具体用法:

1. lt:error-init

   本函数共 1 个参数,参数为表,但表中包含三个元素

   元素1:  包含系统变量及其值的列表,程序在初始时将系统变量依次设置为对应

           值。

          格式为:  '(变量1 变量值1 变量2 变量值2 变量3 变量值3 ... 变量n 变量值n)

          比如:    '("cmdecho" 0 "osmode" 0 "cecolor" "1")

           中途设置的变量为了确保能够在出错后恢复,可以使用 lt:sysvar-set 函数,

           后面我们再详细说明。


   元素2:  UNDO 的设置

           nil--->不做任何操作
           0----->放置 UNDO 的 BEGIN 和 END 标志

                  这样确保程序结束时,用户可通过 U 命令,一次取消该操作
           1或T-->放置 UNDO 的 BEGIN 和 END 标志,但出错时 UNDO 回操作前状态

                  这样确保程序结束时,用户可通过 U 命令,一次取消该操作

                  而且,出错后,程序自动执行(command "undo" 1)的操作

   元素3:  出错时执行的特殊操作。为任意表达式,但以表的方式传递。

           所以表达式之前要加一个 ' 符号

           我们通常会需要在程序出错后,执行其他的任何表达式的操作。

           比如:redraw 函数亮显某图元。出错后 UNDO 的设置无法正常恢复显示。

           所以我们可以设置此元素为: '(if en (redraw en 4))

           对于多个操作可用 progn 函数连接。

           如:'(progn (if en (redraw en 4))

                       (if en2 (entdel en2))

                )

    全局变量:

    $lt-alive$ 记录执行 lt:error-init lt:error lt:error-restore 的执行情况

    如 $lt-alive$=1 说明已经执行了一次 lt:error-init 函数,并且尚未执行 lt:error-restore

    恢复操作。

    这个时候,如果用户再次 执行 lt:error-init ,lt:error-init会自动判别情况,先恢复已经记录

    在 $lt-error$ 变量里的相关操作后,将 $lt-alive$ 变量归零。再执行 lt:error-init 设置。

    $lt-error$

    lt:error-init 通过 $lt-error$ 变量将出错的相关恢复要求传递给 lt:error 和lt:error-restore

    并将执行过的内容依次删除。

;;;------------------------------待续

发表于 2007-4-13 23:29:00 | 显示全部楼层
很有帮助,谢谢楼主。
发表于 2007-4-15 09:27:00 | 显示全部楼层
透彻
发表于 2007-4-17 22:46:00 | 显示全部楼层

值得学习

谢楼主分享

发表于 2007-4-18 22:06:00 | 显示全部楼层
........
发表于 2008-12-1 09:14:00 | 显示全部楼层

挖到前排来学习

发表于 2008-12-1 09:21:00 | 显示全部楼层
谢谢版主的无私!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-5-18 10:04 , Processed in 0.264491 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表