如何在 AutoLISP 中让用户 select 个实体或 KWord?
How to let user select entities or KWord in AutoLISP?
在我的命令中,我想让用户 select 实体,但如果他愿意,他应该能够使用 KWord。
类似于带有提示的命令:
Select elements od [Settings]:
我知道我可以在 entsel
时使用 KWord。
但是 entsel
只允许我 select 一个实体,
ssget
让我 select 许多实体 - 这是需要的,但不能使用 KWords。
或者我错配了什么?
您知道加入两者的方法吗:select 许多实体和 KWord?
由于 AutoLISP ssget
函数提供了自己的关键字以允许用户启动任何标准选择方法(Window、Crossing、Fence 等),因此它不是以下方法之一initget
(关键字初始化)函数支持的函数:
Expects a point or Window/Last/Crossing/BOX/ALL/Fence/WPolygon/CPolygon/Group/Add/Remove/Multiple/Previous/Undo/AUto/SIngle
我想到了两种替代技术,它们可能允许用户提供任意预定义关键字,同时还允许多项选择:
在 while
循环中使用 entsel
或 nentsel
选择,允许多个单选选择(即使用选择框光圈选择,没有 window选择)。
通过在循环中使用 grread
函数来开发您自己的 ssget
函数,以持续捕获用户输入。
我在 2010 年尝试了后者,当时我开发了 'UCS-aligned ssget function'(即选择 window 与活动 UCS 对齐) - 完全控制用户输入的处理方式,然后您可以定义自己的关键字,并在输入匹配此类关键字时做出相应的反应:
;;------------------=={ UCS Aligned ssget }==-----------------;;
;; ;;
;; Provides the user with a selection interface akin to ;;
;; those options provided by ssget, but aligned to the ;;
;; active UCS ;;
;;------------------------------------------------------------;;
;; Author: Lee Mac, Copyright © 2011 - www.lee-mac.com ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; msg - prompt to be displayed ;;
;; filter - optional SelectionSet filter ;;
;;------------------------------------------------------------;;
;; Returns: SelectionSet, else nil ;;
;;------------------------------------------------------------;;
(defun LM:UCS-ssget
(
msg filter /
*error* _redrawss _getitem _getwindowselection
acgrp e express g1 g2 gr grp i mss multiplemode pick pt removemode singlemode ss str
)
(defun *error* ( msg )
(_redrawss ss 4)
(if (not (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*"))
(princ (strcat "\nError: " msg))
)
(princ)
)
(defun _redrawss ( ss mode / i )
(if ss
(repeat (setq i (sslength ss))
(redraw (ssname ss (setq i (1- i))) mode)
)
)
)
(defun _getitem ( collection item )
(if
(not
(vl-catch-all-error-p
(setq item
(vl-catch-all-apply 'vla-item (list collection item))
)
)
)
item
)
)
(defun _getwindowselection ( msg p1 filter flag / gr p2 p3 p4 lst )
(princ msg)
(while (not (= 3 (car (setq gr (grread t 13 0)))))
(cond
( (= 5 (car gr))
(redraw)
(setq p3 (cadr gr)
p2 (list (car p3) (cadr p1) (caddr p3))
p4 (list (car p1) (cadr p3) (caddr p3))
)
(grvecs
(setq lst
(list
(cond
( (eq "_C" flag) -256)
( (eq "_W" flag) 256)
( (minusp (- (car p3) (car p1))) -256)
( 256 )
)
p1 p2 p1 p4 p2 p3 p3 p4
)
)
)
t
)
( (princ (strcat "\nInvalid Window Specification." msg)) )
)
)
(redraw)
(ssget (cond ( flag ) ( (if (minusp (car lst)) "_C" "_W") )) p1 p3 filter)
)
(setq express
(and (vl-position "acetutil.arx" (arx))
(not
(vl-catch-all-error-p
(vl-catch-all-apply
(function (lambda nil (acet-sys-shift-down)))
)
)
)
)
)
(setq acdoc (cond ( acdoc ) ( (vla-get-activedocument (vlax-get-acad-object)) ))
acgrp (vla-get-groups acdoc)
)
(if
(not
(and
(= 1 (getvar 'PICKFIRST))
(setq ss (cadr (ssgetfirst)))
)
)
(setq ss (ssadd))
)
(setq str "")
(sssetfirst nil nil)
(princ msg)
(while
(progn
(setq gr (grread t 13 2)
g1 (car gr)
g2 (cadr gr)
)
(_redrawss ss 3)
(cond
( (= 5 g1) )
( (= 3 g1)
(cond
( RemoveMode
(if
(and
(setq pick (ssget g2 filter))
(setq pick (ssname pick 0))
)
(if (ssmemb pick ss)
(progn (ssdel pick ss) (redraw pick 4))
)
(if (setq pick (_getwindowselection "\nSpecify Opposite Corner: " g2 filter nil))
(repeat (setq i (sslength pick))
(if (ssmemb (setq e (ssname pick (setq i (1- i)))) ss)
(progn (ssdel e ss) (redraw e 4))
)
)
)
)
(princ msg)
)
( MultipleMode
(if
(and
(setq pick (ssget g2 filter))
(setq pick (ssname pick 0))
)
(ssadd pick mss)
)
t
)
( t
(if
(and
(setq pick (ssget g2 filter))
(setq pick (ssname pick 0))
)
(if (and express (acet-sys-shift-down))
(if (ssmemb pick ss)
(progn (ssdel pick ss) (redraw pick 4))
)
(ssadd pick ss)
)
(if (setq pick (_getwindowselection "\nSpecify Opposite Corner: " g2 filter nil))
(if (and express (acet-sys-shift-down))
(repeat (setq i (sslength pick))
(if (ssmemb (setq e (ssname pick (setq i (1- i)))) ss)
(progn (ssdel e ss) (redraw e 4))
)
)
(repeat (setq i (sslength pick))
(ssadd (ssname pick (setq i (1- i))) ss)
)
)
)
)
(princ msg)
(not SingleMode)
)
)
)
( (= 2 g1)
(cond
( (member g2 '(32 13))
(cond
( (zerop (strlen str))
nil
)
( t
(if mss
(progn
(repeat (setq i (sslength mss))
(ssadd (ssname mss (setq i (1- i))) ss)
)
(setq mss nil)
)
)
(cond
( (wcmatch (setq str (strcase str)) "R,REMOVE")
(setq
MultipleMode nil
SingleMode nil
RemoveMode T
)
)
( (wcmatch str "M,MULTIPLE")
(setq
RemoveMode nil
SingleMode nil
MultipleMode T
mss (ssadd)
)
)
( (wcmatch str "A,ADD,AUTO")
(setq
MultipleMode nil
RemoveMode nil
SingleMode nil
)
t
)
( (wcmatch str "SI,SINGLE")
(setq
MultipleMode nil
RemoveMode nil
SingleMode T
)
)
( (wcmatch str "G,GROUP")
(while
(progn (setq grp (getstring t "\nEnter group name: "))
(cond
( (eq "" grp)
nil
)
( (setq grp (_getitem acgrp grp))
(vlax-for obj grp
(if (not (ssmemb (setq e (vlax-vla-object->ename obj)) ss))
(ssadd e ss)
)
)
nil
)
( (princ "\nInvalid group name.") )
)
)
)
t
)
( (or
(eq str "ALL")
(wcmatch str "P,PREVIOUS")
(wcmatch str "L,LAST")
)
(princ
(strcat "\n"
(if
(setq pick
(ssget
(cond
( (eq str "ALL") "_X")
( (wcmatch str "P,PREVIOUS") "_P")
( (wcmatch str "L,LAST") "_L")
)
filter
)
)
(progn
(repeat (setq i (sslength pick))
(ssadd (ssname pick (setq i (1- i))) ss)
)
(itoa (sslength pick))
)
"0"
)
" found"
)
)
t
)
( (or
(eq str "BOX")
(wcmatch str "W,WINDOW")
(wcmatch str "C,CROSSING")
)
(princ
(strcat "\n"
(if
(and
(setq pt (getpoint "\nSpecify first corner: "))
(setq pick
(_getwindowselection "\nSpecify opposite corner: " pt filter
(cond
( (eq str "BOX") nil)
( (wcmatch str "W,WINDOW") "_W")
( (wcmatch str "C,CROSSING") "_C")
)
)
)
)
(progn
(repeat (setq i (sslength pick))
(ssadd (ssname pick (setq i (1- i))) ss)
)
(itoa (sslength pick))
)
"0"
)
" found"
)
)
t
)
( (wcmatch str "U,UNDO")
(if pick
(cond
( (eq 'ENAME (type pick))
(ssdel pick ss)
(redraw pick 4)
)
( (eq 'PICKSET (type pick))
(repeat (setq i (sslength pick))
(setq e (ssname pick (setq i (1- i))))
(ssdel e ss)
(redraw e 4)
)
)
)
)
t
)
( (eq "?" str)
(princ
(strcat
"\nExpects a point or"
"\nWindow/Last/Crossing/BOX/ALL/Fence/WPolygon/CPolygon"
"/Group/Add/Remove/Multiple/Previous/Undo/AUto/SIngle"
)
)
)
( (princ "\n** Invalid Keyword **") )
)
(setq str "")
(princ msg)
)
)
)
( (< 32 g2 127)
(setq str (strcat str (princ (chr g2))))
)
( (= g2 8)
(if (< 0 (strlen str))
(progn
(princ (vl-list->string '(8 32 8)))
(setq str (substr str 1 (1- (strlen str))))
)
)
t
)
( t )
)
)
)
)
)
(_redrawss ss 4)
ss
)
;; Test function
(defun c:test nil
(sssetfirst nil (LM:UCS-ssget "\nSelect Objects: " nil))
(princ)
)
在我的命令中,我想让用户 select 实体,但如果他愿意,他应该能够使用 KWord。 类似于带有提示的命令:
Select elements od [Settings]:
我知道我可以在 entsel
时使用 KWord。
但是 entsel
只允许我 select 一个实体,
ssget
让我 select 许多实体 - 这是需要的,但不能使用 KWords。
或者我错配了什么?
您知道加入两者的方法吗:select 许多实体和 KWord?
由于 AutoLISP ssget
函数提供了自己的关键字以允许用户启动任何标准选择方法(Window、Crossing、Fence 等),因此它不是以下方法之一initget
(关键字初始化)函数支持的函数:
Expects a point or Window/Last/Crossing/BOX/ALL/Fence/WPolygon/CPolygon/Group/Add/Remove/Multiple/Previous/Undo/AUto/SIngle
我想到了两种替代技术,它们可能允许用户提供任意预定义关键字,同时还允许多项选择:
在
while
循环中使用entsel
或nentsel
选择,允许多个单选选择(即使用选择框光圈选择,没有 window选择)。通过在循环中使用
grread
函数来开发您自己的ssget
函数,以持续捕获用户输入。
我在 2010 年尝试了后者,当时我开发了 'UCS-aligned ssget function'(即选择 window 与活动 UCS 对齐) - 完全控制用户输入的处理方式,然后您可以定义自己的关键字,并在输入匹配此类关键字时做出相应的反应:
;;------------------=={ UCS Aligned ssget }==-----------------;;
;; ;;
;; Provides the user with a selection interface akin to ;;
;; those options provided by ssget, but aligned to the ;;
;; active UCS ;;
;;------------------------------------------------------------;;
;; Author: Lee Mac, Copyright © 2011 - www.lee-mac.com ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; msg - prompt to be displayed ;;
;; filter - optional SelectionSet filter ;;
;;------------------------------------------------------------;;
;; Returns: SelectionSet, else nil ;;
;;------------------------------------------------------------;;
(defun LM:UCS-ssget
(
msg filter /
*error* _redrawss _getitem _getwindowselection
acgrp e express g1 g2 gr grp i mss multiplemode pick pt removemode singlemode ss str
)
(defun *error* ( msg )
(_redrawss ss 4)
(if (not (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*"))
(princ (strcat "\nError: " msg))
)
(princ)
)
(defun _redrawss ( ss mode / i )
(if ss
(repeat (setq i (sslength ss))
(redraw (ssname ss (setq i (1- i))) mode)
)
)
)
(defun _getitem ( collection item )
(if
(not
(vl-catch-all-error-p
(setq item
(vl-catch-all-apply 'vla-item (list collection item))
)
)
)
item
)
)
(defun _getwindowselection ( msg p1 filter flag / gr p2 p3 p4 lst )
(princ msg)
(while (not (= 3 (car (setq gr (grread t 13 0)))))
(cond
( (= 5 (car gr))
(redraw)
(setq p3 (cadr gr)
p2 (list (car p3) (cadr p1) (caddr p3))
p4 (list (car p1) (cadr p3) (caddr p3))
)
(grvecs
(setq lst
(list
(cond
( (eq "_C" flag) -256)
( (eq "_W" flag) 256)
( (minusp (- (car p3) (car p1))) -256)
( 256 )
)
p1 p2 p1 p4 p2 p3 p3 p4
)
)
)
t
)
( (princ (strcat "\nInvalid Window Specification." msg)) )
)
)
(redraw)
(ssget (cond ( flag ) ( (if (minusp (car lst)) "_C" "_W") )) p1 p3 filter)
)
(setq express
(and (vl-position "acetutil.arx" (arx))
(not
(vl-catch-all-error-p
(vl-catch-all-apply
(function (lambda nil (acet-sys-shift-down)))
)
)
)
)
)
(setq acdoc (cond ( acdoc ) ( (vla-get-activedocument (vlax-get-acad-object)) ))
acgrp (vla-get-groups acdoc)
)
(if
(not
(and
(= 1 (getvar 'PICKFIRST))
(setq ss (cadr (ssgetfirst)))
)
)
(setq ss (ssadd))
)
(setq str "")
(sssetfirst nil nil)
(princ msg)
(while
(progn
(setq gr (grread t 13 2)
g1 (car gr)
g2 (cadr gr)
)
(_redrawss ss 3)
(cond
( (= 5 g1) )
( (= 3 g1)
(cond
( RemoveMode
(if
(and
(setq pick (ssget g2 filter))
(setq pick (ssname pick 0))
)
(if (ssmemb pick ss)
(progn (ssdel pick ss) (redraw pick 4))
)
(if (setq pick (_getwindowselection "\nSpecify Opposite Corner: " g2 filter nil))
(repeat (setq i (sslength pick))
(if (ssmemb (setq e (ssname pick (setq i (1- i)))) ss)
(progn (ssdel e ss) (redraw e 4))
)
)
)
)
(princ msg)
)
( MultipleMode
(if
(and
(setq pick (ssget g2 filter))
(setq pick (ssname pick 0))
)
(ssadd pick mss)
)
t
)
( t
(if
(and
(setq pick (ssget g2 filter))
(setq pick (ssname pick 0))
)
(if (and express (acet-sys-shift-down))
(if (ssmemb pick ss)
(progn (ssdel pick ss) (redraw pick 4))
)
(ssadd pick ss)
)
(if (setq pick (_getwindowselection "\nSpecify Opposite Corner: " g2 filter nil))
(if (and express (acet-sys-shift-down))
(repeat (setq i (sslength pick))
(if (ssmemb (setq e (ssname pick (setq i (1- i)))) ss)
(progn (ssdel e ss) (redraw e 4))
)
)
(repeat (setq i (sslength pick))
(ssadd (ssname pick (setq i (1- i))) ss)
)
)
)
)
(princ msg)
(not SingleMode)
)
)
)
( (= 2 g1)
(cond
( (member g2 '(32 13))
(cond
( (zerop (strlen str))
nil
)
( t
(if mss
(progn
(repeat (setq i (sslength mss))
(ssadd (ssname mss (setq i (1- i))) ss)
)
(setq mss nil)
)
)
(cond
( (wcmatch (setq str (strcase str)) "R,REMOVE")
(setq
MultipleMode nil
SingleMode nil
RemoveMode T
)
)
( (wcmatch str "M,MULTIPLE")
(setq
RemoveMode nil
SingleMode nil
MultipleMode T
mss (ssadd)
)
)
( (wcmatch str "A,ADD,AUTO")
(setq
MultipleMode nil
RemoveMode nil
SingleMode nil
)
t
)
( (wcmatch str "SI,SINGLE")
(setq
MultipleMode nil
RemoveMode nil
SingleMode T
)
)
( (wcmatch str "G,GROUP")
(while
(progn (setq grp (getstring t "\nEnter group name: "))
(cond
( (eq "" grp)
nil
)
( (setq grp (_getitem acgrp grp))
(vlax-for obj grp
(if (not (ssmemb (setq e (vlax-vla-object->ename obj)) ss))
(ssadd e ss)
)
)
nil
)
( (princ "\nInvalid group name.") )
)
)
)
t
)
( (or
(eq str "ALL")
(wcmatch str "P,PREVIOUS")
(wcmatch str "L,LAST")
)
(princ
(strcat "\n"
(if
(setq pick
(ssget
(cond
( (eq str "ALL") "_X")
( (wcmatch str "P,PREVIOUS") "_P")
( (wcmatch str "L,LAST") "_L")
)
filter
)
)
(progn
(repeat (setq i (sslength pick))
(ssadd (ssname pick (setq i (1- i))) ss)
)
(itoa (sslength pick))
)
"0"
)
" found"
)
)
t
)
( (or
(eq str "BOX")
(wcmatch str "W,WINDOW")
(wcmatch str "C,CROSSING")
)
(princ
(strcat "\n"
(if
(and
(setq pt (getpoint "\nSpecify first corner: "))
(setq pick
(_getwindowselection "\nSpecify opposite corner: " pt filter
(cond
( (eq str "BOX") nil)
( (wcmatch str "W,WINDOW") "_W")
( (wcmatch str "C,CROSSING") "_C")
)
)
)
)
(progn
(repeat (setq i (sslength pick))
(ssadd (ssname pick (setq i (1- i))) ss)
)
(itoa (sslength pick))
)
"0"
)
" found"
)
)
t
)
( (wcmatch str "U,UNDO")
(if pick
(cond
( (eq 'ENAME (type pick))
(ssdel pick ss)
(redraw pick 4)
)
( (eq 'PICKSET (type pick))
(repeat (setq i (sslength pick))
(setq e (ssname pick (setq i (1- i))))
(ssdel e ss)
(redraw e 4)
)
)
)
)
t
)
( (eq "?" str)
(princ
(strcat
"\nExpects a point or"
"\nWindow/Last/Crossing/BOX/ALL/Fence/WPolygon/CPolygon"
"/Group/Add/Remove/Multiple/Previous/Undo/AUto/SIngle"
)
)
)
( (princ "\n** Invalid Keyword **") )
)
(setq str "")
(princ msg)
)
)
)
( (< 32 g2 127)
(setq str (strcat str (princ (chr g2))))
)
( (= g2 8)
(if (< 0 (strlen str))
(progn
(princ (vl-list->string '(8 32 8)))
(setq str (substr str 1 (1- (strlen str))))
)
)
t
)
( t )
)
)
)
)
)
(_redrawss ss 4)
ss
)
;; Test function
(defun c:test nil
(sssetfirst nil (LM:UCS-ssget "\nSelect Objects: " nil))
(princ)
)