TheSwamp

Code Red => .NET => Topic started by: TR on July 27, 2005, 11:42:57 AM

Title: Looking for some example code to insert block. (C#)
Post by: TR on July 27, 2005, 11:42:57 AM
If anyone has any example code for inserting a block from a file can you post it here? I am squirming my way through now but something to go by would be greatly appreciated.
Title: Looking for some example code to insert block. (C#)
Post by: Kerry on July 27, 2005, 05:28:51 PM
Hi Tim,

... a bit more than you wanted ...

This is not original .. I don't know the author


Code: [Select]

using System;
using System.Collections;
using System.Windows.Forms;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Interop.Common;
using Autodesk.AutoCAD.Interop;

namespace ClassLibrary1
{
public class DatabaseExample
{
//Insert an external file as a block definition via .NET
[CommandMethod("CopyBlock")]
public void InsertAsBlock()
{
            string sourceFileName = @"C:\BlockToCopy.dwg";

try
{
using(Database sourceDatabase = GetDatabaseFromFile(sourceFileName))
{
//Insert the blocks database into a new Block Table Record
                    HostApplicationServices.WorkingDatabase.Insert("BlockToCopy", sourceDatabase, false);
}
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
string errorMessage = GetMessageFromErrorStatus(e.ErrorStatus);
MessageBox.Show(errorMessage, "Copy Block Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}


//Copy a block definition from an external file via ActiveX
[CommandMethod("CopyBlockX")]
public void CopyBlockActiveX ()
{
string sourceFileName = @"C:\OftenUsedBlocks.dwg";

string blockName = "ActiveX";

IAxDbDocument dbxDoc = null;

AcadDatabase activeDocument = (AcadDatabase)HostApplicationServices.WorkingDatabase.AcadDatabase;

try
{
//Open the drawing file
dbxDoc = new AxDbDocumentClass();
dbxDoc.Open(sourceFileName, null);

//Place the selected block definition in an array,
//to prepare it for copying
AcadBlock blockDef = dbxDoc.Blocks.Item(blockName);
AcadBlock[] objectsToCopy = {blockDef};

object idPair = null;

//Copy the block definition into the active drawing
dbxDoc.CopyObjects(objectsToCopy, activeDocument.Blocks, ref idPair);
}
catch{}
finally
{
dbxDoc = null;
}
}


#region Private Methods

private Database GetDatabaseFromFile(string fileName)
{
//create a blank database
Database databaseFromFile = new Database(false, true);

//read the database from file into the blank database
databaseFromFile.ReadDwgFile(fileName, System.IO.FileShare.None, false, null);

return databaseFromFile;
}

private string GetMessageFromErrorStatus(int errorCode)
{
return Enum.GetName(typeof(ErrorStatus), errorCode);
}

#endregion
}
}
Title: Looking for some example code to insert block. (C#)
Post by: TR on August 06, 2005, 05:57:42 PM
How did I miss your reply?!?!?

Thanks Kerry, I'll give it a shot when I get to work on Monday.
Title: Looking for some example code to insert block. (C#)
Post by: TR on August 11, 2005, 03:25:08 PM
I am having trouble with the code you posted. It should be easier to understand if I just post a screenshot. Can someone tell me what I'm doing wrong with the errors on 208 and 215? Also regarding the error on line 210, is this something added in 2006 maybe? I can't seem to figure it out with 2005.

Thanks.

http://www.theswamp.org/screens/tjr/CSharpError.png
Title: Looking for some example code to insert block. (C#)
Post by: Glenn R on August 12, 2005, 10:21:56 AM
Compare what Kerry posted to what you have in that screenshot...it is NOT the same on some fundamental levels.
Title: Looking for some example code to insert block. (C#)
Post by: TR on August 12, 2005, 10:47:32 AM
Found it. I had added "static" to my method. Thanks.

Now the only error I have is error CS0246: The type or namespace name 'HostApplicationServicesWorkingDatabase' could not be found (are you missing a using directive or an assembly reference?) Can someone give me a tip on what I'm doing wrong with this? All my using directives contain what's in Kerry's code and I have acmgd.dll and acdbmgd.dll referenced. Is this something that's not available in 2005's .NET API?
Title: Looking for some example code to insert block. (C#)
Post by: JCappiello on August 12, 2005, 01:00:45 PM
I think there is a typing error:

It should read  "HostApplicationServices.WorkingDatabase"

The period is missing.

Hope this helps.
Title: Looking for some example code to insert block. (C#)
Post by: Anonymous on August 12, 2005, 01:23:23 PM
That was it. Thank you sir.
Title: Re: Looking for some example code to insert block. (C#)
Post by: HD on October 28, 2005, 08:05:40 AM
Hello,


I was wondering if anyone had problems compiling the program that Kerry posted. I receive the following error messages during compilation:

* The best overloaded method match for 'ClassLibrary1.DatabaseExample.GetMessageFromErrorStatus(int)' has some invalid arguments

* Argument '1': cannot convert from 'Autodesk.AutoCAD.Runtime.ErrorStatus' to 'int'

Both of these messages are coming from the following line: The above messages are coming from the following line: string errorMessage = GetMessageFromErrorStatus(e.ErrorStatus);


Thanks!
Title: Re: Looking for some example code to insert block. (C#)
Post by: Kerry on October 28, 2005, 02:55:34 PM
Hi HD,

I'll have another look when I get into work mode.

Just a couple of things :-

Due to the evolving nature of the application of .NET technology it's usually handy to provide some additional information :

Which IDE are you using  ?
Which IDE's  do you have installed ?

Which .NET version are you using ?
Which .NET versions do you have installed ?

Which ACAD version are you using ?
Which ACAD versions do you have installed ?

Though this is a compile issue, the last 2 are required because of the library references

In an ideal world these perhaps wouldn't be considerations, but .....

Regards
Kerry

Title: Re: Looking for some example code to insert block. (C#)
Post by: Kerry on October 28, 2005, 08:10:28 PM
HD,
Using MSC#2003 with AC2006

with this Change to the posted Code ;
Code: [Select]
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
string errorMessage = GetMessageFromErrorStatus(Convert.ToInt32(e.ErrorStatus));
MessageBox.Show(errorMessage,
"Copy Block Error - Big dummy Spit ",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}

The Assembly compiles and runs.
As near as I can determine the enumerated value returned from (e.ErrorStatus) produced by AutoCad needs to be converted to an int ie: Int32


Title: Re: Looking for some example code to insert block. (C#)
Post by: Kerry on October 28, 2005, 09:04:02 PM
.. This works as well, and probably easier :)

Code: [Select]
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
string errorMessage = (e.ErrorStatus).ToString();

MessageBox.Show(errorMessage,
"Copy Block Error - Big dummy Spit ",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
Title: Re: Looking for some example code to insert block. (C#)
Post by: Kerry on October 28, 2005, 09:35:50 PM
.. or if you're into frugality
Code: [Select]
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
MessageBox.Show((e.ErrorStatus).ToString(),
"Copy Block Error - Big dummy Spit ",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
Title: Re: Looking for some example code to insert block. (C#)
Post by: Kerry on October 30, 2005, 04:29:08 PM
Afterthought

The last 2 solutions will allow you to remove the
private string GetMessageFromErrorStatus(int errorCode) { ... } Method





[edit : DUH ! need coffee]
Title: Re: Looking for some example code to insert block. (C#)
Post by: HD on October 31, 2005, 06:26:08 AM
Kerry,


Thanks to your post, my assembly compiles and runs.


Sorry for not posting additional information. For what it's worth, here's my environment:

Visual Studio .NET 2003
AutoCAD 2006


Thanks Again!

Title: Re: Looking for some example code to insert block. (C#)
Post by: Bobby C. Jones on November 02, 2005, 01:28:37 PM

This is not original .. I don't know the author


I recognize that code.  I wouldn't trust the author as far as you could throw him  :-P
Title: Re: Looking for some example code to insert block. (C#)
Post by: TR on November 02, 2005, 01:38:50 PM
Thanks for (indirectly) supplying the code Bobby.
Title: Re: Looking for some example code to insert block. (C#)
Post by: MP on November 02, 2005, 01:39:25 PM
Why it's Mr. Jones.

Howdy Bobby.

- Michael.
Title: Re: Looking for some example code to insert block. (C#)
Post by: Kerry on November 02, 2005, 07:03:32 PM

This is not original .. I don't know the author


I recognize that code.  I wouldn't trust the author as far as you could throw him  :-P

hehehehehe ..
now I know :) .. good to hear <the first part anyway>


Title: Re: Looking for some example code to insert block. (C#)
Post by: Chuck Gabriel on November 02, 2005, 07:35:30 PM
Hola Bobby.  Long time no see.
Title: Re: Looking for some example code to insert block. (C#)
Post by: Bobby C. Jones on November 03, 2005, 10:36:20 AM
Hola Bobby.  Long time no see.

Hey Chuck!  They let anybody into this place don't they CG, LE, MP...  :-P

It's good to here from you.
Title: Re: Looking for some example code to insert block. (C#)
Post by: David Hall on September 16, 2009, 11:07:01 AM
Just out of curiosity, is the above code still good in 2010?  I am having a very hard time getting it to read the external file.
Title: Re: Looking for some example code to insert block. (C#)
Post by: David Hall on September 16, 2009, 03:07:09 PM
got it working (Thanks Tim).  Moving ahead...
Title: Re: Looking for some example code to insert block. (C#)
Post by: David Hall on September 21, 2009, 05:08:14 PM
ok, I am having a problem, which is probably something simple I am overlooking.
Code: [Select]
[CommandMethod("TEPWireLabel")]
        public static void WireLabel()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            PromptKeywordOptions pko = new PromptKeywordOptions("");
            pko.Message = "\nJustification and Quanity";
            pko.Keywords.Add("L1");
            pko.Keywords.Add("L2");
            pko.Keywords.Add("L3");
            pko.Keywords.Add("L4");
            pko.Keywords.Add("L5");
            pko.Keywords.Add("L6");
            pko.Keywords.Add("R1");
            pko.Keywords.Add("R2");
            pko.Keywords.Add("R3");
            pko.Keywords.Add("R4");
            pko.Keywords.Add("R5");
            pko.Keywords.Add("R6");
            pko.Keywords.Default = "L3";
            pko.AllowNone = false;

            PromptResult pkr = doc.Editor.GetKeywords(pko);
            int intOsnapMode = System.Convert.ToInt32(Application.GetSystemVariable("OSMODE"));
            Application.SetSystemVariable("OSMODE", 1);

            PromptPointOptions ppo = new PromptPointOptions("\nSelect Point: ");
            PromptPointResult ppr = ed.GetPoint(ppo);
            if (ppr.Status != PromptStatus.OK)
            {
                ed.WriteMessage("\nPoint not selected, Error!");
            }

            string strPath = @"\\autocad\AcadCustomizations\SYMBOLS\";
            string strBlock = pkr.StringResult + "DESC";


            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTableRecord CurrentSpaceBTR = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                if (bt.Has(strBlock))
                {
                    ObjectId tmpBlockId = bt[strBlock];
                    BlockTableRecord blkDefRecord = (BlockTableRecord)tr.GetObject(tmpBlockId, OpenMode.ForRead);
                    BlockReference br = new BlockReference(ppr.Value, tmpBlockId);
                    CurrentSpaceBTR.AppendEntity(br);
                    if (blkDefRecord.HasAttributeDefinitions)
                    {
                        foreach (ObjectId idAtt in blkDefRecord)
                        {
                            AttributeDefinition attDef = tr.GetObject(idAtt, OpenMode.ForRead) as AttributeDefinition;
                            if (attDef != null)
                            {
                                AttributeReference attRef = new AttributeReference();
                                attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
                                br.AttributeCollection.AppendAttribute(attRef);
                                tr.AddNewlyCreatedDBObject(attRef, true);
                            }
                        }
                        tr.AddNewlyCreatedDBObject(br, true);
                    }
                }
                else
                {
                    string sourceFileName = @"\\autocad\AcadCustomizations\SYMBOLS\L3DESC.dwg";
                    try
                    {
                        using ( Database tempDb = new Database( false, true ))
                        {
                            tempDb.ReadDwgFile(sourceFileName, FileShare.Read, true, null);
                            db.Insert(strBlock, tempDb, false);
                        }
                    }
                    catch (Autodesk.AutoCAD.Runtime.Exception e)
                    {
                        ed.WriteMessage(e.Message);
                    }


                }
                tr.Commit();

            }
            Application.SetSystemVariable("OSMODE", intOsnapMode);
        }
If I manually insert the block first, everything works as expected.

If I Do Not insert the block first, it goes and gets the block, but doesn't insert it. (it might be there, just not visable)  It does define the block in the BT though, because I can manually insert it after running through the code.

On a side note, I thought I saw a thread about direct cast VS. using AS,  any preference or situations where one works and the other doesn't?
Title: Re: Looking for some example code to insert block. (C#)
Post by: David Hall on September 21, 2009, 05:20:02 PM
Nevermind on the code question above, I'm an idiot with serious PEBCAK issuses.  I guess I should finish writing the code before I test it.

I am still interested in the () VS AS question
Title: Re: Looking for some example code to insert block. (C#)
Post by: sinc on September 21, 2009, 06:21:18 PM
A direct cast will throw an exception on failure.  "as" will set the value to null on failure.

Code: [Select]
T value1 = (T)value2;
The above will throw an exception if value2 cannot be cast to type T.

Code: [Select]
T value1 = value2 as T;
The above will set value1 equal to NULL if value2 cannot be cast to type T.

Title: Re: Looking for some example code to insert block. (C#)
Post by: David Hall on September 21, 2009, 06:26:22 PM
Thanks Sinc, that makes perfect sense. (Not bad for a monday afternoon)  So which is better? (I know that is a loaded question).  Seems to me setting to null is better than an exception, but would require test for null every time, where as I would only have to deal with the exception when it was thrown.  Having typed all that, I think I might prefer the exception now.
Title: Re: Looking for some example code to insert block. (C#)
Post by: Kerry on September 21, 2009, 10:18:40 PM
personally I'd rather use the 'AS' keyword
and test for null  locally because we are really doing data assertion, which may/could have specific requirements and subsequent actions ...
then use exception catching for 'exceptional' situations.

... perhaps I'm a little anal though :)

Title: Re: Looking for some example code to insert block. (C#)
Post by: sinc on September 22, 2009, 04:39:31 PM
One isn't inherently "better" than the other.  It depends on what the rest of your code is doing.

Usually, exception handling involves some extra overhead, so I usually try to avoid code that throws exceptions as a "normal" part of the operation.  So if all other things are equal, I would tend to prefer checking for a null, instead of catching an exception.

But depending on the rest of your code, and the conditions you expect during runtime, you may prefer one or the other in different situations.

For example, when we get objects from a transaction, we get DBObjects that we then generally must cast to a more-specific type.  If we are getting an object that the user selected on-screen, then the object may be one of a variety.  We can use various methods to check for the type of the selected object, but the simplest is often to use "as".  For example:

Code: [Select]
               PromptEntityResult ssResult = ed.GetEntity(promptOptions);
                if (ssResult.Status == PromptStatus.OK)
                {
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        DBObject dbObj = tr.GetObject(ssResult.ObjectId, OpenMode.ForRead, false);
                        Line line = dbObj as Line;
                        if (line != null)
                        {
                            // work with the line
                        }
                        else
                        {
                            Circle circle = dbObj as Circle;
                            if (circle != null)
                            {
                                // work with the circle
                            }
                            // repeat as necessary for more types
                        }

On the other hand, sometimes an object should pretty much always be of the expected type, and if the cast fails, it would indicate some sort of extraordinary circumstance.  In this situation, it might make more sense to use a direct cast, which would result in an exception on failure.
Title: Re: Looking for some example code to insert block. (C#)
Post by: It's Alive! on September 22, 2009, 06:10:00 PM
Use a cast when you think you 'want' an exception if the object is of the wrong type.
Use a cast when un-boxing value types as 'as' only works with reference types.