.NET

Reply
Contributor
jspark
Posts: 17
Registered: ‎09-30-2007
Message 1 of 15 (379 Views)

How to handle multiple open documents gracefully

379 Views, 14 Replies
10-02-2007 08:20 PM
I have a .NET app that is loaded with the NETLOAD command. I have a single command method that loads a custom control into a palette, and displays it. Whenever my code needs a reference to "ThisDrawing", "ThisAcad", "ThisDB" etc... it is gotten from a function that returns the needed reference. That said I have a few questions:

Why do my event handlers (the app in general) only become active after I type the command for my command method? Why are they not functional after the NETLOAD command? Is my application object (the class that contains my command method and my withevents member declarations) only instantiated when a command method is called?

Why does my app stop working when a new drawing is opened if the AcadApp, Document, Editor, Database etc.. references are gotten from a function? Example:

Dim WithEvents ThisDrawing as Document = GetDoc()

I think I am incorrectly assuming that each time my code uses ThisDrawing, it's the same as calling GetDoc(). Maybe I should explicitly set ThisDrawing = GetDoc() each time a new drawing becomes active?

Any other tips on gracefully handling the transition from active document to active document will be much appreciated as well.

TIA
Valued Contributor
pavlos.katsonis
Posts: 67
Registered: ‎09-12-2006
Message 2 of 15 (379 Views)

Re: How to handle multiple open documents gracefully

10-03-2007 01:57 AM in reply to: jspark
Concerning the event handlers, these must be initialized in the entrypoint of your app, not in the command method. The command method runs only when you call the corresponding command. The entrypoint runs when your app is loaded. That is the only thing that runs when an app is loaded.
*Tony Tanzillo
Message 3 of 15 (379 Views)

Re: How to handle multiple open documents gracefully

10-03-2007 06:27 AM in reply to: jspark
I suppose that if you've been using VBA and its
'ThisDrawing' object, you might become confused
by what you take for granted.

In VBA, 'ThisDrawing' looks like a variable, but is
in reality, more like a function that always returns
the Active document in the editor.

So in .NET, rather than assigning a variable to
the result of your GetDoc() function (which I
presume returns the active document), you must
call the GetDoc() function when want the Active
document (or to make it easier, you can add a
property to your class called 'ThisDrawing', and
in the 'getter' for it, just return the active doc).

When you're working with palettes, you should
never cache a document object in a variable. You
should always reference the MdiActiveDocument
property of the DocumentCollection directly, when
an operation begins, and then use that value only
for the duration of the operation. An 'operation'
means when the user clicks a button on your
user interface, and in response, you access the
active document to do something.

What is also not obvious about VBA's 'ThisDrawing',
is that when you handle an event of 'ThisDrawing',
the event is fired for every open document, not
just the one that was active when the event was
assigned.

In .NET, things are not as simple or automatic as
they are in VBA.

In .NET a Document object represents a single
Document open in the editor, that has its own
events. When you add a handler for a Document
event to a Document, the handler only receives
notification for the event in the Document that
you added the handler to. So, to handle the same
document event in every document, you must
add the handler for the event to every document
manually.

In order to do that, you handle the events of the
DocumentCollection (Application.DocumentManager),
like DocumentAdded, and DocumentToBeDestroyed,
and in the handlers for those events, you must add
or remove your document event handlers to the
newly added, or about-to-be closed document.

If your app is not loaded at startup, then you also
have to iterate over the collection of currently open
documents, and add document events handlers to
each of them.

There's sample code showing how to do this on my
website, but its in C#. There may be someone here
that has converted it to VB.NET.


--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2008
Supporting AutoCAD 2000 through 2008
http://www.acadxtabs.com

wrote in message news:5738738@discussion.autodesk.com...
I have a .NET app that is loaded with the NETLOAD command. I have a single command method that loads a custom control into a palette, and displays it. Whenever my code needs a reference to "ThisDrawing", "ThisAcad", "ThisDB" etc... it is gotten from a function that returns the needed reference. That said I have a few questions:

