本帖最后由 作者 于 2008-4-29 21:46:22 编辑
一直以来,我们都希望能找到一种简便的方法来实现VBA程序中的先选择后操作。
以前也提供过一种方法,见二次开发栏目的有关PickfirstSelectionSet方法的讨论 文章。
虽然以前提供过方法,但这种方法的缺点是:
1.过程复杂,要写个事件来触发,而且需要写个空的LISP程序来配合,这对一般用户来说有些难度,所以很多开发者最后都放弃使用先选择后操作(呵呵,包括我在内)。
2.这种方法存在BUG,这个BUG本身是AutoCAD的缺陷,而且直到2005都没有解决,看来Autodesk一直就对AX方法不太重视。这个BUG是,当所触发的程序都有对话框,而且对话框需要与AutoCAD交互(如隐藏对话框选择对象或点等操作),当隐藏对话框后,屏幕中无法操作鼠标,只能使用键盘。
所以因为存在着这样的BUG,我写的那个“对象对齐与均布”的程序也没有使用这个功能(本来象那样的程序就需要可以先选择后操作)。
现在终于找到简单解决的方法,所以与大家分享。
大家都知道,使用LISP函数或AutoCAD命令来调用VBA过程,都会因为触发了其它命令而使PickfirstSelectionSet无法得到刚选定的选择集。但如果使用AX的RunMacro方法,则因为是AX方法,而不影响刚选定选择集的存在。对于VL来说,同样可以调用RunMacro方法,大家可以试试以下的LISP程序:- (defun C:VBARUNX ()
- (vl-load-com)
- (vla-runmacro
- (vlax-get-acad-object)
- (getstring "\n宏名称: ")
- )
- (princ)
- )
运行后输入你需要运行的宏(过程),格式为:DVB文件!模块名.过程名
呵呵,忘了给大家一个样例,将以下的程序保存为CC.DVB文件,注意放到支持目录下,这样就可以先选定图形中的一些对象,然后输入VBARUNX,在出现宏名称提示时输入CC.DVB!CC ,看看图形中的对象是不是变成绿色的。
- Function PickFirstSSet() As AcadSelectionSet
- On Error Resume Next
- ThisDrawing.SelectionSets("PICKFIRST").Delete
- Set PickFirstSSet = ThisDrawing.PickfirstSelectionSet
- If PickFirstSSet.Count = 0 Then PickFirstSSet.SelectOnScreen
- End Function
- Sub CC()
- Dim Ent As AcadEntity
- Dim SS As AcadSelectionSet
- Set SS = PickFirstSSet
- For Each Ent In SS
- Ent.color = acGreen
- Next
- End Sub
虽然已经找到了方法,我们就把上一次给大家的一个自动加载及执行VBA程序的函数改一下,变成兼容“先选择后操作”方式:
- ;;自动加载VBA程序的函数
- (defun AutoVBALoad (app cmdliste / qapp)
- (vl-load-com)
- (setq qapp (strcat """ app """))
- (mapcar
- '(lambda (cmd / nom_cmd dot nodotcmd)
- (progn
- (setq dot (vl-string-search "." cmd))
- (if dot
- (setq nodotcmd (substr cmd (+ dot 2)))
- (setq nodotcmd cmd)
- )
- (setq nom_cmd (strcat "C:" nodotcmd))
- (eval
- (read (strcat
- "(defun " nom_cmd "(/ app)"
- "(if (setq app(fdvbfile " qapp "))"
- "(vla-runmacro (vlax-get-acad-object) (strcat app "!" cmd ""))"
- "(nodvbfile " qapp "))"
- "(princ ))"
- )))))
- cmdliste
- )
- (princ)
- )
- (defun fdvbfile (app)
- (if (not (findfile app))
- (if (not (findfile (strcat app ".dvb"))) nil (strcat app ".dvb")) app)
- )
- (defun nodvbfile (filename)
- (princ (strcat "\n文件 " filename "(.dvb) 在搜索路径文件夹中未找到。" ))
- (princ "\n请检查支持文件的安装,然后重试。")
- (princ)
- )
这样刚才那个VBA过程就可以这样加载:- (AutoVBALoad "CC" '("cc"))
复制代码 好了,选定一些对象后,输入“CC”看看,是不是很简单。
顺便也给大家介绍一下“先选择后操作”在VBA中是怎样写选择集的,大家可以看到刚才的VBA程序中使用了一个自定义函数:
- Function PickFirstSSet() As AcadSelectionSet
- On Error Resume Next
- ThisDrawing.SelectionSets("PICKFIRST").Delete
- Set PickFirstSSet = ThisDrawing.PickfirstSelectionSet
- If PickFirstSSet.Count = 0 Then PickFirstSSet.SelectOnScreen
- End Function
这个函数包含了以下的功能:
1.生成选择集。
2.把用户已经选定的对象放在选择集中。
3.如果用户没有选定对象,则提示用户选择对象。
呵呵,就这么几行就可以解决这么多问题,而且还解决了选择集的BUG。这个BUG就不介绍了,论坛中已经介绍过好多次了。
大家在写程序过程中用这个函数来做选择。
|