乐筑天下

搜索
欢迎各位开发者和用户入驻本平台 尊重版权,从我做起,拒绝盗版,拒绝倒卖 签到、发布资源、邀请好友注册,可以获得银币 请注意保管好自己的密码,避免账户资金被盗
查看: 74|回复: 6

[编程交流] 错误捕捉器撤消太多

[复制链接]

77

主题

298

帖子

232

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
394
发表于 2022-7-5 16:48:17 | 显示全部楼层 |阅读模式

 
我们的一些LISP例程,特别是错误捕捉器/处理程序,一直存在问题。问题是,有时出现“错误”时,会撤消太多操作。
 
我的假设是。。。(我很高兴有争议)。。。一个LISP例程的错误处理程序使用“UNDO”“BACK”,但例程本身没有放置“UNDO”“标记”。
 
因此,一旦出现“错误”,捕捉器将发出“UNDO”“BACK”并撤消到之前的标记集,而不是被崩溃的例程中的标记集。这听起来对吗?
 
说了这么多,有没有人对如何找出哪种例行程序会把事情搞砸有什么建议?下面是一个例程的代码,该例程在出现“错误”时取消了所有内容(返回到上一个标记)。但是这个例程确实有一个“撤消”“标记”集。。。所以它否定了我的理论。
 
不管怎样,我都在努力解决这个问题,如果能帮我摆脱罪恶感,我将不胜感激。
 
谢谢。
 
  1. (defun uzerr (s)
  2. (command "undo" "b")
  3. (prompt "\n*Program Terminated***UZ.lsp ERROR MESSAGE*")
  4. (setq *error* exi)
  5. (princ)
  6. )
  7. (Defun c:UZ (/ pnt1 pnt2 os orth)
  8. (setq uzcmde (getvar "cmdecho"))
  9. (setvar "cmdecho" 0)
  10. (command "undo" "m")
  11. (setq exi *error*)
  12. (setq *error* uzerr)
  13. (setq OS (getvar "osmode"))
  14. (setq ORTH (getvar "orthomode"))
  15. (setvar "osmode" 512)
  16. (command "UCSICON" "ON")
  17. (setq PNT1 (getpoint "\nPick first point, nearest to - or press enter to turn off nearest osnap..."))
  18. (setvar "orthomode" 0)
  19. (if (= PNT1 nil)
  20. (progn
  21. (setvar "osmode" OS)
  22. (prompt "\nPick two points to align X axis...")
  23. (command "ucs" "z" pause pause)
  24. )
  25. (progn
  26. (initget 1)
  27. (setq PNT2 (getpoint PNT1 "\nPick second point - Nearest to ..."))
  28. (setvar "osmode" 0)
  29. (command "ucs" "z" PNT1 PNT2)
  30. (setvar "osmode" OS)
  31. )
  32. )
  33. (setvar "orthomode" ORTH)
  34. (setq *error* exi)
  35. (setvar "cmdecho" uzcmde)
  36. (princ)
  37. )
回复

使用道具 举报

77

主题

298

帖子