Why do my event handlers (the app in general) only become active after I type the command for my command method? Why are they not functional after the NETLOAD command? Is my application object (the class that contains my command method and my withevents member declarations) only instantiated when a command method is called?

Why does my app stop working when a new drawing is opened if the AcadApp, Document, Editor, Database etc.. references are gotten from a function? Example:

Dim WithEvents ThisDrawing as Document = GetDoc()

I think I am incorrectly assuming that each time my code uses ThisDrawing, it's the same as calling GetDoc(). Maybe I should explicitly set ThisDrawing = GetDoc() each time a new drawing becomes active?

Any other tips on gracefully handling the transition from active document to active document will be much appreciated as well.

TIA
Contributor
jspark
Posts: 17
Registered: ‎09-30-2007
Message 4 of 15 (379 Views)

Re: How to handle multiple open documents gracefully

10-03-2007 07:37 AM in reply to: jspark
Thank you both for your time. It has been very enlightening. A few more questions with some sample code this time…

In a nutshell, this is “MyApp” object:

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.Interop

Public Class MyApp

‘Private Members
Private WithEvents mThisAcad as AcadApplication = Ctype(ThisAcad.AcadApplication, AcadApplication)
Private WithEvents mThisDrawing as AcadDocument = Ctype(ThisDrawing.AcadDocument, AcadDocument)

‘Public Properties
Public Shared ReadOnly Property ThisAcad as Application
Get
Return Application.AcadApplication
End Get
End Property

Public Shared ReadOnly Property ThisDrawing as Document
Get
Return Application.DocumentManager.MdiActiveDocument
End Get
End Property

