.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Blockview,NET

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
alex_b
2478 Views, 13 Replies

Blockview,NET

Hi All

 

I'm trying to use Fenton Webb's BlockView.Net control in my addin(in fact I use two of them).

It works fine but there are some issues (i.e. the addin crashes Autocad if I start the command/dialog, close it and start it again).

So, if anybody has any experience with this control, I have a couple of questions:

 

1. Did anybody encounter the problem mentioned above, its reason and maybe a solution?

 

2. There is the issue of the control crashing Visual Studio when trying to open the form in designer (see Kean Walmsley's blog http://through-the-interface.typepad.com/through_the_interface/2008/06/autocad-net-ver.html ).

In the same blog, Toby Tanzillo proposed a solution based on System.Process.GetCurrentProcess, but one cannot add or modify code in the designer. Has anyone succeeded using that?

 

3. For each file to view, the control creates a new Database which remains there for the life of the Autocad session, eating up memory etc. 

Can these Databases be deleted when the command exits? Could one use a single Database, erasing its contents each time before reading in anothe file?

 

Well, this was a mothfull.

Any tips will be much appreciated.

 

alex

 

13 REPLIES 13
Message 2 of 14
Balaji_Ram
in reply to: alex_b

Hi Alex,

 

I havent come across any specific crash similar to what you have mentioned. If you can please let me know the steps to reproduce the behavior, I can try it out and see if I can spot the problem.

 

What Tony Tanzillo has suggested is to find if the current process name is "acad.exe" and if it is not, omit all the code related to the GSPreview control. Another way for this is to check the "DesignMode" which will tell if you are in the designer. For example the following changes in "BlockViewDialog.cs" and "GsPreviewCtrl.cs" will let you open in the form in the designer. This worked for me, but I have seen guys reporting problems with the use of "DesignMode" in which case you will need to use the method that Tony has suggested. Here is one such link :

http://www.david-gouveia.com/problems-with-designmode-in-winforms/

 

public BlockViewDialog()
{
  InitializeComponent();

  if (!DesignMode)
  {// initialise the GsPreviewCtrl onl if not in design mode
	  InitDrawingControl(AcadApp.DocumentManager.MdiActiveDocument, AcadApp.DocumentManager.MdiActiveDocument.Database);
  }
}

public void refreshView()
    {
// refresh view only if not in design mode
		if (!DesignMode)
		{
			mpView.Invalidate();
			mpView.Update();
		}
    }

 protected override void OnSizeChanged(EventArgs e)
	{
// Ensure size change only if not in design mode
		if (!DesignMode)
		{
			base.OnSizeChanged(e);
			if (mpDevice != null)
			{
				mpDevice.OnSize(this.Size);
			}
		}
    }
  }

If you are unable to open inside form designer, then you may have to add a similar check in other places of your code that use the preview control.

 

Regarding the use of a single database, I think it is possible. I havent tried it though.

Following steps might be of help :

 

1) The "GsPreviewCtrl.cs" has a ClearAll method which can be called first and then the database disposed.

2) Create a new database and then call the "InitDrawingControl" and pass-in the newly created database.

 

Hope this helps.

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 3 of 14
alex_b
in reply to: Balaji_Ram

Hi Balaji.

 

Just when I was loosing all hope Smiley Happy

 

Thank you for the DesignMode solution. I will try it. I'll probably have to move all relevant code out of the form designer created file, but it is great anyway.

 

Regarding the use of a single db, I am trying - unsuccessfully - to create one side-database and use it repeatedly as a container of drawable objects (erasing the existing objects and 'pasting' new ones) and feed it to the GS control to view the objects.

 

Regarding the crashes I mentioned, I was wrongly blaming the Preview control. The real reason was related to a modeless dialog not being properly dismissed.

 

Thank you again

 

alex

Message 4 of 14
Balaji_Ram
in reply to: alex_b

Hi Alex,

 

 

Just a suggestion - Can you trying creating a new side database instead of trying to erase the objects that you have already have in the db ?

 

Disposing the old database and creating a new side base and then passing it to the GsPreviewCtrl's "Init" method seems like an easier option to me.

 

Please let me know if you continue to have problem in getting this to work.

I will try to get a sample code for it.

 

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 5 of 14
alex_b
in reply to: Balaji_Ram

Balaji

 

Thank you for replying.

There was a topic in the ObjectARX forum, raising some problems with repeatedly creating and destroyng databases, crashes, memory not being freed etc., so I thought it would be better to just use one temporary (not editable, not visible)database and dispose it at session end.

Maybe in .NET is safer. I will try it.

I will be grateful for an example.

 

Thanks

 

alex

Message 6 of 14
Balaji_Ram
in reply to: alex_b

Hi Alex,

 

Sorry for the delay.

 

Here is the change that I did to the "BlockViewDialog.cs" to ensure that there is only one database opened at a time.

As I had mentioned earlier, it is much simpler to dispose off the previous database and create a new one.

 

The change is in the "FileOpenMenuItem_Click" event handler :

 

    private void FileOpenMenuItem_Click(object sender, EventArgs e)
    {
      // pick the place where o output the image type
      Autodesk.AutoCAD.Windows.OpenFileDialog dialog = new Autodesk.AutoCAD.Windows.OpenFileDialog("Open DWG File", null, "dwg", "OpenDWGFileDialog", Autodesk.AutoCAD.Windows.OpenFileDialog.OpenFileDialogFlags.NoUrls);
      // if all is ok?
      if (DialogResult.OK == dialog.ShowDialog())
      {
        // clear the preview control
        mPreviewCtrl.mpView.EraseAll();

		/*
		#region Original code
			// create a new database
			dwgs.Add(new Database(false, true));
		#endregion
		*/

		#region Modified code
		// create a new database
		if (dwgs.Count > 0)
		{   
			// Dispose the earlier database.
			dwgs[0].Dispose();  

			// Create a new database for the existing one
			dwgs[0] = new Database(false, true);
		}
		else
			dwgs.Add(new Database(false, true));
		#endregion

		// now read it in
		dwgs[dwgs.Count - 1].ReadDwgFile(dialog.Filename, FileOpenMode.OpenForReadAndReadShare, true, "");
		// initialising the drawing control, pass the existing document still as the gs view still refers to it
		InitDrawingControl(AcadApp.DocumentManager.MdiActiveDocument, dwgs[dwgs.Count - 1]);
	  }
    }

 The change is very simple and will ensure that no other part of that sample requires any change.

 