232

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
394
发表于 2022-7-5 16:59:30 | 显示全部楼层
经过更多的调查(和教育-感谢李在这里的文章。。。http://www.lee-mac.com/errorhandling.html)我现在意识到,我的LISP例程都没有将临时的“错误”函数/符号定义为局部变量。因此,我的一些例程(我猜会有一些)将*error*定义为临时函数,特定于该例程,但不会将*error*恢复为其默认函数。
 
这解释了我在UNDO>BACK中遇到的问题(因为我有一个临时的*error*函数集,而它应该设置为默认值)。
回复

使用道具 举报

114

主题

1万

帖子

1万

银币

中流砥柱

Rank: 25

铜币
543
发表于 2022-7-5 17:16:58 | 显示全部楼层
 
虽然您没有遵循在函数本地声明*错误*符号的路线,但您当前的代码仍然遵循我在标题“函数本地化的替代方案”下描述的方法,因此之前的*错误*函数仍将恢复。
回复

使用道具 举报

77

主题

298

帖子

232

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
394
发表于 2022-7-5 17:21:03 | 显示全部楼层
谢谢李。我认为我最初发布的示例代码可能不是一个令人讨厌的例程。
 
我有一些我认为还没有完全结束的常规动作。例如,我有一个启动块编辑的例程,我认为块编辑器是在例程调用将*错误*符号恢复为默认值之前启动的。我理解(或者,我希望我理解),“错误”符号的本地化将纠正这种特殊情况。
 
很高兴被引导到正确的方向。
 
非常感谢您的回复。
回复

使用道具 举报

77

主题

298

帖子

232

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
394
发表于 2022-7-5 17:34:35 | 显示全部楼层
大家好。
我刚刚失去了一个长的,详细的帖子,所以请原谅我,如果这是一个有点简短。
我们仍然有这个问题。
我有点不知所措,随着时间的推移,我纠正了更多错误的惯例,我们应该越来越少地看到这个问题,但它仍然偶尔出现。现在我开始怀疑我是否真的理解了这个问题。
有人对解决这个问题的其他方法有什么建议吗?或者如何确定要修复的违规例程?
我在这里读到:http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/misbehaving-undo-mark/td-p/863544  ... 在LISP例程中使用UNDO标记是不明智的。这是真的吗?我遵循了AFRALISP的错误处理程序示例UNDO MARK&BACK,我应该更改为UNDO BEGIN&END吗?
如有任何其他建议,将不胜感激。
回复

使用道具 举报

66

主题

1552

帖子

1514

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
325
发表于 2022-7-5 17:42:29 | 显示全部楼层
我总是使用vla-EndUndoMark/vla-StartUndoMark方法,用李的描述检查这个片段:
  1. (setq doc (vla-get-activedocument (vlax-get-acad-object)))
  2. (if (= 8 (logand 8 (getvar 'undoctl))) ;; If an undo group is already open
  3. (vla-endundomark doc) ;; close it
  4. ) ;; end if
  5. (vla-startundomark doc) ;; Open a new undo group
  6. (vla-endundomark doc) ;; Close the open undo group

在开始和结束标记之间,必须找到表达式,这些表达式在图形上执行更改(如更改对象的特性值)。
我还认为,在使用UNDO命令时,当其在*error*函数内时,必须使用command-s调用,否则这样的调用就足够了:
  1.   (defun *error* ( msg )
  2.    (and acDoc (= 8 (logand (getvar 'undoctl) ) (vla-EndUndoMark acDoc))
  3.    (princ msg)
  4.    (princ)
  5. )
回复

使用道具 举报

77

主题

298

帖子

232

银币

后起之秀

Rank: 20Rank: 20Rank: 20Rank: 20

铜币
394
发表于 2022-7-5 17:49:45 | 显示全部楼层
我想我现在已经能够重现这个错误,并发现了一些令人困惑的线索/结果:
 
这些测试中使用了3个LISP例程,请参见以下内容:
 
代码#1
  1. (defun C:BI2NOSCALING (/)
  2. (SETVAR "CMDECHO" 0)
  3.   (prompt "\nPICK INSERTION POINT. ")
  4.   (SETQ SCALE "1")
  5. (SETVAR "CMDECHO" 1)
  6.   (COMMAND "INSERT" BLOCK pause "" scale pause)
  7. (SETVAR "CMDECHO" 0)
  8. (command "explode" "L")
  9.   (terpri)
  10. )
代码#2
  1. (defun c:mi ( / *error* MIss MIpt1 MIpt2 OROS ORORT)
  2. (SETQ OROS (GETVAR "OSMODE"))
  3. (SETQ ORORT (GETVAR "ORTHOMODE"))
  4. (command "undo" "m")
  5. ;(command "undo" "m")
  6. (SETVAR "OSMODE" 0)
  7. (SETVAR "ORTHOMODE" 1)
  8. (SETVAR "cmdecho" 0)
  9. ;(COMMAND "undo" "END")
  10. (setq exi *error*)
  11. (setq *error* MIerr)
  12. (setq MIss (ssget))
  13. (setq MIpt1 (getpoint))
  14. (command "ucs" "O" MIpt1)
  15. (setq MIpt2 '( 0 0 0))
  16. (SETVAR "cmdecho" 1)
  17. (command "mirror" MIss "" MIPT2 pause pause)
  18. (command "ucs" "P")
  19. (SETVAR "OSMODE" OROS)
  20. (SETVAR "ORTHOMODE" ORORT)
  21. (SETVAR "cmdecho" 0)
  22. (setq *error* exi)
  23. (princ)
  24. )
代码#3
  1. (defun c:mi ( / *error* MIss MIpt1 MIpt2 OROS ORORT)
  2. (SETQ OROS (GETVAR "OSMODE"))
  3. (SETQ ORORT (GETVAR "ORTHOMODE"))
  4. (command "undo" "m")
  5. (command "undo" "m")
  6. (SETVAR "OSMODE" 0)
  7. (SETVAR "ORTHOMODE" 1)
  8. (SETVAR "cmdecho" 0)
  9. ;(COMMAND "undo" "END")
  10. (setq exi *error*)
  11. (setq *error* MIerr)
  12. (setq MIss (ssget))
  13. (setq MIpt1 (getpoint))
  14. (command "ucs" "O" MIpt1)
  15. (setq MIpt2 '( 0 0 0))
  16. (SETVAR "cmdecho" 1)
  17. (command "mirror" MIss "" MIPT2 pause pause)
  18. (command "ucs" "P")
  19. (SETVAR "OSMODE" OROS)
  20. (SETVAR "ORTHOMODE" ORORT)
  21. (SETVAR "cmdecho" 0)
  22. (setq *error* exi)
  23. (princ)
  24. )

错误处理程序
  1. (defun MIerr (s)
  2. (command "undo" "b")
  3. (prompt "\n*Program Terminated***Mirror.lsp ERROR MESSAGE*")
  4. (setq *error* exi)
  5. (princ)
  6. )
测试1-未产生任何问题
在新图形中(没有撤消历史记录),如果我完全运行代码#1,则代码#2,但在提示第二点时退出例程。。。没问题。
 
测试2-没有问题
在新图形中(没有撤消历史记录),如果我完全运行代码#1,则代码#3,但在提示第二点时退出例程。。。没问题。
 
测试3-产生的问题
在新图形中(无撤消历史记录),如果我完全运行代码#1,然后单击RETURN&然后单击ESC,然后运行代码#2,但在提示第二点时退出例程。。。问题
 
测试4-没有问题
在新图形中(无撤消历史记录),如果我完全运行代码#1,然后单击RETURN&然后单击ESC,然后运行代码#3,但在提示第二点时退出例程。。。没问题。
 
我发现很难理解这一点,但我的观察结果是:如果我在退出代码#2之前退出代码#1,问题就会出现。但如果我在退出代码#3之前退出代码#1,则不会出现任何问题。代码#2和代码#3之间的唯一区别是代码#3的(命令“undo”“m”)行重复。似乎有可能忽略单个(命令“undo”“m”)行(或其他内容)。但是如果我在成功完成上一个命令后运行代码#2。。。没问题。
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

  • 微信公众平台

  • 扫描访问手机版

  • 点击图片下载手机App

QQ|关于我们|小黑屋|乐筑天下 繁体中文

GMT+8, 2025-3-13 13:32 , Processed in 0.447222 second(s), 66 queries .

© 2020-2025 乐筑天下

联系客服 关注微信 帮助中心 下载APP 返回顶部 返回列表