TheSwamp
Code Red => VB(A) => Topic started by: ML on July 11, 2007, 09:43:30 AM
-
I have been having this problem for months but have not followed through with a post to get it resolved:
I have an acad.rx file; in there I tpyed acvba.arx, it looks like it is initializing VBA on startup however I can not get any app events to work
I have the class module created called Class1
Public WithEvents ACADApp As AcadApplication ' Use with Application Event Examples
Sub Acad_Application_Events()
' This intializes the public variable (ACADApp) which is used
' to intercept AcadApplication Events.
'
' The VBA WithEvents statement makes it possible to intercept a generic
' object with the events associated with that object.
'
' Before you are able to trigger any of the AcadApplication events,
' you first need to run this procedure.
' You could get the application from the ThisDocument object, but that
' would require having a drawing open, so in this case it is grabbed from the system.
Set ACADApp = GetObject(, "AutoCAD.Application.16.2")
End Sub
And a module to call it up
Sub ExposeAppEvents()
Dim AppEvents As Class1
Set AppEvents = New Class1
End Sub
Still nothing
Any suggestions?
Also, does anyone have a fairly simple App Event that I can use a test?
Thanks
Mark
-
1) Put this at the top of the thisdrawing module (thisdrwawing is a class module)
Private WithEvents AutoCAD As AcadApplication
2) Put this in the thisdrawing module as wellPublic Sub Acadstartup()
Set AutoCAD = Application
AutoCAD.WindowState = acMax
ThisDrawing.WindowState = acMax
End Sub
3)In the thisdrawing module of your acad.dvb
Sub ACADStartup()
Call AcadApplication.RunMacro("F:\Project startup2006.dvb!App_StartMacro")
End Sub
Place your path to the dvb you are loading.
4)At the top of your vbaide window there are 2 control boxes, the one on the left is called the object box.
It will probably say (General), if you click the arrow and select "AutoCAD", the pull down box on the right ("Procedure") will have a listing of all the available application level apps.
Click on BeginOpen, and a sub of that name will appear, write MsgBox("opening") in there.
-
Bry
I failed to mention that all of the above is in my acad.dvb file
Mark
-
I could be wrong but it looks like you are grabbing the events from drawing level instead of from The system?
Mark
-
Which would require a drawing to be open :-(
-
Hi Mark,
Attached is my acad.dvb that uses events. See if it helps what you want to do. This has code in it for LandDesktop specific items, but that part shouldn't run if LDT is not running.
Jeff
-
Cool Jeff
How are you calling it up?
THanks
Mark
-
Jeff
That is good stuff
The cool thing is that I use Land Desktop also but I am still a bit too new at it to really appreciate what you have done. It is certainly worth hanging onto.
In my acad.dvb file
I did a simple event:
Private Sub ACADApp_BeginSave(ByVal Filename As String)
Dim Filename As String
Filename = Test.dwg
MsgBox "Hello"
End Sub
When I press the save button, should I not at least get a simple message box?
Thank you
Mark
-
Hi Mark,
Not sure what's up, but the docs say the the BeginSave & EndSave events use the AcadApp, but the Examples for both use the AcadDocument....this works:
Private Sub ACADDocument_BeginSave(ByVal Filename As String)
'Filename = Test.dwg ''this will error since it's not a string
MsgBox "Hello"
End Sub
-
Well that is easily solved by
Dim Filenname as String
But the problem I am having is not really using document level events, it is using App level events :-(
-
This came right from the help screen:
Private Sub AcadDocument_BeginPlot(ByVal DrawingName As String)
' This example intercepts a drawing BeginPlot event.
'
' This event is triggered when a drawing receives a plot request.
'
' To trigger this example event: Plot an open drawing
' Use the "DrawingName" variable to determine which drawing is about to plot
MsgBox "A drawing has just received a request to plot for: " & DrawingName
End Sub
I literally copied and pasted the code in the event and still nothing :-(
WHY?????????
-
Well that is easily solved by
Dim Filenname as String
Actually, FileName is already defined as a string in the arguments section...... the way you put in Test.dwg was not a string. Also, since the filename is supplied by Autocad, I'm not sure you want to be changing it in this event (I haven't tested that, just a thought).
Does anything in your acad.dvb get run? What about if you replace yours with mine (rename yours, place mine in the support path & restart acad)?
The Plot code works for me......when you start Acad, once it's fully loaded type VBAIDE. Is the acad.dvb there in the editor? If not, it's not loading...... if it is, could you post or email the dvb to me? miff AT sonic DOT net
-
Jeff
Mine is loading fine and all looks well but nothing is triggering? :-(
If you can take a look, I would really appreciate it
DAM, hell do I attach file?
Thanks
Mark
-
Ok, it is attached to the last post
Thanks Jeff!
-
One last question, Mark. What Acad version are you using?
-
R 16.2
Land Desktop 2006
Thanks Jeff!
-
OK, the attached acad.dvb is working. While doing this I recalled having all kinds of problems using this Class module method which is why mine all resides in ThisDrawing module. I'm still not sure why the Help says to do it one way that you, nor I, could make work.
-
I could be wrong but it looks like you are grabbing the events from drawing level instead of from The system?
As far as I know vba needs a drawing open to access the application, Jeff any thoughts?
-
I don't know for sure, but that's how I've always thought it works. I was confused about that as well.
-
Sounds right to me. VBA does appear to disappear without a drawing opne. I have always use the right menu to do this, but I like your way better Bryco. Thanks for sharing that.
-
A drawing does not need to be open to use the VBA environment, however, a drawing does need to be open to enable the environment.
Consider this:
Load the previously attached acad.dvb and create an event for opening a drawing and/or creating a new drawing.
Save the dvb
Close AutoCAD
Re-open AutoCAD, note that no events fire as the first drawing is already open by the time the VBA environment initializes.
Close that drawing so there are no drawings currently open, presumably the VBA environment is now inactive.
Create a new drawing, note how the events fire just prior to refreshing the window.
Another exercise is to create a timer module that sets a system timer. Set the timer to call a macro to pop up a window every minute. Run the timer macro and close all open drawings. Presumably the timer would not be able to find the macro to call if the VBA environment is inactive while there are no drawings open, but it does fire, and it does find the macro.
-
Keith,
Please, as per previous disussions, isn't it correct that VBA needs to be initialized on startup in order to use APP Level Events?
May be you know why The Class Module isn't working?
I know it use to work for me in previous positions.
Thanks
Mark
-
Jeff
I haven't tried it yet but thank you, I will try it now.
However, I suspect that if we are using The document (thisdrawing) method, we are still not going to be able to initiate APP level events, only drawing level.
Please correct me if I am wrong :-o
Thank you again
Mark
-
To continue that discussion, VBA sure can be initialized without a drawing open. It can be initialized on startup.
Please look at my very first post at the top.
Mark
-
Ml use the thisdrawing module, it does what you ask.
Keith, once you have set the application (And this happens when a drawing is opening as in opening autocad) you can close all drawings and the vba is still running, like you said. However if the link is broken, you can't reset the application while there is no drawing open, it errors
-
Mark, In the revised acad.dvb that I posted I don't use any reference to ThisDrawing. Out of curiosity, what are you trying to catch/control that you wouldn't have a drawing open?
-
Correct, you cannot restart the application link from within VBA by creating a new link, but that link will always be active until the application is closed or the variable holding the application is destroyed
-
Yes Jeff, I see that now, thank you
However, niether of these test events are working ????
Private Sub ACADApp_BeginPlot(ByVal DrawingName As String)
MsgBox "A drawing has just received a request to plot for: " & DrawingName
End Sub
[code]
Private Sub ACADApp_EndSave(ByVal FileName As String)
MsgBox ThisDrawing.FullName & "Has Been Saved"
End Sub
[/code]
Bryon-Jeff
How do you guys initialize VBA on startup?
Mark
-
Jeff, All of sudden it is working just fine!
That's great, thank you very much
Mark
-
OK, this is a very naive question:
Jeff:
In the exposeappevents module
You have the code
Dim AppEvents As New EventsClass
-----------------------------------------
Sub acadstartup()
Set AppEvents.ACADApp = Application
End Sub
I understand that you made a new class module but what is actually triggering it (acadstartup)?
THanks
Mark
-
OK, this is a very naive question:
Jeff:
In the exposeappevents module
You have the code
Dim AppEvents As New EventsClass
-----------------------------------------
Sub acadstartup()
Set AppEvents.ACADApp = Application
End Sub
I understand that you made a new class module but what is actually triggering it (acadstartup)?
THanks
Mark
It doesn't need to be triggered, outside of AutoCAD starting up.
-
Sorry, I meant to say a new class, not class module.
So you are saying that when ACAD starts, it calls the macro?
Mark
-
Which then triggers The ACADapp?
Mark
-
yep
-
To expand on Keith's excellent reply :-)
Just as Acad will autoload any acad.lsp, acaddoc.lsp, acad.rx acad.dvb, S::STARTUP (in lisp), and any associated MNL files, it will run an AcadStartup Sub in the now loaded Acad.dvb
-
Yeah Keith's explanation was pretty profound
Yep
LOL, I am just kidding Keith. Keith has been a GREAT help to me over the years, I owe him a great bit of gratitude.
Jeff, that was an excellent explanation, thank you
That really clarified a lot for me :-)
I appreciate all your help!
Mark
-
Jeff,
You are a Land Desktop user.
With Land Desktop is it still necessary to use the acad.rx file to load the acvba.arx file in order to initialize VBA on startup?
Thank you
Mark
-
Yep :-)
-
Cool!
It looks like we've clarified this "event" LOL :-D
Thank you
-
Hey Jeff:
Pretty cool,
Branching out on The plot Event that you included
I added some VBScripting Language into The Plot Event
Mark
Private Sub ACADApp_BeginPlot(ByVal DrawingName As String)
Dim WshNetwork
Dim username
Set WshNetwork = CreateObject("WScript.Network")
username = WshNetwork.username
MsgBox "Drawing " & DrawingName & "has just received a request to plot for: " & username
End Sub
-
Jeff,
Also I noticed that sometimes when I make changes to the events, I have to re run my ExposeAppEvents (acadstartup) module
Dim AppEvents As New EventsClass
Sub acadstartup()
Set AppEvents.ACADApp = Application
End Sub
I don't think that should be necessary, do you?
Thanks
Mark
-
No, that seems odd. I'm pretty sure that I can make changes and they are immediately used.
-
Please
I would appreciate that :-)
Mark
-
Oh I'm sorry
I tohught you had a fix
The same situation is still happening???
You would think the event itself would trigger the acadstartup?
Yes, I can have every event handler run acadstartup but this should not be neccessary :?
So, you have not encountered this problem?
Mark
-
I reset with the AcadDocument_EndCommand "OPEN" and "NEW", notice this is a document level command.
There is also an application level Open and New, but these may not fire.
When you open a new drawing there is a point where thisdrawing changes ownership, this is where the application setting loses it's scope.
-
Hummmm
Interesting point: :?
If I am correct, you are saying if the event can be handled at document level, then that should be the first line of attack as the documnet level events take precedence over application level. Is this what you are saying Bry?
If that is the case, then i should do some experimenting
For instance, we know the appactivate is definetely an app level event so there "should" be no conflict but I can see the save and plot events occuring in both drawing and app level.
Thank you
Mark
-
That is in The Thisdrawing (document object) of the acad.dvb file correct?
I think I just stated the obvious. ;-)
-
Re-open AutoCAD, note that no events fire as the first drawing is already open by the time the VBA environment initializes
This is interesting Keith and sounds pretty good.
However I find it difficult to get any application events to work on a newly opened autocad session. I find the thisdrawing is fine but the app link is broken.
After new or open resetting the link, all is fine. I can imagine the app link is set then the new drawing opens up and breaks it.
Ml, yes use the lower level when you can.
-
Thanks Bry
Now let me ask (Bry) you this:
How are you initializing VBA on startup?
I use the acad.rx file to call the acadvba.arx, which then initializes VBA on startup.
If you don't have an acad.rx file, just create it with a text file, type in the text file acadvba.arx, save as acad.rx and you should be good to go.
Now, I had this discussion with Keith in the past but being the absent minded person that I can be at times, I forget whether or not The acad.rx and the acadvba.arx files need to be in the same directory.
Mark
-
He is a pretty good post page that I just got done reading. Interesting, I think it was Bryco that suggested putting the acadstartup routine in The Thisdrawing Object? That is what this guy is suggesting but I very much like the way Jeff set me up. This guy gives a very good explanation of using the acad.rx, acad.dvb and acad (ac) vba.arx files in conjunction to achieve the same goal we are discussing here. :lol:
Mark
http://www.cadalyst.com/cadalyst/article/articleDetail.jsp?id=122827
(http://www.cadalyst.com/cadalyst/article/articleDetail.jsp?id=122827)
-
Another question; if you guys would be so kind?
This was a little joke I played on a fellow co-worked that kind of ticked me off at my last position.
However, it is rather harmless :-) LOL
Private Sub AcadDocument_BeginCommand(ByVal CommandName As String)
If UCase(CommandName) = "LINE" Then
MsgBox " We apologize for the inconvenience but AutoCAD has ran out of lines", vbCritical
End If
The question I have asked in the past but never got a good answer on is:
After he gets the message "We apologize for the inconvenience but AutoCAD has ran out of lines"
and he clicks OK, how do I iniate an Esc Esc?
Anyone like to try?
Thanks
Mark
-
Use boolean with a counter...
if linejoke = 0 then
..blah
set linejoke = 1
end if
... of sorts
-
Hey deegeecees
I'm not sure how I would integrate that in with my code? :-(
-
Like so....
MsgBox " We apologize for the inconvenience but AutoCAD has ran out of lines", vbCritical
SendKeys "^C"
-
Jeff
The result I am getting with that is :
Command: _copybase Specify base point:
??????
-
Keep in mind I'm a bit rusty in this dept...
This way will should (untested) work once per session:
Private Sub AcadDocument_BeginCommand(ByVal CommandName As String) as
Dim linjok as int
if linjok = 0 then
If UCase(CommandName) = "LINE" Then
MsgBox " We apologize for the inconvenience but AutoCAD has ran out of lines", vbCritical
set linjok = 1
end if
End If
end sub
I think Jeff is heading down the right path...
-
Hey Deegeecees
I'm afraid that did not work, I tired a few things with it :-(
-
Hey Deegeecees
I'm afraid that did not work, I tired a few things with it :-(
Well, someone with a bit more experience will prolly come along. Keep on truckin!
-
Ok, it works now.
Private Sub AcadDocument_BeginCommand(ByVal CommandName As String)
Dim linjok As Integer
If linjok = 0 Then
If UCase(CommandName) = "LINE" Then
MsgBox " We apologize for the inconvenience but AutoCAD has ran out of lines", vbCritical
End If
End If
linjok = 1
End Sub
-
No it doesn't LOL but Thank you
It still keeps me in the line command
WAIT! I got it!
Going back to Jeff's send keys idea.
I may just need to find the ascii equivalent to ESC (i.e chr94)
Hummmmmmm :-o
-
Or by employing some lisp (which I rather not) we could undefine the line command
Then immediately afterwards, redefine it.
Mark
-
Ok, if you just want to end the command try this:
Private Sub AcadDocument_BeginCommand(ByVal CommandName As String)
Dim linjok As Integer
If linjok = 0 Then
If UCase(CommandName) = "LINE" Then
MsgBox " We apologize for the inconvenience but AutoCAD has run out of lines", vbCritical
End If
End If
linjok = 1
[color=red]ThisDrawing.SendCommand vbCr & vbCr[/color]
End Sub
-
That is what this guy is suggesting but I very much like the way Jeff set me up. This guy gives a very good explanation of using the acad.rx, acad.dvb and acad (ac) vba.arx files in conjunction to achieve the same goal we are discussing here.
Mark, what that guy (Mike Tuersley) is doing is the same thing I do...except he placed the AcadStartup into ThisDrawing instead of it's own Module. I'm pretty sure that I got mine setup based on one of Mike's posts in the Adesk forums. :-)
Testing somemore....I tried changing the acad.dvb I posted for Mark to get the Application from Windows by modifying JUST this line:
Set AppEvents.ACADApp = Application
to this:
Set AppEvents.ACADApp = GetObject(, "AutoCAD.Application")
If that line is executed AFTER a drawing is open, all is well. However, since it is in the AcadStartup Sub, Acad attempts to load it before the Drawing is open and, evidently, before the AcadApplication is registered as being an Object with windows because it errors out with "Unable to Get the Object".
So it appears that App level events don't get autostarted in the first drawing...which I think is what Keith was saying.
Oh, and this worked for me for the Line command....
Private Sub AcadDocument_BeginCommand(ByVal CommandName As String)
If CommandName = "LINE"
MsgBox "No lines for you!", vbCritical
SendKeys "{ESC}"
End If
End Sub
-
Oh, and this worked for me for the Line command....
Private Sub AcadDocument_BeginCommand(ByVal CommandName As String)
If CommandName = "LINE"
MsgBox "No lines for you[color=red], ONE YEAR![/color]", vbCritical
SendKeys "{ESC}"
End If
End Sub
:lmao:
-
Yes sir Jeff!
That is the ticket!
Thank you so much
"{ESC}" worked!
Also I do (for the most part) understand your (analogy).
Instead of saying GetObject, where are setting acadapp object to equal The acad app. + :?
Thank you very much
Mark
-
Private Sub AcadDocument_BeginCommand(ByVal CommandName As String)
Select Case UCase(CommandName)
Case Is = "LINE"
MsgBox " We apologize for the inconvenience but AutoCAD has ran out of lines", vbCritical
SendKeys "{ESC}"
End Select
End Sub
The above code is beautiful, freaking classic LOL
It makes programming all worth while :-)
Hey, we can some fun once in a while, can't we? :-D