‘Methods
(Autodesk.AutoCAD.Runtime.CommandMethod("Start", "Start", _ Autodesk.AutoCAD.Runtime.CommandFlags.Modal)> _
Public Sub Start()
‘Create a new PaletteSet and a Palette. Add Palette to PaletteSet.
‘Set PaletteSet.Visible = True
EndSub

‘Events
Private Sub mThisDrawing_ObjectAdded(ByVal Obj As Object) Handles _ mThisDrawing.ObjectAdded
‘Do Stuff
End Sub

End Class

If I were to reset mThisDrawing = Ctype(ThisDrawing.AcadDocument, AcadDocument) each time a new Document becomes the active document, would my ObjectAdded event now only apply to the new active document?

IIRC, my ObjectAdded event will not fire until my command method has been executed from the command prompt. Why is that? It's almost as if "MyApp" is not created until the command method is executed.

I want “MyApp” object to be a single instance. Should I declare it as: Public Shared Class Myapp?

Overall, I want a single MyApp object and a single PaletteSet object to handle any active document the user throws at it. What should I be (not be) doing to make this so? (I should probably not be declaring a NEW PaletteSet in my command method.)
*Tony Tanzillo
Message 5 of 15 (379 Views)

Re: How to handle multiple open documents gracefully

10-03-2007 08:44 AM in reply to: jspark
In order for your event handler to be fired,
there needs to be an instance of the class
the handler is declared in.

Have you wondered how an instance of your
class is being created?

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2008
Supporting AutoCAD 2000 through 2008
http://www.acadxtabs.com

wrote in message news:5739156@discussion.autodesk.com...
Thank you both for your time. It has been very enlightening. A few more questions with some sample code this time…

In a nutshell, this is “MyApp” object:

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.Interop

Public Class MyApp

‘Private Members
Private WithEvents mThisAcad as AcadApplication = Ctype(ThisAcad.AcadApplication, AcadApplication)
Private WithEvents mThisDrawing as AcadDocument = Ctype(ThisDrawing.AcadDocument, AcadDocument)

‘Public Properties
Public Shared ReadOnly Property ThisAcad as Application
Get
Return Application.AcadApplication
End Get
End Property

Public Shared ReadOnly Property ThisDrawing as Document
Get
Return Application.DocumentManager.MdiActiveDocument
End Get
End Property

‘Methods
(Autodesk.AutoCAD.Runtime.CommandMethod("Start", "Start", _ Autodesk.AutoCAD.Runtime.CommandFlags.Modal)> _
Public Sub Start()
‘Create a new PaletteSet and a Palette. Add Palette to PaletteSet.
‘Set PaletteSet.Visible = True
EndSub

‘Events
Private Sub mThisDrawing_ObjectAdded(ByVal Obj As Object) Handles _ mThisDrawing.ObjectAdded
‘Do Stuff
End Sub

End Class

If I were to reset mThisDrawing = Ctype(ThisDrawing.AcadDocument, AcadDocument) each time a new Document becomes the active document, would my ObjectAdded event now only apply to the new active document?

IIRC, my ObjectAdded event will not fire until my command method has been executed from the command prompt. Why is that? It's almost as if "MyApp" is not created until the command method is executed.

I want “MyApp” object to be a single instance. Should I declare it as: Public Shared Class Myapp?

Overall, I want a single MyApp object and a single PaletteSet object to handle any active document the user throws at it. What should I be (not be) doing to make this so? (I should probably not be declaring a NEW PaletteSet in my command method.)
Contributor
jspark
Posts: 17
Registered: ‎09-30-2007
Message 6 of 15 (379 Views)

Re: How to handle multiple open documents gracefully

10-03-2007 08:59 AM in reply to: jspark
Yes, I have been wondering, and am unclear on when exactly "MyApp" is created. I would guess that NETLOAD does not create an instance of "MyApp". In order to execute the command method, an instance of "MyApp" is created... If thats the case then I would assume a second instance of "MyApp" is NOT created when the command is ran for a second time. So I dont need to worry about multiple instances of "MyApp" object being created. What about resetting mThisDrawing each time a new document becomes the active document? Will that make the same event handler work for the new active doc? (I guess I could do some tests to figure that out, but it sounds logical...) Am I on the right track here?
Distinguished Contributor
caddie75
Posts: 135
Registered: ‎07-07-2006
Message 7 of 15 (379 Views)

Re: How to handle multiple open documents gracefully

10-03-2007 09:37 AM in reply to: jspark
Hi,

In the beginning I also struggled how to do it..look into the following:

1. Best is to let the Assembly (dll) autoload into AutoCAD, this requires a registry key.

2. Use a "Autodesk.AutoCAD.Runtime.IExtensionApplication" in you're app. As soon as the app gets loaded (NETLOAD or AutoLoad) then this class gets Initialized.

On the "Initialize" you can create a Shared instance of the custom class that handles the documents. (including events)

3. In you're Custom Class (let's name it: "acEvents_Manager" or so)
In this class there have to be the Application Reference for handling events raised by the Application (ACAD), this depends on what events you will need.
You also need a DocumentCollection Reference(instance)
This one DocumentBecameCurrent, DocumentCreated etc....

4. Form the events of the DocumentCollection you'll be able to react, depending on you're goals.

5. You can then event "listen" to database events. If a object changes, you can eval it and possibly update information displayed on a Palette.

Samples etc, of these can be found in this NG.
Search for the following:
"Autoload dll"
"IExtensionApplication"
"DocumentCollection"

ps. You should also download the "ObjectARX SDK (2008)"
There samples and documentation regarding .NET in it.
It helped me a lot.
(i You need it I can upload a sample in VB.net)

I use the following config:
AutoCAD 2008, VS2005, WinXP sp2

Good luck,
A. Caddie
Contributor
jspark
Posts: 17
Registered: ‎09-30-2007
Message 8 of 15 (379 Views)

Re: How to handle multiple open documents gracefully

10-03-2007 09:59 AM in reply to: jspark
That is very helpful, thank you. I will search the NG using your suggestions. I did assume I would need to handle the DocumentCollection events in order to keep "mThisDrawing" up to date with the active document. Will my application class need to "Inherit" IExtensionApplication? I am not sure what you mean by "Use "Autodesk.AutoCAD.Runtime.IExtensionApplication" in you're app". I will look into the IExtensionAppliciation. You also suggested that I create a new class for handling events. Is it "ok" to handel events within my main application class?
*CADJunkie
Message 9 of 15 (379 Views)

Re: How to handle multiple open documents gracefully

10-03-2007 10:04 AM in reply to: jspark
What a nice professional response. You must have had some good action last
night :-)

