entmake vs. Active X with locked layers

Discussion in 'AutoCAD' started by Joe Burke, Aug 7, 2004.

  1. Joe Burke

    Joe Burke Guest

    All,

    Ran into this mess recently. I'm scratching my head for a better Active X solution,
    rather than go back to using entmake.

    The following two functions are designed to place a temporary circle in the drawing
    which is later deleted by the calling function. They both return the circle as a
    vla-object. The first uses Active X. The second uses entmake.

    The problem with Active X, as I see it, is the fact the Add method doesn't support a
    layer argument like entmake. So if the active layer is locked, you cannot change the
    layer, or other properties, of the new object without an error. I could go on... but
    instead I'll just post the code and hope for some insight which hasn't dawned on me
    yet.

    I might add, the implications here seem a bit mind boggling to me. I hope I'm missing
    some easy Active X solution.

    Thanks for all comments.
    Joe Burke

    ;; Active X method:
    ;; Pass a point and a layer name.
    ;; Assume the layer name passed is not locked,
    ;; but the active layer might be.
    ;; If so, you won't be able to change
    ;; the layer of new circle after it's created
    ;; without an error: on locked layer.
    ;; So one possible solution as follows, which may
    ;; need more error checking.
    ;; Change the active layer to the layer name argument,
    ;; then restore the active layer.
    ;; Ugly IMO...
    (defun TempCircleAX (pt lay / rad doc layers space activelay cir)
    (setq rad (/ (getvar "viewsize") 125.0))
    (setq doc (vla-get-activedocument (vlax-get-acad-object)))
    (setq layers (vla-get-layers doc))
    (if (= 1 (vlax-get doc 'ActiveSpace))
    (setq space (vla-get-ModelSpace doc))
    (setq space (vla-get-PaperSpace doc))
    )
    (setq activelay (vlax-get doc 'ActiveLayer))
    (vlax-put doc 'ActiveLayer (vla-item layers lay))
    (setq cir (vlax-invoke space 'AddCircle pt rad))
    (vlax-put doc 'ActiveLayer activelay)
    cir ;return vla circle object
    ) ;end


    ;; entmake method:
    ;; Pass a point and a layer name.
    ;; Clean and easy.
    (defun TempCircleMake (pt lay / rad)
    (setq rad (/ (getvar "viewsize") 125.0))
    (if
    (entmake (list '(0 . "CIRCLE")
    (cons 8 lay)
    (cons 10 pt)
    (cons 40 Rad))
    )
    (vlax-ename->vla-object (entlast)) ;return vla circle object
    )
    ) ;end
     
    Joe Burke, Aug 7, 2004
    #1
  2. Joe Burke

    Doug Broad Guest

    Hi Joe,
    Both of your functions look good. I don't see a need to use ActiveX except
    for objectdbx or within a reactor callback. If entmake is easier to implement,
    and makes clearer code, then that's what I'd use.

    One problem with your activeX version is that if layer lay doesn't exist already
    the function will bomb at the (vla-item..)

    I'd also be tempted to add the block(space) and the radius to the argument
    list of the ActiveX version, making the function more general. I'd also get the
    document from the block rather than assume the activedocument.

    Regards,
    Doug
     
    Doug Broad, Aug 7, 2004
    #2
  3. Joe Burke

    John Uhden Guest

    A few embedded suggestions <yikes! sure makes (entmake) look a lot easier>...

    (defun TempCircleAX (pt lay / rad doc layers space ActiveLay Unlocked cir)
    (and
    (setq rad (/ (getvar "viewsize") 125.0))
    (setq doc (vla-get-activedocument (vlax-get-acad-object)))
    (setq layers (vla-get-layers doc))
    (setq ActiveLay (vla-get-activelayer doc))
    ;; determine whether in PaperSpace or ModelSpace
    ;; (which could be a Model Space viewport)
    (if (= 1 (vla-getvariable doc "cvport"))
    (setq space (vla-get-PaperSpace doc))
    (setq space (vla-get-ModelSpace doc))
    )
    ;; If there is no layer named (eval lay)
    (or
    (not
    (vl-catch-all-error-p
    (vl-catch-all-apply
    'vla-item (list Layers Lay)
    )
    )
    )
    ;; then try to add the layer
    (not
    (vl-catch-all-error-p
    (vl-catch-all-apply
    'vla-add (list Layers Lay)
    )
    )
    )
    )
    ;; Set a variable whether the ActiveLay is unlocked,
    ;; and unlock it if necessary.
    (or
    (setq Unlocked (= (vla-get-lock ActiveLay) :vlax-false))
    (not (vla-put-lock ActiveLay :vlax-false))
    )
    ;; Create the circle (on the ActiveLay)
    (setq cir (vlax-invoke space 'AddCircle pt rad))
    ;; Change its layer to (eval lay)
    (not (vla-put-layer Cir Lay))
    ;; If the ActiveLay was locked, then lock it again.
    (or
    Unlocked
    (not (vla-put-lock ActiveLay :vlax-true))
    )
    )
    cir ;return vla circle object
    )
     
    John Uhden, Aug 8, 2004
    #3
  4. Joe Burke

    Doug Broad Guest

    Hi John,

    Is there any particular advantage to
    over
    (vla-add layers lay)

    ?

    I mean why check to see if a layer exists, especially
    in such a complex fashion, when adding a layer does
    not create a error even if one already exists.

    Also, why would one ever want the current layer locked?
    Wouldn't it be better to just
    (vla-put-lock <layer> :vlax-false)
    and be done with it?

    Hope you've been well.

    Regards,
    Doug
     
    Doug Broad, Aug 8, 2004
    #4
  5. Joe Burke

    John Uhden Guest

    Thank you, Doug. I get so used to "catching" things that I forget some of the
    friendly methods. Then again, since Joe wanted to use pure VLisp, I wanted to
    include an ActiveX counterpart to (snvalid). But you're right that the first
    catch-all isn't needed.

    As to locked layers, one never knows what the user has done or wants to do. I
    would <almost always> not build a routine that changes a setting without putting
    it back.
     
    John Uhden, Aug 8, 2004
    #5
  6. Joe Burke

    Kerry Brown Guest

    Joe,
    The layer locked checking is redundant.

    Have you tried something like this :
    With these in a library, 'cause they get used all the time :
    ;;;------------------------------------------------------------------
    (defun fx:activestuff ()
    (vl-load-com)
    ;;
    ;;; IAcadApplication Object
    (or gx:acadapp (setq gx:acadapp (vlax-get-acad-object)))
    ;;
    ;;; IAcadDocument Object
    (or gx:activedoc (setq gx:activedoc (vla-get-activedocument
    gx:acadapp)))
    ;;
    ;;; IAcadModelSpace Object
    (or gx:modelspace (setq gx:modelspace (vla-get-modelspace
    gx:activedoc)))
    ;;
    ;;; IAcadBlocks Collection
    (or gx:blocks (setq gx:blocks (vla-get-blocks gx:activedoc)))
    ;;
    ;;; IAcadLayers Collection
    (or gx:layers (setq gx:layers (vla-get-layers gx:activedoc)))
    ;;
    ;;
    ;;;; < snip >
    (princ)
    )
    ;;;------------------------------------------------------------------
    ;;; Returns object to active space (ModelSpace or PaperSpace )
    ;;; (fx:activespace)
    ;;;
    (defun fx:activespace ()
    (if (= acmodelspace (vla-get-activespace gx:activedoc))
    gx:modelspace
    (if (= :vlax-true (vla-get-mspace gx:activedoc))
    gx:modelspace
    (vla-get-paperspace gx:activedoc)
    )
    )
    )
    ;;;------------------------------------------------------------------
    ;;;------------------------------------------------------------------

    the actual routine becomes a little cleaner :

    (defun TempCircleAX (pt sLay / oCirc)
    (fx:activestuff)
    (vla-add gx:layers sLay)
    (vla-put-layer (setq oCirc (vla-addcircle
    (fx:activespace)
    pt
    (/ (getvar "viewsize") 125.0)))
    sLay
    )
    oCirc
    )
    ;;;------------------------------------------------------------------

    (setq oTempCircle (TempCircleAX (vlax-3d-point (list 100 100 0))
    "Temp"))

    ;;;------------------------------------------------------------------
    You will see that this (vla-add gx:layers slay) ensures the layer
    actually exists.
    Rather than change the layer, this routine just assigns the new object
    to the required layer.

    Regards
    kwb


    ;;>>>>>>>>>>>>>>>>>>

    All,

    Ran into this mess recently. I'm scratching my head for a better Active
    X solution,
    rather than go back to using entmake.

    The following two functions are designed to place a temporary circle in
    the drawing
    which is later deleted by the calling function. They both return the
    circle as a
    vla-object. The first uses Active X. The second uses entmake.

    The problem with Active X, as I see it, is the fact the Add method
    doesn't support a
    layer argument like entmake. So if the active layer is locked, you
    cannot change the
    layer, or other properties, of the new object without an error. I could
    go on... but
    instead I'll just post the code and hope for some insight which hasn't
    dawned on me
    yet.

    I might add, the implications here seem a bit mind boggling to me. I
    hope I'm missing
    some easy Active X solution.

    Thanks for all comments.
    Joe Burke

    ;; Active X method:
    ;; Pass a point and a layer name.
    ;; Assume the layer name passed is not locked,
    ;; but the active layer might be.
    ;; If so, you won't be able to change
    ;; the layer of new circle after it's created
    ;; without an error: on locked layer.
    ;; So one possible solution as follows, which may
    ;; need more error checking.
    ;; Change the active layer to the layer name argument,
    ;; then restore the active layer.
    ;; Ugly IMO...
    (defun TempCircleAX (pt lay / rad doc layers space activelay cir)
    (setq rad (/ (getvar "viewsize") 125.0))
    (setq doc (vla-get-activedocument (vlax-get-acad-object)))
    (setq layers (vla-get-layers doc))
    (if (= 1 (vlax-get doc 'ActiveSpace))
    (setq space (vla-get-ModelSpace doc))
    (setq space (vla-get-PaperSpace doc))
    )
    (setq activelay (vlax-get doc 'ActiveLayer))
    (vlax-put doc 'ActiveLayer (vla-item layers lay))
    (setq cir (vlax-invoke space 'AddCircle pt rad))
    (vlax-put doc 'ActiveLayer activelay)
    cir ;return vla circle object
    ) ;end


    ;; entmake method:
    ;; Pass a point and a layer name.
    ;; Clean and easy.
    (defun TempCircleMake (pt lay / rad)
    (setq rad (/ (getvar "viewsize") 125.0))
    (if
    (entmake (list '(0 . "CIRCLE")
    (cons 8 lay)
    (cons 10 pt)
    (cons 40 Rad))
    )
    (vlax-ename->vla-object (entlast)) ;return vla circle object
    )
    ) ;end
     
    Kerry Brown, Aug 8, 2004
    #6
  7. Joe Burke

    Kerry Brown Guest

    Joe,
    Ahhhh I should have read your post fully [twice]

    Yes, If the Current layer is locked, the routine errors out. ..
    .... but why the current layer would be locked is another issue.


    Regards.Kerry
     
    Kerry Brown, Aug 8, 2004
    #7
  8. Joe Burke

    Joe Burke Guest

    Doug, John and Kerry,

    Thanks for your thoughts on this. I'm still chew'n on what to do. Will post something
    later.

    Regards
    Joe Burke
     
    Joe Burke, Aug 8, 2004
    #8
  9. Joe Burke

    Joe Burke Guest

    Well I guess I'll take Doug's advice and John's hint, use entmake in this case.

    I appreciate the other points of advice offered. I may have given the mistaken
    impression TempCircle is a toolbox function. It's not. It's a sub-function in a
    program which offers a couple was to change the angle of a line. The temporary circle
    indicates the start point, so the user knows which end is the rotation base point.

    The layer name that's passed (lay) is determined by selecting the line. So there's no
    question whether the layer exists. When that's an issue I use this, which probably
    came from Doug, John or Robert.

    (defun ValidItem (collection item / vobj)
    (vl-catch-all-apply
    '(lambda ()
    (setq vobj (vla-item collection item))))
    vobj
    )

    I offer the following as a possible toolbox solution based on John's suggestion.
    Comments welcome. The example is a modified version of the original TempCircle
    function.

    ;; JB 8/8/2004
    ;; Toggle the active layer lock to ensure
    ;; it is not locked while using Add methods.
    ;; Does nothing if the active layer is
    ;; unlocked to begin with.
    ;-1 = locked, 0 = unlocked
    (defun ActiveLayerLock ( / ActiveLay )
    (setq ActiveLay
    (vlax-get
    (vla-get-activedocument
    (vlax-get-acad-object)) 'ActiveLayer))
    (or
    (and
    ;active layer is locked - unlock it
    (= -1 (vlax-get ActiveLay 'Lock))
    (not (vlax-put ActiveLay 'Lock 0))
    (setq lockflag T)
    )
    (and
    ;if lockflag - relock the active layer
    lockflag
    (not (vlax-put ActiveLay 'Lock -1))
    (setq lockflag nil)
    )
    )
    )

    ;; Example use of ActiveLayerLock.
    ;; Pass a point and a layer "name".
    (defun TempCircle (pt lay / doc space rad cir)
    (setq doc (vla-get-activedocument (vlax-get-acad-object)))
    (if (= 1 (vlax-get doc 'ActiveSpace))
    (setq space (vla-get-ModelSpace doc))
    (setq space (vla-get-PaperSpace doc))
    )
    (setq rad (/ (getvar "viewsize") 125.0))
    (ActiveLayerLock) ;added here
    (setq cir (vlax-invoke space 'AddCircle pt rad))
    (vlax-put cir 'Layer lay)
    (ActiveLayerLock) ;and here
    cir ;return vla-object
    ) ;end

    Regards and thanks,
    Joe Burke
     
    Joe Burke, Aug 8, 2004
    #9
  10. Joe Burke

    Doug Broad Guest

    You're welcome Joe. BTW, when accessing an individual
    layer, you never need anything but (vla-add-layer <layers> "layername")
    if you're unsure that the layer exists. It returns the layer if it exists
    and makes one if it didn't exist. It returns the same object that (vla-item...) does.
     
    Doug Broad, Aug 8, 2004
    #10
  11. Joe Burke

    Doug Broad Guest

    You're welcome John. Good to see you posting again.
    I agree that most of the time you don't want side effects.
    Liked your layer filter delete solution.
     
    Doug Broad, Aug 8, 2004
    #11
  12. Joe Burke

    John Uhden Guest

    Joe:

    Just one constructive criticism:
    You're still usting 'ActiveSpace instead of "CVPORT"
     
    John Uhden, Aug 8, 2004
    #12
  13. Joe Burke

    Joe Burke Guest

    Kerry,

    As John said, who knows why the active layer might be locked. It might be
    intentional. Or it might be caused by a missed selection in the layer toolbar menu.
    Or it might be the result of some function which sets the active layer. Whatever the
    reason, it is a potential problem when using Add methods which subsequently expect to
    use Put methods.

    It would be nice if the Add methods allowed an optional layer argument to avoid the
    locked layer problem. Do we think so?

    I was tempted by Doug's suggestion.
    Seems too dangerous to me. Even if setting the active layer to a locked layer was a
    mistake, unlocking without relocking could cause unexpected results down-the-road.

    On a related tangent... I've never understood the logic behind allowing things to be
    drawn, or programmatically put, on a locked layer. I mean if the layer is locked, it
    seems to me all changes should not be allowed. Maybe there's history behind this I'm
    not aware of. I've only used ACAD since A2k.

    Joe Burke


     
    Joe Burke, Aug 8, 2004
    #13
  14. Joe Burke

    John Uhden Guest

    Joe:

    Seriously. I lock layers all the time 'cause I want to change objects only on
    certain layers by crossing. Typically it's like -LA;L;*;U;<whatever>;
    So the even the current layer wants to be locked. After the editing it's
    just -LA;U;*; but any interruption can make me forget to do it.

    Yes, additional 'Add options would be great.
     
    John Uhden, Aug 8, 2004
    #14
  15. Joe Burke

    Joe Burke Guest

    John,

    RE:
    Only because I'm confused the distinction between these two.

    ;; determine whether in PaperSpace or ModelSpace
    ;; (which could be a Model Space viewport)
    (if (= 1 (vla-getvariable doc "cvport"))
    (setq space (vla-get-PaperSpace doc))
    (setq space (vla-get-ModelSpace doc))
    )

    (if (= 1 (vlax-get doc 'ActiveSpace))
    (setq space (vla-get-ModelSpace doc))
    (setq space (vla-get-PaperSpace doc))
    )

    Please explain for the feeble minded.

    I've only tested these functions in model space, where I'd expect them to be used.
    Now I see there is a problem if I'm in paper space. The circle isn't drawn at the
    start point of the line. I'm not sure why yet.

    Thanks
    Joe
     
    Joe Burke, Aug 8, 2004
    #15
  16. Joe,

    If you have a layout active, but have used MSpace or VPMax to get to
    ModelSpace within a floating window, ActiveSpace still returns PaperSpace.


    --
    R. Robert Bell


    John,

    RE:
    Only because I'm confused the distinction between these two.

    ;; determine whether in PaperSpace or ModelSpace
    ;; (which could be a Model Space viewport)
    (if (= 1 (vla-getvariable doc "cvport"))
    (setq space (vla-get-PaperSpace doc))
    (setq space (vla-get-ModelSpace doc))
    )

    (if (= 1 (vlax-get doc 'ActiveSpace))
    (setq space (vla-get-ModelSpace doc))
    (setq space (vla-get-PaperSpace doc))
    )

    Please explain for the feeble minded.

    I've only tested these functions in model space, where I'd expect them to be
    used.
    Now I see there is a problem if I'm in paper space. The circle isn't drawn
    at the
    start point of the line. I'm not sure why yet.

    Thanks
    Joe
     
    R. Robert Bell, Aug 8, 2004
    #16
  17. Joe Burke

    John Uhden Guest

    What Robert said. The ActiveSpace may be Paper but the current viewport may be
    in Model. Since CVPORT can be 1 only when in a PaperSpace viewport, any other
    value means a ModelSpace viewport is current, regardless of ActiveSpace.
     
    John Uhden, Aug 9, 2004
    #17
  18. Joe Burke

    Joe Burke Guest

    Thanks Robert and John.

    Joe Burke
     
    Joe Burke, Aug 9, 2004
    #18
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.