Accessing Document History from VBA

Discussion in 'AutoCAD' started by Jarod Arney, Aug 11, 2003.

  1. Jarod Arney

    Jarod Arney Guest

    Well I solved my previous post (see that thread) by myself. Thanx a lot
    guys. However, I have a new one. I can successfully change profiles based on
    the active drawing for every case I can think of except closing one of the
    active drawings. I can get around it by manually inputting the profile to
    use but that kind of defeats the purpose. Once again, the problem is a
    timing issue. All of the events triggered by a closing drawing happen too
    early to start executing code on another drawing without knowing which item
    in the DocumentsCollection that drawing is going to be. IE ThisDrawing and
    ActiveDocument may or may not point to the right place.
    The obvious solution to me is to just borrow AutoCAD's information on
    what the previously active document was and correlate that with the
    documents collection. However, I have absolutely no idea where AutoCAD is
    storing that value. It has to have it, because it doesn't just go the the
    last document in the collection, it remembers the exact order you went
    through the open documents, but I can't find it anywhere. Anyway, anyone
    have any idea how to find this value?
     
    Jarod Arney, Aug 11, 2003
    #1
  2. Jarod Arney

    Kevin Terry Guest

    You can iterate through the documents collection without ever using
    ActiveDocument - just store the information about all open documents in an
    array or collection (either just the name or the doc itself).

    Application.Documents.Item(?)

    Kevin
     
    Kevin Terry, Aug 12, 2003
    #2
  3. Jarod Arney

    Jarod Arney Guest

    Kevin,
    Yeah I know I can get a list of the documents but the problem is the
    order they were accessed. I know it's a little picky, but I want AutoCAD to
    go back to the last drawing accessed before the current drawing was closed.
    That's the default, but for me to set the profile based on that drawing I
    need to know what that drawing is either by name or ID. I can randomly pick
    a drawing out of the documents collection and set it active, but it would
    break the default AutoCAD history behavior that I kind of like.
    I started trying to create an array that updated as drawings were
    activated, but it was becoming twice as long as the rest of my program
    because of all the ways that documents can be opened, activated, and closed.
    Plus, unless I'm missing something, re-ordering an array isn't the simplest
    operation in the world. I keep coming back to the fact that AutoCAD knows
    the last drawing so it has to be stored somewhere. I'm afraid it may be some
    time of Windows operation.

    Jarod
     
    Jarod Arney, Aug 12, 2003
    #3
  4. Jarod Arney

    Jarod Arney Guest

    Thanks to Ed and Kevin but neither response was what I was looking for. The
    documents collection just gave me all the documents including the one being
    closed, and the recent document list just tells me the most recently
    "opened" not "activated" drawings.
    It turns out it was a windows API call I was looking for, the code is below.

    Declare Function GetNextWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As
    Long, ByVal wFlag As Long) As Long

    'The next lines are placed in the document_beginclose event
    'This line gets the windows handle for the document being closed
    strActiveDocument = ActiveDocument.hwnd
    'This line changes the handle to the last active window
    strActiveDocument = GetNextWindow(ActiveDocument.hwnd, 2)

    Now you can compare the items in the document collection to the window
    handle for the previously active document and get whatever information you
    need.
     
    Jarod Arney, Aug 14, 2003
    #4
  5. Jarod Arney

    Ed Jobe Guest

    You can use the win api, but its better to stick with the object model
    you're working with. If you upgrade the os, the api can change. Try this:

    'Declarations
    Private oCurDoc As AcadDocument
    Private oPrevDoc As AcadDocument

    Private Sub Doc_Activate()
    If oCurDoc Is Nothing Then
    'the first time a dwg is opened, cur & prev are the same
    Set oCurDoc = AcadApplication.Documents(ThisDrawing.Name)
    Set oPrevDoc = oCurDoc
    Else
    Set oPrevDoc = oCurDoc
    Set oCurDoc = AcadApplication.Documents(ThisDrawing.Name)
    End If
    MsgBox oPrevDoc.Name

    End Sub
     
    Ed Jobe, Aug 14, 2003
    #5
  6. Jarod Arney

    Jarod Arney Guest

    I agree with your concerns about the API. However, if I follow the logic
    correctly with the code below, it is only good for closing one drawing. If
    you have three open drawings, closing the first one will be OK, but then the
    value of OPrevDoc is the drawing you just closed and it is no longer
    available. I started down this path but trying to track an unspecified
    number of open drawings and adjusting for closing some of them ends up being
    more than I was willing to tackle. I could be missing something and making
    this more complicated then it really is.

    Jarod
     
    Jarod Arney, Aug 14, 2003
    #6
  7. Jarod Arney

    Ed Jobe Guest

    Did you try it. It worked for me. I designed it only as a quick example of
    tracking while switching between dwgs, which also works when opening them.
    You will have to add to it to account for closing dwgs. Its quittin' time.
    I'll look at it again tomorrow if I get the chance.
     
    Ed Jobe, Aug 14, 2003
    #7
  8. This has been an interesting thread, but one question I haven't seen asked
    is: Why are you changing profiles for each drawing? Isn't there a tree in
    this forest you might be missing?

    --
    R. Robert Bell, MCSE
    www.AcadX.com


    | Did you try it. It worked for me. I designed it only as a quick example of
    | tracking while switching between dwgs, which also works when opening them.
    | You will have to add to it to account for closing dwgs. Its quittin' time.
    | I'll look at it again tomorrow if I get the chance.
    |
    | --
    | Ed
    | --
    |
    | | > I agree with your concerns about the API. However, if I follow the logic
    | > correctly with the code below, it is only good for closing one drawing.
    If
    | > you have three open drawings, closing the first one will be OK, but then
    | the
    | > value of OPrevDoc is the drawing you just closed and it is no longer
    | > available. I started down this path but trying to track an unspecified
    | > number of open drawings and adjusting for closing some of them ends up
    | being
    | > more than I was willing to tackle. I could be missing something and
    making
    | > this more complicated then it really is.
    | >
    | > Jarod
    | >
    | > | > > You can use the win api, but its better to stick with the object model
    | > > you're working with. If you upgrade the os, the api can change. Try
    | this:
    | > >
    | > > 'Declarations
    | > > Private oCurDoc As AcadDocument
    | > > Private oPrevDoc As AcadDocument
    | > >
    | > > Private Sub Doc_Activate()
    | > > If oCurDoc Is Nothing Then
    | > > 'the first time a dwg is opened, cur & prev are the same
    | > > Set oCurDoc = AcadApplication.Documents(ThisDrawing.Name)
    | > > Set oPrevDoc = oCurDoc
    | > > Else
    | > > Set oPrevDoc = oCurDoc
    | > > Set oCurDoc = AcadApplication.Documents(ThisDrawing.Name)
    | > > End If
    | > > MsgBox oPrevDoc.Name
    | > >
    | > > End Sub
    | > >
    | > > --
    | > > Ed
    | >
    | >
    |
    |
     
    R. Robert Bell, Aug 15, 2003
    #8
  9. Jarod Arney

    Jarod Arney Guest

    I don't need to change the profile for every drawing but we do
    consulting work for dozens of clients and rather then have everybody try and
    remember the settings for each client, we have a massive set of LISP
    routines that automate as much as possible. Each client has a profile with
    the appropriate paths to data and templates for that client. In the past
    each user had 12-20 icons for AutoCAD, one for each client they work with.
    If they wanted to start a drawing for a specific client they had to start
    AutoCAD using that profile or manually change the active profile. Now, by
    creating a dictionary in each drawing with settings for our company I can
    "assign" a client profile to each drawing and change the AutoCAD profile to
    match. This turns out being better then keeping client info in the drawing
    because I can update the info for every drawing from a central source on the
    network. Also, with AutoCAD's MDI interface a drafter can work with drawings
    from multiple clients without having multiple instances of AutoCAD open.
    If there is a better way of doing this, I'm open to suggestions. I
    probably will not be able to convince my company to change but anything that
    I can learn from is good.
     
    Jarod Arney, Aug 15, 2003
    #9
  10. Jarod Arney

    Kevin Terry Guest

    Robert,
    I believe he's looking for the document that was active before this one, but
    not until the event of closing this one is fired. The way I see it though,
    is this could be saved to the registry at exactly the moment you've captured
    here. Then when thisdrawing is closed, lastdrawing could be pulled from the
    registry for appropriate profile activation.

    Jarod, I guess if you're happy with your API call then I wouldn't change
    anything, but if you're still interested in a solution that is platform
    independent, then look into storing the previous document's name in the
    registry.

    Another idea I had on the subject is to store the profile name within the
    document itself - this to me might be the most reliable method of all - then
    as each document is activated the profile name is pulled (from dictionary,
    extended data, user variable, etc) and the profile activated.

    HTH,
    Kevin
     
    Kevin Terry, Aug 15, 2003
    #10
  11. You missed by point. Who cares what the prior document was? By sinking the
    Activate event, when you close the current document, the last one goes
    active, and the profile may be reapplied. I only used a MsgBox for
    simplicity, but the concept is proven.


    --
    R. Robert Bell, MCSE
    www.AcadX.com


    | Robert,
    | I believe he's looking for the document that was active before this one,
    but
    | not until the event of closing this one is fired. The way I see it though,
    | is this could be saved to the registry at exactly the moment you've
    captured
    | here. Then when thisdrawing is closed, lastdrawing could be pulled from
    the
    | registry for appropriate profile activation.
    |
    | Jarod, I guess if you're happy with your API call then I wouldn't change
    | anything, but if you're still interested in a solution that is platform
    | independent, then look into storing the previous document's name in the
    | registry.
    |
    | Another idea I had on the subject is to store the profile name within the
    | document itself - this to me might be the most reliable method of all -
    then
    | as each document is activated the profile name is pulled (from dictionary,
    | extended data, user variable, etc) and the profile activated.
    |
    | HTH,
    | Kevin
    |
    | | > Ok, I can understand that.
    | >
    | > Mind you, I haven't followed this thread carefully, but what is wrong
    with
    | > this approach (in VBA)?
    | >
    | >
    | > Private Sub AcadDocument_Activate()
    | > Dim DocName As String
    | > DocName = ThisDrawing.Name
    | > MsgBox DocName
    | > End Sub
    | >
    | >
    | > --
    | > R. Robert Bell, MCSE
    | > www.AcadX.com
    | >
    | >
    | > | > | I don't need to change the profile for every drawing but we do
    | > | consulting work for dozens of clients and rather then have everybody
    try
    | > and
    | > | remember the settings for each client, we have a massive set of LISP
    | > | routines that automate as much as possible. Each client has a profile
    | with
    | > | the appropriate paths to data and templates for that client. In the
    past
    | > | each user had 12-20 icons for AutoCAD, one for each client they work
    | with.
    | > | If they wanted to start a drawing for a specific client they had to
    | start
    | > | AutoCAD using that profile or manually change the active profile. Now,
    | by
    | > | creating a dictionary in each drawing with settings for our company I
    | can
    | > | "assign" a client profile to each drawing and change the AutoCAD
    profile
    | > to
    | > | match. This turns out being better then keeping client info in the
    | drawing
    | > | because I can update the info for every drawing from a central source
    on
    | > the
    | > | network. Also, with AutoCAD's MDI interface a drafter can work with
    | > drawings
    | > | from multiple clients without having multiple instances of AutoCAD
    open.
    | > | If there is a better way of doing this, I'm open to suggestions. I
    | > | probably will not be able to convince my company to change but
    anything
    | > that
    | > | I can learn from is good.
    | > |
     
    R. Robert Bell, Aug 15, 2003
    #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.