找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 240|回复: 1

Lisp程序设计错误处理的技巧

[复制链接]

0

主题

0

回帖

26

积分

管理员

积分
26
发表于 2024-4-6 16:40:32 | 显示全部楼层 |阅读模式
  1. ;|
  2.   Gxl-ErrStaSys  -> Gxl-ErrEnd ;只针对系统变量的恢复
  3.   Gxl-ErrSta     -> Gxl-ErrEnd ;系统变量+函数+编组
  4.   Gxl-ErrStaNrm  -> Gxl-ErrEndNrm ;只针对自定义常量的恢复
  5. |;
  6. Lisp程序设计错误处理的技巧@Gu采用xl,由Kucha梳理 (源自博客:http://guxl.mjtd.com/?p=14)
  7.   任何程序在运行中都可能不完全会按照程序设计者预想的方式去运行,程序运行中会出现各种意想不到的情况,
  8.   AutoLisp提供的标准错误处理函数*error*,仅能告诉你程序运行有了错误,但不能对错误进行善后处理。
  9.   这对于一个优秀的程序来说,是不能忍受的,为此,我们应当用自定义的错误处理函数来改善这种情况,使程序在出现任何错误情况下都能正确处理!
  10. //一、在程序内设置局部自定义错误处理函数
  11.   AutoLisp提供内部提供了一个标准的自定义错误处理函数:(*error* string)
  12.   当AutoLisp程序运行出错时, *error* 函数值不为空
  13.   AutoCAD会传递给 *error* 函数的参数 string 一个错误信息字符串值,并自动执行 *error* 函数。
  14.   根据这个错误处理运行机制,我们可以根据自己的需要,对错误处理函数 *error* 进行自定义。
  15.   ;;;例1:自定义如下错误处理函数:
  16.   (defun *error* (Msg)
  17.     (princ "error:")
  18.     (princ Msg);打印错误信息
  19.     (princ)
  20.   )
  21.   当Lisp程序运行出错时,系统会自动调用 *error* 函数,打印出错误处理信息。
  22.   但是这个错误处理函数几乎没有什么用,该错误处理函数仅仅是对错误信息进行了输出,没有对可能出现的错误进行任何处理
  23.   这可不是我们想要的程序,我们需要对 *error* 函数内容根据程序处理的需要进行定制!
  24.   ;;;例2:下面是一个绘制三角形的例子,程序目的是在图上选取三点,自动绘制三角形,。
  25.   (defun C:TT (/ Old采用CMD Old采用OSM p1 p2 P3)
  26.     (setq Old采用CMD (getvar "cmdecho"));保存系统变量cmdecho值
  27.     (setvar "cmdecho" 0);关闭命令行的回显提示
  28.     (setq Old采用OSM (getvar "osmode"));保存系统变量osmode值
  29.     (setvar "osmode" 0);关闭捕捉模式
  30.     (setq p1 (getpoint "\n输入第一点: ")
  31.           P2 (getpoint "\n输入第二点: ")
  32.           P3 (getpoint "\n输入第三点: ")
  33.     )
  34.     (vl-cmdf "采用.pline" p1 p2 p3 "c")
  35.     (setvar "cmdecho" Old采用CMD);恢复cmdecho系统变量
  36.     (setvar "osmode" Old采用OSM);恢复osmode系统变量
  37.     (princ)
  38.   )
  39.   在程序正常运行的情况下,程序会在绘制完三角形后自动恢复系统变量"osmode"、" Old采用CMD",
  40.   但是在图面选取点时,按下ESC键,或某个点输入为空,会导致程序出错
  41.   后面的恢复系统变量值的代码则不会执行,程序关闭了捕捉模式,我们不得不手动来重新设置捕捉方式。
  42.   为此,我们在程序的开始自定义一个错误处理函数 *error* ,在 *error* 函数内添加恢复系统变量"osmode"、" Old采用CMD"的代码
  43.   在程序运行出错时自动调用 *error* 函数, *error* 函数内恢复系统变量"osmode"、" Old采用CMD"的代码自动运行
  44.   这便达到了我们对程序错误处理的要求!示例代码如下:
  45.   (defun C:TT (/ *error* Old采用OSM Old采用CMD p1 p2 P3)
  46.     (defun *error* (Msg)
  47.         (setvar "cmdecho" Old采用CMD);恢复cmdecho系统变量
  48.         (setvar "osmode" Old采用OSM);恢复osmode系统变量
  49.         (princ "error: ")
  50.         (princ Msg);打印错误信息
  51.         (princ)
  52.     )
  53.     ;;以下为主程序内容
  54.     (setq Old采用CMD (getvar "cmdecho"));保存系统变量cmdecho值
  55.     (setvar "cmdecho" 0);关闭命令行的回显提示
  56.     (setq Old采用OSM (getvar "osmode"));保存系统变量osmode值
  57.     (setvar "osmode" 0);关闭捕捉模式
  58.     (setq p1 (getpoint "\n输入第一点: ")
  59.           P2 (getpoint "\n输入第二点: ")
  60.           P3 (getpoint "\n输入第三点: ")
  61.     )
  62.     (vl-cmdf "采用.pline" p1 p2 p3 "c")
  63.     (setvar "cmdecho" Old采用CMD);恢复cmdecho系统变量
  64.     (setvar "osmode" Old采用OSM);恢复osmode系统变量
  65.     (princ)
  66.   )
  67. //二、通用错误处理函数的处理技巧
  68.   请注意,在上面例2的程序中,我们是将 *error* 函数声明为局部变量,则该错误处理仅在test函数范围内有效!
  69.   这样我们就需要在每个程序里都要添加类似的错误处理代码,其实大部分程序的错误处理代码都类似
  70.   如果在每个程序里都添加相同的代码,是一件很讨厌的事儿,会导致代码越来越长
  71.   为此,我们可以做一个通用错误处理函数,以后仅需要调用该函数即可,无需再写出长长的一串代码!
  72.   ;;;例3:自定义通用错误处理初始化函数
  73.   (defun Gxl-ErrStaSys (SysLst / SysNam SysVar)
  74.     ;|(Gxl-ErrStaSys SysLst) 初始化*error*
  75.       功能: 保存 SysLst 给定的系统变量值,并按表给定的系统变量值设置系统变量
  76.       参数:
  77.           SysLst 系统变量及其设置值列表 例如: '("osmode" 0 "cmdecho" 0  "cecolor" "1")
  78.     |;·
  79.     (setq *OldEr* *error*);储存*error*函数
  80.    
  81.     (defun *error* (Msg / SysNam SysVar)
  82.         (if *Old采用SysVar* ;储存的系统变量值列表
  83.             (while
  84.                 (and (setq SysNam (car *Old采用SysVar*))
  85.                     (setq SysVar (cadr *Old采用SysVar*))
  86.                 )
  87.                 (setq *Old采用SysVar* (cddr *Old采用SysVar*))
  88.                 (setvar SysNam SysVar)
  89.             )
  90.         );恢复
  91.         (setq *error* *OldEr*)
  92.         (or (wcmatch (strcase Msg) "*BREAK,*CANCEL*,*EXIT*")
  93.             (princ (strcat "\n** Error: " Msg " **"))
  94.         )
  95.     );自定义出错函数 *error*
  96.     (if (= 8 (logand (getvar "undoctl") 8))
  97.         (command "采用undo" "采用e")
  98.     );如果有活动编组,先结束编组
  99.    
  100.     (command "采用undo" "采用be")
  101.     (if SysLst
  102.         (while
  103.             (and (setq SysNam (car SysLst))
  104.                  (setq SysVar (cadr SysLst))
  105.             )
  106.             (setq *Old采用SysVar* (append *Old采用SysVar* (list SysNam (getvar SysNam))));储存系统变量
  107.             (setq SysLst (cddr SysLst))
  108.             (setvar SysNam SysVar);设置系统变量
  109.         )
  110.     )
  111.     (princ)
  112.   )
  113.   ;;;例4:自定义通用错误处理恢复函数
  114.   (defun Gxl-ErrEnd ();恢复参数
  115.     (if (= 8 (logand (getvar "undoctl") 8))
  116.       (command "采用undo" "采用e")
  117.     );如果有活动编组,先结束编组
  118.     (if *OldEr*
  119.         (setq *error* *OldEr*
  120.               *OldEr* nil
  121.         );恢复参数函数
  122.     )
  123.     (if *Old采用SysVar* ;恢复储存的系统变量
  124.         (while
  125.           (and (setq SysNam (car *Old采用SysVar*))
  126.                (setq SysVar (cadr *Old采用SysVar*))
  127.           )
  128.           (setq *Old采用SysVar* (cddr *Old采用SysVar*))
  129.           (setvar SysNam SysVar)
  130.         )
  131.     )
  132.     (setq *DoFun* nil
  133.           *UnMde* nil
  134.     )
  135.     (princ)
  136.   )
  137.   ;;;实际运用示例:
  138.   (defun C:TT ()
  139.     (Gxl-ErrStaSys '("osmode" 0 "cmdecho" 0 "cecolor" "1"));记录参数
  140.     ;;主程序内容
  141.     .
  142.     .
  143.     (Gxl-ErrEnd);恢复参数
  144.     (princ)
  145.   )
  146.   (Gxl-ErrStaSys SysLst)错误处理函数,当程序运行出错时只可以对保存的系统变量进行恢复
  147.   但这在复杂的程序面前,并不能满足我们的需要,因为各种各样的程序在运行出错后可能还要进行其他各种各样不同的处理
  148.   为此,我们要对 Gxl-ErrStaSys 函数进行进一步改进,使得 Gxl-ErrStaSys 函数可以应对各种可能出现的各种问题。
  149.   ;;;例5:改进后的自定义通用错误处理初始化函数
  150.   (defun Gxl-ErrSta (SysLst DoFun UnMde / SysNam SysVar)
  151.     ;|(Gxl-ErrSta SysLst DoFun UnMde)
  152.       功能: 多功能错误处理函数
  153.       参数:
  154.         SysLst = 系统变量表
  155.         DoFun  = 要执行的函数 ,无动作则为nil
  156.         UnMde  = Undo处理模式 0 = 不编组 1 = 仅仅编组 2 = 回到出错前
  157.     |;
  158.     (setq *OldEr* *error*
  159.           *DoFun* DoFun
  160.           *UnMde* UnMde
  161.     )
  162.     (defun *error* (Msg / SysNam SysVar)
  163.       (if (= 2 *UnMde*)
  164.           (progn
  165.               (if (= 8 (logand (getvar "undoctl") 8))
  166.                   (command "采用undo" "采用e")
  167.               );如果有活动编组,先结束编组
  168.               (command "采用U")
  169.           )
  170.           (progn
  171.             (if *Old采用SysVar*
  172.               (while
  173.                   (and (setq SysNam (car *Old采用SysVar*))
  174.                       (setq SysVar (cadr *Old采用SysVar*))
  175.                   )
  176.                   (setq *Old采用SysVar* (cddr *Old采用SysVar*))
  177.                   (setvar SysNam SysVar)
  178.               )
  179.             )
  180.             (if *DoFun* (vl-catch-all-apply *DoFun*));执行函数
  181.             (if (= *UnMde* 1)
  182.               (if (= 8 (logand (getvar "undoctl") 8))
  183.                   (command "采用undo" "采用e")
  184.               );如果有活动编组,先结束编组
  185.             )
  186.           )
  187.       )
  188.       (setq *error* *OldEr*
  189.             *OldEr* nil
  190.             *DoFun* nil
  191.             *UnMde* nil
  192.       )
  193.       (or (wcmatch (strcase Msg) "*BREAK,*CANCEL*,*EXIT*")
  194.           (princ (strcat "\n** Error: " Msg " **"))
  195.       )
  196.     )
  197.     (if (or (= *UnMde* 1) (= *UnMde* 2))
  198.         (progn
  199.             (if (= 8 (logand (getvar "undoctl") 8))
  200.               (command "采用undo" "采用e")
  201.             );如果有活动编组,先结束编组
  202.             (command "采用undo" "采用BE");编组开始
  203.         )
  204.     )
  205.     (if SysLst
  206.       (while
  207.         (and (setq SysNam (car SysLst))
  208.              (setq SysVar (cadr SysLst))
  209.         )
  210.         (setq *Old采用SysVar* (append *Old采用SysVar* (list SysNam (getvar SysNam))))
  211.         (setq SysLst (cddr SysLst))
  212.         (setvar SysNam SysVar)
  213.       )
  214.     )
  215.     (princ)
  216.   )
  217.   ;;;错误处理应用范例:
  218.   (defun C:TT (/ ErrFun p1 p2 p3)
  219.     ;初始化*error* 参数UnMde根据需要可设置为 0 1 2
  220.     (Gxl-ErrSta (list 'blipmode 0 'cmdecho 0 'osmode 0) 'ErrFun 2);出错只编组
  221.     (defun ErrFun () ;出错后*error*要执行的动作
  222.       (alert "出错啦!")
  223.     )
  224.     (setq p1 (getpoint "\n第一点: "))
  225.     (setq p2 (getpoint "\n第二点: "))
  226.     (setq p3 (getpoint "\n第三点: "))
  227.     (vl-cmdf "line" p1 p2 p3 "c")
  228.     ;将UnMde分别设置为 0 1 2,运行到以下任意位置按下ESC试试效果
  229.     (setq p1 (getpoint "\n第一点: "))
  230.     (setq p2 (getpoint "\n第二点: "))
  231.     (setq p3 (getpoint "\n第三点: "))
  232.     (vl-cmdf "line" p1 p2 p3 "c")
  233.     (setq p1 (getpoint "\n第一点: "))
  234.     (setq p2 (getpoint "\n第二点: "))
  235.     (setq p3 (getpoint "\n第三点: "))
  236.     (vl-cmdf "line" p1 p2 p3 "c")
  237.     (setq p1 (getpoint "\n第一点: "))
  238.     (setq p2 (getpoint "\n第二点: "))
  239.     (setq p3 (getpoint "\n第三点: "))
  240.     (vl-cmdf "line" p1 p2 p3 "c")
  241.     (Gxl-ErrEnd)
  242.     (princ)
  243.   )
  244.   可能有些读者觉得对于这样的出错处理函数中,对于系统变量表参数,要写一长串变量,也很麻烦
  245.   因为在程序中,我们经常要设置和使用的一些系统变量都数量有限。为此,我们提供另外一种错误处理的方法和思路
  246.   在初始化错误函数中保存一些常用的系统变量初始值,储存在全局变量中,然后初始化一些常用系统变量的值
  247.   程序中可以对这些已经保存的系统变量任意修改,在程序结束时用错误恢复函数自动恢复系统变量值,程序出错时由错误处理函数来恢复系统变量值。
  248.   我们将一些有关经常使用的系统变量名储存表,设为常量 *SNLst* :
  249.   (setq *SNLst* (list 'AUNITS 'AUPREC 'ATTDIA 'ATTREQ 'BLIPMODE 'DIMZIN 'CECOLOR
  250.                         'CELTYPE 'CLAYER 'CMDECHO 'TRIMMODE 'EXPERT 'HIGHLIGHT 'LUNITS
  251.                         'LUPREC 'EDGEMODE 'OSMODE 'ORTHOMODE 'TEXTSTYLE 'PLINEWID 'PLINEGEN
  252.                         'FILEDIA 'PICKBOX 'QAFLAGS 'UCSAXISANG 'CELTSCALE 'NOMUTT
  253.                         'PEDITACCEPT 'Mirrtext 'limcheck
  254.                   )
  255.   );*SNLst* 常用系统变量表
  256.   ;;;例6、自定义通用错误处理函数Gxl-ErrSta02:
  257.   (defun Gxl-ErrStaNrm (DoFun UnMde)
  258.     ;|自定义错误处理函数 Gxl-ErrStaNrm
  259.       参数:
  260.         DoFun = 要执行的函数,无动作则为nil
  261.         UnMde = Undo处理模式 0 = 不编组 1 = 仅仅编组 2 = 回到出错前
  262.     |;
  263.     (defun *error* (Msg / SysNam SysVar)
  264.       (if (= 2 *UnMde*)
  265.         (progn
  266.             (if (= 8 (logand (getvar "undoctl") 8))
  267.               (command "采用undo" "采用e")
  268.             );如果有活动编组,先结束编组
  269.             (command "采用U")
  270.         )
  271.         (progn
  272.           (if *DoFun* (vl-catch-all-apply *DoFun*));执行函数
  273.           (if (= *UnMde* 1)
  274.               (if (= 8 (logand (getvar "undoctl") 8))
  275.                   (command "采用undo" "采用e")
  276.               );如果有活动编组,先结束编组
  277.           )
  278.         )
  279.       )
  280.       (if (and *SVLst* *SNLst*)
  281.           (mapcar
  282.             '(lambda (a b)
  283.               (vl-catch-all-apply 'setvar (list a b))
  284.             )
  285.             *SNLst*
  286.             *SVLst*
  287.           )
  288.       );回收变量值
  289.       (setq *error* *OldEr*
  290.             *OldEr* nil
  291.             *DoFun* nil
  292.             *UnMde* nil
  293.             *SVLst* nil
  294.       )
  295.       (or (wcmatch (strcase Msg) "*BREAK,*CANCEL*,*EXIT*")
  296.           (princ (strcat "\n** Error: " Msg " **"))
  297.       )
  298.     );定义出错函数
  299.     ;程序开始
  300.     (setq *SVLst* nil);*SVLst* 用于储存系统变量表 *SNLst* 中系统变量对应的值
  301.     (setq *SVLst* (mapcar '(lambda (x) (getvar x)) *SNLst*))
  302.     ;对一些程序中必须要初始化为0的系统变量初始化为0
  303.     (foreach XX '("ATTDIA" "ATTREQ" "BLIPMODE" "CMDECHO" "DIMZIN" "OSMODE" "ORTHOMODE" "MIRRTEXT")
  304.         (setvar XX 0)
  305.     )
  306.     (setq *OldEr* *error*
  307.           *DoFun* DoFun
  308.           *UnMde* UnMde
  309.     )
  310.   
  311.     (if (or (= *UnMde* 1) (= *UnMde* 2))
  312.       (progn
  313.         (if (= 8 (logand (getvar "undoctl") 8))
  314.           (command "采用undo" "采用e")
  315.         );如果有活动编组,先结束编组
  316.         (command "采用undo" "采用BE")
  317.       )
  318.     );是否开始编组
  319.    ;| EXPERT = 5 禁止显示提示
  320.       "块已经存在。重新定义?"
  321.       使用DIMSTYLE 命令的"保存"选项时,如果输入的标注样式名已经存在,系统将显示该提示。
  322.       如果 EXPERT 禁止显示一个提示,相应操作会认为用户已输入 y 确认提示。
  323.       EXPERT 的设置会影响脚本、菜单宏、AutoLISP 及其命令函数。
  324.     |;
  325.     (setvar "EXPERT" 5)
  326.     (setvar "CECOLOR" "BYLAYER");设置颜色随层
  327.     (setvar "celtype" "BYLAYER");设置线型随层
  328.     (setvar "LWDISPLAY" 1);设置显示线宽
  329.     (setvar "CELTSCALE" 1);设置当前线形比例为1
  330.     (setvar "PLINEGEN" 1);设置围绕多段线顶点生成连续线型
  331.   )
  332.   ;;;例7:Gxl-ErrSta02对应的自定义通用错误处理恢复函数
  333.   (defun Gxl-ErrEndNrm ()
  334.     (if (or (= *UnMde* 1) (= *UnMde* 2))
  335.       (if (= 8 (logand (getvar "undoctl") 8))
  336.         (command "采用undo" "采用e")
  337.       );如果有活动编组,先结束编组
  338.     )
  339.     (if *OldEr*
  340.         (setq *error* *OldEr*
  341.               *OldEr* nil
  342.         );恢复参数函数
  343.     )
  344.     (if (and *SVLst* *SNLst*)
  345.         (mapcar
  346.           '(lambda (a b)
  347.             (vl-catch-all-apply 'setvar (list a b))
  348.           )
  349.           *SNLst*
  350.           *SVLst*
  351.         )
  352.     )
  353.     (setq *DoFun* nil
  354.           *UnMde* nil
  355.           *SVLst* nil
  356.     )
  357.   )(princ)
  358.   ;;;错误处理应用示例:
  359.   (defun C:TT (/ ErrFun p1 p2 p3)
  360.     ;;初始化*error* 参数UnMde根据需要可设置为 0 1 2
  361.     (Gxl-ErrStaNrm 'ErrFun 2);出错只编组,这里省去了系统变量设置
  362.     (defun ErrFun ();出错后*error*要执行的动作
  363.       (alert "出错啦!")
  364.     )
  365.     (setq p1 (getpoint "\n第一点: "))
  366.     (setq p2 (getpoint "\n第二点: "))
  367.     (setq p3 (getpoint "\n第三点: "))
  368.     (vl-cmdf "line" p1 p2 p3 "c")
  369.     ;;将 UnMde分别设置为 0 1 2,运行到以下任意位置按下ESC试试效果
  370.     (setq p1 (getpoint "\n第一点: "))
  371.     (setq p2 (getpoint "\n第二点: "))
  372.     (setq p3 (getpoint "\n第三点: "))
  373.     (vl-cmdf "line" p1 p2 p3 "c")
  374.     (setq p1 (getpoint "\n第一点: "))
  375.     (setq p2 (getpoint "\n第二点: "))
  376.     (setq p3 (getpoint "\n第三点: "))
  377.     (vl-cmdf "line" p1 p2 p3 "c")
  378.     (setq p1 (getpoint "\n第一点: "))
  379.     (setq p2 (getpoint "\n第二点: "))
  380.     (setq p3 (getpoint "\n第三点: "))
  381.     (vl-cmdf "line" p1 p2 p3 "c")
  382.     (Gxl-ErrEndNrm)
  383.     (princ)
  384.   )
  385. //三、Vl-Catch-All-Apply函数捕捉错误的应用技巧
  386.   上面部分讨论的是传统的*error*方法,这种方法是对整个程序设置的统一的处理功能
  387.   无论程序中什么地方出错,都集中在这里处理!这种情况在程序比较简单,要处理的情况不多时,比较容易应付,因为这时程序需要处理的情况比较少!
  388.   当程序的规模比较大,要处理的情况比较复杂时,就很难满足我们对程序错误处理的要求,特别是当出现同样的错误代码需要在程序的不同部分做出不同处理的时候。
  389.   幸运的是,AutoLisp另外还提供了三个错误处理函数。
  390.   Vl-Catch-All-Apply函数能够捕捉指定函数的错误
  391.   Vl-Catch-All-Apply-Error-Message函数可以读取相关错误信息
  392.   Vl-Catch-All-Error-P函数可以测试Vl-Catch-All-Apply函数返回结果是否异常。
  393.   ;;;例如:下面这个函数是根据图上选取直角三角形的一条直角边,然后输入斜边长度,根据勾股定理计算另一直角边,并绘制三角形的例子:
  394.   (defun C:TT (/ p1 p2 d1 dd Ang)
  395.     ;初始化错误处理,出错后回到初始状态
  396.     (Gxl-ErrSta (list "cmdecho" 0 "osmode" 0) nil 2)
  397.     (setq p1 (getpoint "\n输入直角三角形直角边第一点: "))
  398.     (setq p2 (getpoint p1 "\n输入直角三角形直角边第二点: "))
  399.     (setq d1 (distance p1 p2))
  400.     (vl-cmdf "采用line" p1 p2 "")
  401.     (setq dd (getdist p1 "\n请输入斜边长度: "))
  402.     ;;根据勾股定理计算另一条直角边长度
  403.     (setq d2 (vl-catch-all-apply ;捕捉 sqrt 函数的错误
  404.                                 'sqrt
  405.                                 (list
  406.                                   (- (* dd dd) (* d1 d1))
  407.                                 )
  408.             )
  409.     )
  410.     (if (vl-catch-all-error-p d2);当输入的斜边长度小于直角边长度时 sqrt 函数会出错
  411.         (progn ;sqrt 函数结果异常
  412.               (alert (vl-catch-all-error-message d2));提示错误信息
  413.               (abcdefg);自己的错误退出程序
  414.         )
  415.         (progn
  416.             (setq Ang (+ (angle p1 p2) (* 0.5 pi)))
  417.             (command "采用line" p2 (polar p2 angd2) p1 "")
  418.         );绘制三角形
  419.     )
  420.     (Gxl-ErrEnd);恢复错误处理
  421.     (princ)
  422.   )
  423.   这样,自定义函数test就可以返回正确的结果或出错信息这两种结果,这是一种新的函数定义模式
  424.   其使用方法简而言之就是使用Vl-Catch-All-Apply对函数进行包装,然后使用Vl-Catch-All-Error-P判断包装函数返回值是否异常
  425.   若有异常,可使用Vl-Catch-All-Apply-Error-Message函数输出错误信息,并再此对错误进行处理。
复制代码

0

主题

0

回帖

26

积分

管理员

积分
26
 楼主| 发表于 2024-4-6 16:40:58 | 显示全部楼层
  1. Gxl-ErrStaSys  -> Gxl-ErrEnd ;只针对系统变量的恢复
  2.   Gxl-ErrSta     -> Gxl-ErrEnd ;系统变量+函数+编组
  3.   Gxl-ErrStaNrm  -> Gxl-ErrEndNrm ;只针对自定义常量的恢复
  4. (if (null vlax-dump-object) (vl-load-com));将Visual LISP扩展功能加载到 AutoLISP
  5. (defun C:TT (/ *error* CurDoc *Old采用SysVar*)
  6.   (setq CurDoc (vla-get-activedocument (vlax-get-acad-object)))
  7.   (defun *error* (x)  ;出错函数
  8.     ;其它需要恢复的内容
  9.     (if *Old采用SysVar* (foreach xx *Old采用SysVar* (apply 'setvar xx)));参数恢复
  10.     (vla-endundomark CurDoc) ;错误时结束编组
  11.   )
  12.   (while (eq 8 (logand 8 (getvar 'undoctl)))
  13.     (vla-endundomark CurDoc)
  14.   ) ;关闭以前的编组
  15.   (vla-startundomark CurDoc) ;记录编组
  16.     (progn ;记录系统变量
  17.       (setq *Old采用SysVar* '());清空变量,避免出错
  18.       (setq *Old采用SysVar*
  19.           (mapcar
  20.             '(lambda (a / b)
  21.               (if (setq b (getvar (car a)))
  22.                   (progn
  23.                     (vl-catch-all-apply 'setvar a)
  24.                     (list (car a) b)
  25.                   )
  26.               )
  27.             )
  28.             (list
  29.               (list "DIMZIN" 0);保留前导和后续的零
  30.               (list "CMDECHO" 0) ;关闭回显
  31.             )
  32.           )
  33.       );记录参数
  34.     )
  35.    
  36.     ;你的程序
  37.    
  38.     (command "redraw");清空一行
  39.     (if *Old采用SysVar* (foreach xx *Old采用SysVar* (apply 'setvar xx)));参数恢复
  40.   (vla-endundomark CurDoc) ;结束编组
  41.   (princ)
  42. )
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|膜结构网

GMT+8, 2024-12-28 02:28 , Processed in 0.177922 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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