Hope this helps.

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 7 of 14
alex_b
in reply to: Balaji_Ram

Balaji;

Many thanks

alex

Message 8 of 14
DiningPhilosopher
in reply to: alex_b

Designer failures often occur because there is code that uses AutoCAD types in the constructor (whether the code is actually called at design time or not, does not matter), or other methods that are called at design-time.

 

Visual Studio must just-in-time compile methods to run them in the designer, and it is the JIT'ing of those methods that is actually what can fail, rather than a call to an AutoCAD API. In other words, the failure can occur long before any AutoCAD APIs are called, and results from the fact that the JIT'ing of a method requires all assemblies containing any types used in the method to be loaded, which can trigger loading of the AutoCAD assemblies. That will happen regardless of whether the if( DesignMode ) test succeeds or not, because the code that runs only when the test is false is still in the method and is being jitted.

 

To solve the problem, put all code that calls AutoCAD APIs or uses AutoCAD types in a separate method, and  if the test indicates that you're not in the designer, then call that method. That works because the runtime will not jit a method unless it is actually called, so putting the code that uses AutoCAD types in a separate method that's never called at design time, ensures there's no JIT'ing of any code that calls AutoCAD APIs or uses AutoCAD types.

 

The same problem occurs with any other methods that are called at design-time. Including for example, the overide of the Form's OnSizeChanged() method. You must deal with it in the same way it is dealt with in the constuctor as shown below:

 

public class Form1
{
   // No calls to AutoCAD APIs or references to 
   // AutoCAD types should be in the constructor:
   
   public Form1()
   {
      InitializeComponent();
      
      if( ! base.DesignMode )
      {
         RuntimeOnlyConstruct();
      }
   }
   
   /// this method will never be jit'ed at design-time:
   
   void RuntimeOnlyConstruct()
   {
      // here it is safe to use AutoCAD types
      // and call AutoCAD APIs
   }
   
   // This method will also be JIT'ed at compile-time,
   // so you need to keep calls to AutoCAD code and
   // references to AutoCAD types out of this method,
   // by placing them into another method that's only
   // called when DesignMode is false:
   
   protected override void OnSizeChanged( EventArgs e ) 
   {
      if( ! base.DesignMode )
         RuntimeOnSizeChanged( e );
   }
   
   void RuntimeOnSizeChanged( EventArgs e )
   {
      // Ok to use AutoCAD APIs and types here
   }
}

 

Message 9 of 14
alex_b
in reply to: DiningPhilosopher

Hi DiningPhilosopher,

 

Your response was iluminating, I learned something I didn't know before and it also solves the problem.

It also connected with another problem I'm trying to solve:

Quoting from your response:

...the failure can occur long before any AutoCAD APIs are called, and results from the fact that the JIT'ing of a method requires all assemblies containing any types used in the method to be loaded

I'm trying to use an AutoCAD type in an out-of process program and the JIT compiler raises an exception when trying to load the AutoCAD assemblies, apparently because it can't load some unmanaged dependencies of those assemblies.

Do you know of a way to prevent it loading those dependencies, which are not needed anyway for the type I use.

The whole discussion is at: http://forums.autodesk.com/t5/NET/Is-dll-a-AutoCAD-plug-in/td-p/3662592

 

Thank you

 

alex

Message 10 of 14
DiningPhilosopher
in reply to: alex_b

Attached is a fixed and slightly-refactored version of the BlockView.NET source code. You can open the BlockViewDialog in the designer without any problems (although i only tested it on Visual Studio 2008 because I didn't want to convert it to a 2010 project). 

 

You'll also see some notes I added to the source regarding how to avoid design-time failures like the ones this sample was plagued with.

 

If you are trying to use types from AutoCAD's assemblies in any process other than AutoCAD, it will not work. Since you can't call any AutoCAD APIs, why do you think you need to use those assemblies from another process?

Message 11 of 14
alex_b
in reply to: DiningPhilosopher

Thank you Philosopher,

 

I'll have to study your code and implement the changes.

 

About the Acad types:

I need to extract from a Autocad plug-in the command names defined in it (if any). See topic  "Is dll a AutoCAD plug-in?"

http://forums.autodesk.com/t5/NET/Is-dll-a-AutoCAD-plug-in/td-p/3662592

Also my answer there.

Message 12 of 14

Thank you for the sample and the steps to ovecome the issue.



Balaji
Developer Technical Services
Autodesk Developer Network

Message 13 of 14

You're quite welcome.

 

This is actually the first time I looked at it in the 4 or so years since it was published, and would like to thank Fenton for his efforts.

Message 14 of 14
Automohan
in reply to: Balaji_Ram

Hi Balaji; Can you explain me how to use the approved final code I know Lisp how to create a lsp file & run with the AutoCAD Is this copy & paste to notepad & save with an extension .dll & run into autocad Thanks a lot Automohan
"Save Energy"
Did you find this reply helpful? If so please use the Accept as Solution
Tags (3)

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost