Bill Tillman 发表于 2022-7-5 22:51:53

使用DCL验证用户Inp

我正在使用一个相当简单的DCL应用程序,它是从Jeffery P.Sanders网站教程中获得的:

(defun GetUserInput ()
(setq server_path "//a_very_long_novell_path/")
;;;--- Try to load the DCL file from disk into memory
(if(not(setq dcl_id (load_dialog (strcat server_path "MyDCLFile.dcl"))))
   (progn
   (alert "The DCL file could not be loaded.")
   (exit)
   )
   ;;;--- Else, the DCL file was loaded into memory
   (progn

   ;;;--- Try to load the definition inside the DCL file
   (if (not (new_dialog "MyDCL" dcl_id))
       (progn
         (alert "The definition could not be found inside the DCL file")
         (exit)
       )

       ;;;--- Else, the definition was loaded, we are ready to roll
       (progn

         ;;;--- If an action event occurs, do this function
         (action_tile "cancel" "(done_dialog 1)")
         (action_tile "accept" "(saveVars)(done_dialog 2)")

         ;;;--- Display the dialog box
         (setq ddiag(start_dialog))

         ;;;--- If the cancel button was pressed - display message
         (if (= ddiag 1)
         (princ "\n \n ...EXAMPLE Cancelled. \n ")
         )

         ;;;--- If the "Okay" button was pressed
         (if (= ddiag 2)
         (princ "\n \n ...Example Complete!")
         )
       )
   )
   )
)

;;;--- Suppress the last echo for a clean exit
(princ)

); end GetUserInput function

