复制时如何更新实体的扩展数据信息

How to update xdata information of an entity when it is copied

我有两个文本与一行相关联。因为文本代表了该行的一些数据,所以它们总是被认为是该行的子项并且在它旁边可见。通过一些 lisp 例程,如果行的数据发生变化,文本实体会通过更改其文本来反映变化。为此,我将每个文本的行句柄存储为 xdata,反之亦然,例如文本句柄到行中。

当我复制包含文本的行时出现问题,其中每个文本都获得一个新句柄,但存储的 xdata 提供旧句柄,这会导致进一步的问题。我认为 vlr-copied 反应堆可以解决我的问题,但由于我对反应堆不是很精通,所以我似乎无法让它工作。

有人能给我指出正确的方向吗?我找到了这个

http://www.theswamp.org/index.php?topic=42654.0

但我无法理解当我选择一组行但还包括不相关的其他实体时,如何将正确的选择集传递给反应器并更新句柄。

任何建议表示赞赏。谢谢你。

首先,您需要确定您希望对象表现出的行为,假设其中一个对象(文本或行)是独立于另一个复制的。由于这两个对象是链接的,您可能需要确定哪个对象是 'master',哪个是 'slave' .

例如,如果将文本对象复制到空 space,您可能会决定应删除生成的副本,因为没有它可以引用的行。然而,如果该行被复制到空 space,您可能会决定复制关联的文本对象并将其相对于新行定位。

这是我在开发 Associative Textbox 应用程序时遵循的方法(它本质上解决了在绘图中关联两个对象的相同问题 - 在我的例子中,一个文本对象和一个边界框)。

在我的应用中,我使用了一个单独的对象反应器来分别处理文本对象和文本框的修改事件:

(vlr-object-reactor txt "tbox-textreactor"
   '(
        (:vlr-modified . tbox:textcallback)
        (:vlr-copied   . tbox:textcopied)
    )
)
(vlr-object-reactor box "tbox-tboxreactor"
   '(
        (:vlr-modified . tbox:tboxcallback)
        (:vlr-copied   . tbox:tboxcopied)
    )
)

与您的设置类似,这些是使用附加到文本和文本框的扩展实体数据 (xData) 在程序加载时构建和配置的。

当 texbox 的 Copy 事件被触发时(评估 tbox:tboxcopied 回调函数),我决定文本框不能没有它包含的文本,所以我从绘图中删除了孤立的文本框。

然而,在使用对象反应器时,您必须记住的最重要的一点是,您不能在其自身的回调函数中修改对象反应器的所有者

因此,对于我需要修改事件所有者的所有修改事件,我生成一个临时命令反应器,它将在 对象被修改后触发,从而保证对象不被锁定修改。

例如,对于文本框复制事件,我使用以下内容:

(defun tbox:tboxcopied ( owner reactor params )
    (if (/= 0 (car params))
        (progn
            (setq tbox:owner (append tbox:owner (list (car params))))
            (vlr-command-reactor "tbox-tboxcopiedcommreactor"
               '(
                    (:vlr-commandended     . tbox:tboxcopiedcommandended)
                    (:vlr-commandcancelled . tbox:tboxcopiedcommandcancelled)
                    (:vlr-commandfailed    . tbox:tboxcopiedcommandcancelled)
                )
            )            
        )
    )
    (princ)
)

然后我在它自己的任何回调函数中删除这个临时命令反应器,以防止绘图中冗余反应器的传播:

(defun tbox:tboxcopiedcommandended ( reactor params / ent )
    (vlr-remove reactor) ;; <----- Remove temporary Command Reactor
    (if
        (and
            (setq ent (car tbox:owner))
            (member (cdr (assoc 0 (entget ent))) '("CIRCLE" "LWPOLYLINE"))
        )
        (entdel ent) ;; <----- Delete orphan textbox
    )
    (setq tbox:owner (cdr tbox:owner))
    (princ)
)

然而,当 text 被复制时,我重新创建了周围的文本框并构建了新的关联(同样,生成了一个临时的 Command Reactor 以方便修改文本对象本身) :

(defun tbox:textcopied ( owner reactor params )
    (if (/= 0 (car params))
        (progn
            (setq tbox:owner (append tbox:owner (list (car params))))
            (vlr-command-reactor "tbox-textcopiedcommreactor"
               '(
                    (:vlr-commandended     . tbox:textcopiedcommandended)
                    (:vlr-commandcancelled . tbox:textcopiedcommandcancelled)
                    (:vlr-commandfailed    . tbox:textcopiedcommandcancelled)
                )
            )
        )
    )
    (princ)
)

...并重新创建适当的文本框作为临时 Command Reactor 回调函数的一部分:

(defun tbox:textcopiedcommandended ( reactor params / box ent enx val )
    (vlr-remove reactor) ;; <----- Remove temporary Command Reactor
    (if
        (and
            (setq ent (car tbox:owner))
            (setq enx (entget ent (list tbox:app)))
            (member (cdr (assoc 0 enx)) '("TEXT" "MTEXT"))
            (setq val (cdadr (assoc -3 enx)))
            (setq box (tbox:createbox enx (cdr (assoc 1000 val)) (cdr (assoc 1040 val))))
        )
        (progn
            (entmod
                (append (vl-remove (assoc 40 enx) (entget ent))
                    (list
                        (list -3
                            (list tbox:app
                               '(1002 . "{")
                                (cons  1005 (cdr (assoc 5 (entget box))))
                                (assoc 1000 val)
                                (assoc 1040 val)
                               '(1002 . "}")
                            )
                        )
                    )
                )
            )
            (if (= 'vlr-object-reactor (type tbox:textreactor))
                (vlr-owner-add tbox:textreactor (vlax-ename->vla-object ent))
            )
            (if (= 'vlr-object-reactor (type tbox:tboxreactor))
                (vlr-owner-add tbox:tboxreactor (vlax-ename->vla-object box))
            )                    
        )            
    )
    (setq tbox:owner (cdr tbox:owner))
    (princ)
)

我上面描述的方法是我会为您的场景推荐的方法:

复制文本时,删除生成的孤立文本对象;当复制时,创建一个相应的文本对象并建立复制行和新文本对象之间的关联