Davis
"Tony Tanzillo" wrote in message
news:5739091@discussion.autodesk.com...
I suppose that if you've been using VBA and its
'ThisDrawing' object, you might become confused
by what you take for granted.

In VBA, 'ThisDrawing' looks like a variable, but is
in reality, more like a function that always returns
the Active document in the editor.

So in .NET, rather than assigning a variable to
the result of your GetDoc() function (which I
presume returns the active document), you must
call the GetDoc() function when want the Active
document (or to make it easier, you can add a
property to your class called 'ThisDrawing', and
in the 'getter' for it, just return the active doc).

When you're working with palettes, you should
never cache a document object in a variable. You
should always reference the MdiActiveDocument
property of the DocumentCollection directly, when
an operation begins, and then use that value only
for the duration of the operation. An 'operation'
means when the user clicks a button on your
user interface, and in response, you access the
active document to do something.

What is also not obvious about VBA's 'ThisDrawing',
is that when you handle an event of 'ThisDrawing',
the event is fired for every open document, not
just the one that was active when the event was
assigned.

In .NET, things are not as simple or automatic as
they are in VBA.

In .NET a Document object represents a single
Document open in the editor, that has its own
events. When you add a handler for a Document
event to a Document, the handler only receives
notification for the event in the Document that
you added the handler to. So, to handle the same
document event in every document, you must
add the handler for the event to every document
manually.

In order to do that, you handle the events of the
DocumentCollection (Application.DocumentManager),
like DocumentAdded, and DocumentToBeDestroyed,
and in the handlers for those events, you must add
or remove your document event handlers to the
newly added, or about-to-be closed document.

If your app is not loaded at startup, then you also
have to iterate over the collection of currently open
documents, and add document events handlers to
each of them.

There's sample code showing how to do this on my
website, but its in C#. There may be someone here
that has converted it to VB.NET.


--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2008
Supporting AutoCAD 2000 through 2008
http://www.acadxtabs.com

wrote in message news:5738738@discussion.autodesk.com...
I have a .NET app that is loaded with the NETLOAD command. I have a single
command method that loads a custom control into a palette, and displays it.
Whenever my code needs a reference to "ThisDrawing", "ThisAcad", "ThisDB"
etc... it is gotten from a function that returns the needed reference. That
said I have a few questions:

Why do my event handlers (the app in general) only become active after I
type the command for my command method? Why are they not functional after
the NETLOAD command? Is my application object (the class that contains my
command method and my withevents member declarations) only instantiated when
a command method is called?

Why does my app stop working when a new drawing is opened if the AcadApp,
Document, Editor, Database etc.. references are gotten from a function?
Example:

Dim WithEvents ThisDrawing as Document = GetDoc()

I think I am incorrectly assuming that each time my code uses ThisDrawing,
it's the same as calling GetDoc(). Maybe I should explicitly set ThisDrawing
= GetDoc() each time a new drawing becomes active?

Any other tips on gracefully handling the transition from active document to
active document will be much appreciated as well.

TIA
Valued Contributor
pavlos.katsonis
Posts: 67
Registered: ‎09-12-2006
Message 10 of 15 (379 Views)

Re: How to handle multiple open documents gracefully

10-03-2007 10:49 AM in reply to: jspark
It would be better to download the SDK and read everything concerning the entrypoint of an application. The method is simple enough and the examples are good.
The entrypoint is just a method of one of your classes that is executed during load time. You just have to declare it in a certain way. It's simple enough after you see the examples.
After you implement it, you can decide whether you want to store your variables in static variables and create a new instance of your class for every drawing or whatever.

You are not logged in.

Log into access your profile, ask and answer questions, share ideas and more. Haven't signed up yet? Register

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.

Need installation help?

Start with some of our most frequented solutions to get help installing your software.

Ask the Community