(defun Popup ( title msg flags / wsh )
(vl-catch-all-apply
   (function
   (lambda nil
(setq wsh (vlax-create-object "WScript.Shell"))
(setq res (vlax-invoke-method wsh 'popup msg 0 title flags))
)
   )
   )
(if wsh (vlax-release-object wsh))
res
)

我想做的是在退出此例程之前验证用户的输入。它需要两个输入,一个跨度和一个宽度。我正在检查它们是否在有限范围内,然后它进入程序的另一部分。但是如果用户输入了无效的内容,我想警告他们。。。我用李·Mac的弹出程序来做这件事,但一旦他们在收到错误警告后按OK,我希望程序DCL重置并再次询问用户,并不断询问用户输入,直到他们得到正确的结果。有谁能就如何最好地处理这个问题提出一些建议吗?
 
我让它工作并检查有效输入,但现在它只是退出。我正在寻找一种方法,以不断重复输入,直到用户得到它的权利。
 
再次证明,这很难,但确实能够编写复杂的代码来进行计算和绘制图形。最困难的部分是防止用户扔进垃圾桶,如果他们出错,再给他们一次机会。

Jef! 发表于 2022-7-5 23:02:01

当一个对话框被丢弃(done\u dialog)时,lisp将继续运行,并将用户输入的值保存在变量中(在您的示例中,它是由(saveVars)函数完成的)。
你可以用两种方法。
-检索并验证这两个值。根据哪一个无效(或两者都无效),您可以创建警告弹出窗口,然后再次启动GetUserInput。如果1个输入在可接受的范围内,则最好在重新启动dcl时将其放回原位。这样,如果你在其中一个页面上输入了错别字,你就不必同时输入这两个页面。需要记住的一点是:如果您获得无效输入并第二次启动,当第二个实例的完成将完成时,代码将“返回”到第一次执行中,以处理取消“重新启动”后的所有内容。(类似递归函数)。很好的解决方法(我认为):(if[无效](prong(getuserinput)(exit)))。
-更好的是(我会这样做),在dcl中添加一个空文本区域,以提供反馈,告诉用户为什么输入无效。您可以更改accept按钮的执行并添加if语句。如果值超出范围,根据输入错误及其原因,仅使用适当的注释更新文本区域。即“跨度值不能超过x英寸”。如果在可接受的范围内,则继续“(saveVars)(完成对话框2)”。这样,不会丢弃无效输入,但您不需要“重复”任何内容。您还可以更改焦点,将其放回故障字段。这很容易做到,也很漂亮。

Tharwat 发表于 2022-7-5 23:18:39

你好
 
尝试这个简单的示例,它展示了使用错误平铺属性的一种方法,它应该非常清楚地演示示例的目的。
 
DCL代码(保存到test.DCL)
 

test : dialog
       { label = "Example";
         : boxed_row {
         : edit_box { label = "First: "; key = "f"; alignment = right; width = 16; fixed_width = true;}
         : edit_box { label = "Second :";key = "s"; alignment = right; width = 20; fixed_width = true;}
         
       }
       : spacer { height = 0.5;}
       : boxed_row { alignment = centered;
       : button { label = "accept"; key = "ok"; is_default = true; }
       : button { label = "cancel"; key = "esc"; is_cancel = true; }
       }
       : errtile { key = "a"; alignment = centered;}
       : errtile { key = "b"; alignment = centered;}
       }

 
lisp代码。
 

(defun c:test (/ NumbersOnly dcl_id)
;;    Tharwat 21.6.2014      ;;
(defun NumbersOnly (/ l)
   (mapcar 'set_tile '("a" "b") '("" ""))
   (setq l (mapcar 'get_tile '("f" "s")))
   (cond ((and (not (numberp (read (car l))))
               (not (numberp (read (cadr l))))
          )
          (mapcar 'set_tile
                  '("a" "b")
                  (list "Only numbers is allowed in First cell"
                        "Only numbers is allowed in Second cell"
                  )
          )
         )
         ((not (numberp (read (car l))))
          (set_tile "a" "Only numbers is allowed in First cell")
         )
         ((not (numberp (read (cadr l))))
          (set_tile "b" "Only numbers is allowed in Second cell")
         )
         (t
          (done_dialog)
         )
   )
)
(setq dcl_id (load_dialog "test.dcl"))
(if (not (new_dialog "test" dcl_id))
   (progn (alert " Error in loading the dialog (test.dcl) ")
          (exit)
   )
)
(action_tile "ok" "(NumbersOnly)")
(action_tile "esc" "(done_dialog)")
(start_dialog)
(unload_dialog dcl_id)
(princ)
)

BIGAL 发表于 2022-7-5 23:28:00

比尔,你想过一个滑动条,然后你不能超过最大值。您可以在调用它之前设置最小-最大inc。
 

: slider {
                   key = "size2";
                   min_value= 1;
                   max_value = 250;
                   value = 110;
                   big_increment = 5;
                   }

Bill Tillman 发表于 2022-7-5 23:37:08

嘿,这看起来很酷。我今天应该试试。。。但是现在,会议,会议,会议。我认为我们应该召开一次关于所有会议的会议。

Bill Tillman 发表于 2022-7-5 23:49:39

再次感谢大家对我正在开发的DCL应用程序的帮助。我想知道是否有人能在这方面给我更详细的帮助。以下是我目前掌握的情况:
 
我写了一个脚本,可以从自定义菜单项启动。该脚本加载包含所需块的图形文件,然后加载并执行LISP文件。在此LISP文件中,DCL的以下功能再次由Jeffery P.Sander的网站提供:
 

(defun GetUserInput ()
(setq server_path "//a_very_long_novell/path/")

;;;--- Try to load the DCL file from disk into memory
(if(not(setq dcl_id (load_dialog (strcat server_path "MyDCLFile.dcl"))))
   (progn
   (alert "The DCL file could not be loaded.")
   (exit)
   )
   ;;;--- Else, the DCL file was loaded into memory
   (progn

   ;;;--- Try to load the definition inside the DCL file
   (if (not (new_dialog "SingleGrt" dcl_id))
       (progn
         (alert "The definition could not be found inside the DCL file")
         (exit)
       )
       ;;;--- Else, the definition was loaded, we are ready to roll
       (progn

         ;;;--- If an action event occurs, do this function
         (action_tile "cancel" "(done_dialog 1)")
         (action_tile "accept" "(saveVars)(done_dialog 2)")

         ;;;--- Display the dialog box
         (setq ddiag(start_dialog))

         ;;;--- If the cancel button was pressed - display message
         (if (= ddiag 1)
         (princ "\n \n ...EXAMPLE Cancelled. \n ")
         )

         ;;;--- If the "Okay" button was pressed
         (if (= ddiag 2)
         (princ "\n \n ...Example Complete!")
         )
       )
   )
   )
)

;;;--- Suppress the last echo for a clean exit
(princ)

); end GetUserInput function

(defun saveVars()
;;;--- Save the input from the dialog box
(setq dwgno (get_tile "dwgno")
Span (atof (get_tile "dimA"))
Width (atof (get_tile "dimB"))
)
)

(defun Popup ( title msg flags / wsh )
(vl-catch-all-apply
   (function
   (lambda nil
(setq wsh (vlax-create-object "WScript.Shell"))
(setq res (vlax-invoke-method wsh 'popup msg 0 title flags))
)
   )
   )
(if wsh (vlax-release-object wsh))
;res
)

这是dcl文件:

SingleGrt : dialog {
         label = "My DCL Window";
         initial_focus = "dwgno";
         : column {
         : row {
             : boxed_column {
               : edit_box {
               key = "dwgno";
               label = "Drawing Number";
               edit_width = 12;
               value = "";
               }
             }
         }
    : row {
        : edit_box {
          key = "dimA";
          label = "A Dim (Span)";
          edit_width = 10;
               value = "";
               }
         }
    : row {
        : edit_box {
          key = "dimB";
          label = "B Dim (Width)";
          edit_width = 10;
               value = "";
               }
         }
         : row {
             : boxed_row {
               : button {
               key = "accept";
               label = " Okay ";
               is_default = true;
               }
               : button {
               key = "cancel";
               label = " Cancel ";
               is_default = false;
               is_cancel = true;
               }
             }
         }
         }
}

这是可行的,但我更喜欢塔瓦的方法。说实话,我只是没有足够的DCL经验来理解他做了什么。
DCL需要请求四种不同的输入:
dwgno公司
跨度
宽度
格栅顶部
dwgno可以是任何数字字符串、数字、字母,但不能是#%@等特殊字符。。。
跨度将限制在12“和60”之间
宽度将限制在12“和193”之间
光栅顶部将是任何十进制数,但不应大得离谱。我认为将其限制在1“到24”之间就足够了。
如果用户输入了任何无效的内容,我想快速警告他们,然后让他们重新开始,而不删除他们已经输入的内容。只需给他们一个机会,将错误字段更改为有效答案。它需要一直这样做,直到所有四个字段都被正确填写。
完成后,剩下的代码将接受这四个变量,并发挥神奇的作用。
 
顺便说一句,这将自动创建铝格栅板的制造细节表。我已经很好地完成了代码的编写,但这最后一块拼图将充分证明用户只能输入有效数据,我只需要完成它。如有任何帮助,我们将不胜感激。

BIGAL 发表于 2022-7-6 00:01:05

如果您使用滑块,您可以链接编辑框,使其显示当前值。不确定您是否可以将其锁定为无输入。我使用它的示例允许用户滑动或输入。
 
您有旧版Autocad Customization Guide mine is Release 12(非2012)的副本吗?Autocad帮助中有每种方法的示例
 
好的,它使用文本输出来显示值,看看底部的总宽度。
 

 

: boxed_column {
                   : row {
                   label = "Total width";               
                   : text {
                   key = "cav7";
                   width = 3;
                   fixed_width = true;
                   value = "270";
               }
         }
         }      
页: [1]
查看完整版本: 使用DCL验证用户Inp