Code reusability - Please help

Discussion in 'AutoCAD' started by Oberer, Nov 2, 2004.

  1. Oberer

    Oberer Guest

    I have code that will examine the current layer name and search for a corrosponding "annotation" layer (ie Sec_3-STM and Sec_3-STM-TXT). Intially, i created a "smart leader" function which would set me on the correct annotation layer. Then i realized i'd also like to apply this to dtext/mtext.

    So, here's my problem: The subs that can be used as commands won't accept arguements, so how do i reuse this code?:

    Public Sub Smart_Leader()
    Dim oLayer As AcadLayer
    Dim oLayers As AcadLayers
    Dim oCurrentLayer As AcadLayer
    Dim strLayerName As String
    Dim bFoundMatchingLayer As Boolean

    bFoundMatchingLayer = False
    Set oCurrentLayer = ThisDrawing.ActiveLayer
    Set oLayers = ThisDrawing.Layers
    For Each oLayer In oLayers
    strLayerName = oLayer.Name
    ' if there;s a matching layer with -TX or _TX
    If InStr(1, strLayerName, oCurrentLayer.Name & "_TX") > 0 Or InStr(1, strLayerName, oCurrentLayer.Name & "-TX") > 0 Then
    ' and it's not a XREF layer
    If InStr(1, strLayerName, "|") = 0 Then
    ThisDrawing.ActiveLayer = oLayer
    ThisDrawing.SendCommand ("le ")
    bFoundMatchingLayer = True
    Exit For
    End If
    End If
    Next oLayer

    ThisDrawing.ActiveLayer = oCurrentLayer
    Set oLayer = Nothing
    Set oLayers = Nothing
    Set oCurrentLayer = Nothing

    'if there was no matching layer found....
    If bFoundMatchingLayer = False Then
    ' stupid API bug doesn't work!
    'ThisDrawing.Utility.Prompt "No corrosponding text layer found "
    ThisDrawing.SendCommand ("le ")
    End If

    End Sub

    (this is how i magine it working, except i can't have the arguments!)
    In the below code, i could pass commands like leader, qleader, dtext & mtext...

    TIA!


    Public Sub getAnnotationLayer(strCommand As String)
    Dim oLayer As AcadLayer
    Dim oLayers As AcadLayers
    Dim oCurrentLayer As AcadLayer
    Dim strLayerName As String
    Dim bFoundMatchingLayer As Boolean

    bFoundMatchingLayer = False
    Set oCurrentLayer = ThisDrawing.ActiveLayer
    Set oLayers = ThisDrawing.Layers
    For Each oLayer In oLayers
    strLayerName = oLayer.Name
    ' if there;s a matching layer with -TX or _TX
    If InStr(1, strLayerName, oCurrentLayer.Name & "_TX") > 0 Or InStr(1, strLayerName, oCurrentLayer.Name & "-TX") > 0 Then
    ' and it's not a XREF layer
    If InStr(1, strLayerName, "|") = 0 Then
    ThisDrawing.ActiveLayer = oLayer
    ThisDrawing.SendCommand (strCommand)
    bFoundMatchingLayer = True
    Exit For
    End If
    End If
    Next oLayer

    ThisDrawing.ActiveLayer = oCurrentLayer
    Set oLayer = Nothing
    Set oLayers = Nothing
    Set oCurrentLayer = Nothing

    'if there was no matching layer found....
    If bFoundMatchingLayer = False Then
    ' stupid API bug doesn't work!
    'ThisDrawing.Utility.Prompt "No corrosponding text layer found "
    ThisDrawing.SendCommand (strCommand)
    End If

    End Sub
     
    Oberer, Nov 2, 2004
    #1
  2. Oberer

    TomD Guest

    corrosponding "annotation" layer (ie Sec_3-STM and Sec_3-STM-TXT).
    Intially, i created a "smart leader" function which would set me on the
    correct annotation layer. Then i realized i'd also like to apply this to
    dtext/mtext.
    arguements, so how do i reuse this code?:

    I couldn't really follow the basic flow of what you have, so I'll just throw
    out my thoughts on how I'd likely approach what you're trying to do.

    Function GetTxtLayerName(sLayerName as String) as String
    'code here to get layer name, similar to what you have, based on what
    layer name is passed to this function
    GetTxtLayerName = WhateverLayerNameYourCodeGrabbedHere
    End Function

    Sub DrawLeader()
    dim vPnt1 as Variant, vPnt2 as Variant, vPnt3 as Variant
    dim oLeader as AcadLeader, sLayer as String
    sLayer = GetTxtLayerName(ThisDrawing.ActiveLayer.Name)
    'initialize user input to disallow null entry, not sure of exact syntax
    With ThisDrawing.Utility
    .InitializeUserInput 1
    vPnt1 = ThisDrawing.Utility.GetPoint(,vbCrLf & "From point: ")
    .InitializeUserInput 1
    vPnt2 = ThisDrawing.Utility.GetPoint(vPnt1, vbCrLf & "To point: ")
    .InitializeUserInput 1
    vPnt3 = ThisDrawing.Utility.GetPoint(vPnt2, vbCrLf & "To point: ")
    End WIth
    'code here to AddLeader, something similar to
    Set oLeader = ThisDrawing.ModelSpace.AddLeader 'again, I don't know the
    arguments, off-hand
    oLeader.Layer = sLayer
    set oLeader = Nothing
    End Sub

    Sorry for the holes in the code, but I didn't want to mislead you. I'd have
    to actually write in the VBA IDE, which I don't have time for, at the
    moment. There are most likely syntax errors, etc. in there, but that's the
    basic idea I'd follow.

    HTH
     
    TomD, Nov 2, 2004
    #2
  3. Oberer

    Matt W Guest

    Matt W, Nov 2, 2004
    #3
  4. Oberer

    Oberer Guest

    Thanks Tom & others.
    What I've realized is that i'm trying to accomplish too much in one routine.

    It's tough being a "dangerous coder" (knowing just enough to really create a mess!)

    Thanks again...
     
    Oberer, Nov 2, 2004
    #4
  5. Oberer

    TomD Guest

    a mess!)

    Yeah, but it sure is fun. ;)
     
    TomD, Nov 2, 2004
    #5
  6. Oberer

    Oberer Guest

    "Yeah, but it sure is fun. ;)"
    Really? could have fooled me today!

    Any ideas of how Acad processes "send commands?"
    What I've found is that if send command calls a user defined function (ie defined via lisp c:XX), send command will pause and continue after the call.
    If, however, it's an internal call, well you know the bad news.

    Here's how i found it:
    The first function works just like i hoped it would->
    ' attempt to find a corrosponding text layer to put leader on
    Public Sub Smart_Leader()
    Dim oCurrentLayer As AcadLayer
    Dim oTextLayer As AcadLayer
    Dim strTextLayer As String
    ' get current layer object
    Set oCurrentLayer = ThisDrawing.ActiveLayer

    Set oTextLayer = getAnnotationLayer

    ' check to see if layer is FROZEN
    If oTextLayer.Freeze = True Then
    oTextLayer.Freeze = False
    End If

    ' check to see if layer is OFF
    If oTextLayer.LayerOn = False Then
    oTextLayer.LayerOn = True
    End If
    ' make text layer current
    ThisDrawing.ActiveLayer = oTextLayer
    ' send Qleader command
    ThisDrawing.SendCommand ("le ")
    ' restore original layer
    ThisDrawing.ActiveLayer = oCurrentLayer
    Set oCurrentLayer = Nothing
    End Sub

    In the above code example, you can physically see the layer change while the leader is created, then going back to the original layer.

    In the next example, the send command doesn't execute until after the sub is over:

    ' attempt to find a corrosponding text layer to put leader on
    Public Sub Smart_Text()
    Dim oCurrentLayer As AcadLayer
    Dim oTextLayer As AcadLayer
    Dim strTextLayer As String
    ' get current layer object
    Set oCurrentLayer = ThisDrawing.ActiveLayer

    Set oTextLayer = getAnnotationLayer

    ' check to see if layer is FROZEN
    If oTextLayer.Freeze = True Then
    oTextLayer.Freeze = False
    End If

    ' check to see if layer is OFF
    If oTextLayer.LayerOn = False Then
    oTextLayer.LayerOn = True
    End If
    ' make text layer current
    ThisDrawing.ActiveLayer = oTextLayer
    ' send Qleader command
    ThisDrawing.SendCommand ("dtext ")
    ' restore original layer
    ThisDrawing.ActiveLayer = oCurrentLayer
    Set oCurrentLayer = Nothing
    End Sub

    finally, i found that if i create a c:XX via lisp (instead of using the PGP) for dtext (ie c:DT), then the function works well.

    Ok, WHY in the world does acad do this to us??
     
    Oberer, Nov 2, 2004
    #6
  7. Oberer

    TomD Guest

    Not always.
    As you'll no doubt hear many times in this NG, you should avoid using
    SendCommand whenever possible, for the reasons you're seeing. Generally
    speaking, there isn't need to use it. (One exception I found, was a case
    where Acad actually crashed if you passed a vbCR to SendCommand. I got
    around it by using VBA's SendKeys method.)

    PGP) for dtext (ie c:DT), then the function works well.
    Again, simply don't do it. I made this same mistake. Bite the bullet and
    learn the *right* ways to do things, thereby avoiding SendCommand.

    Is there some reason you're insisting on using the LE command?
     
    TomD, Nov 3, 2004
    #7
  8. I haven't programmed with ACAD events, but it sounds like this is what you
    would want to use. I would think it would be something like this...

    In the BeginCommand event:

    1) store the current layer name (curLayer)
    2) check to see the command name that was used. If it was either LE, or
    QLEADER, or DTEXT, etc. then:
    2a) set a global boolean such as boolLayerChanged = True
    2b) find the corresponding annotation layer and set the active layer to
    curLayer & "-TXT" or "_TX", etc.

    In the EndCommand event
    1) if boolLayerChanged = True then reset the active layer to curLayer

    I think there are a lot of previous posts about using BeginCommand and
    EndCommand to control the active layer for certain commands. And search the
    NG for "WithEvents" or look in the examples directory for a DVB file with
    EVENTS in the name to see an example.

    If I'm wrong about this stuff, at least it'll get someone who knows what
    they're doing talking...

    GL,
    James



    corrosponding "annotation" layer (ie Sec_3-STM and Sec_3-STM-TXT).
    Intially, i created a "smart leader" function which would set me on the
    correct annotation layer. Then i realized i'd also like to apply this to
    dtext/mtext.
    arguements, so how do i reuse this code?:
     
    James Belshan, Nov 3, 2004
    #8
  9. Oberer

    TomD Guest

    Sounds like a good plan, to me.

    I have a BeginPlot event and it works quite well, with minimal amount of
    code. Very simple.
     
    TomD, Nov 3, 2004
    #9
  10. Oberer

    MP Guest

    hope this gives you some ideas of a way to proceed.
    put your revised version of something like this in the ThisDrawing module of
    Acad.Dvb
    that way it will always be available when you start acad.

    Private Sub AcadDocument_BeginCommand(ByVal CommandName As String)
    Select Case CommandName
    Case "YourCommandName1"
    Call SetLayer1
    Case "YourCommandName2"
    Call SetLayer2
    Case "YourCommandName3"
    Call SetLayer3
    Case Else
    'etc
    End Select
    End Sub

    Private Sub AcadDocument_EndCommand(ByVal CommandName As String)
    Select Case CommandName
    Case "YourCommandName1","YourCommandName2","YourCommandName3"
    Call ReSetLayer
    Case Else
    'etc
    End Select
    End Sub

    Then you need a sub for setLayer for each different layername you want to
    change to depending on what command you're using - and to save the value of
    the previous layername for use by the ResetLayer command

    and another sub to reset the layer after done with command - using the saved
    value of PreviousLayer

    hth
    Mark


    corrosponding "annotation" layer (ie Sec_3-STM and Sec_3-STM-TXT).
    Intially, i created a "smart leader" function which would set me on the
    correct annotation layer. Then i realized i'd also like to apply this to
    dtext/mtext.
    arguements, so how do i reuse this code?:
     
    MP, Nov 3, 2004
    #10
  11. Oberer

    Oberer Guest

    Thanks again for the suggestions. The "with events" concept is exactly what I'm after.

    As for "why am I using send command"? It's obvious that I;m still learning programming and VB(A). With help like this, I'll be MORE than happy to ditch such a flakey method!
     
    Oberer, Nov 3, 2004
    #11
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.