TheSwamp

Code Red => .NET => Topic started by: Bobby C. Jones on December 28, 2005, 02:59:28 PM

Title: AU 2005 code - Part 7 "Digging into the Database"
Post by: Bobby C. Jones on December 28, 2005, 02:59:28 PM
Get out yer' shovels and start diggin'

This is the basics of the Database.  Nothing new to most of you.

Code: [Select]

using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;

using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace AU2005.AcadApi
{

//Pages 13 to 17
public class DatabaseExamples
{

//Page14
//Digging into the database, symbol tables, and ObjectId's
[CommandMethod("ShowAllLayers")]
public void ShowAllLayers()
{
//Get the current editor object
Editor currentEditor = AcadApp.DocumentManager.MdiActiveDocument.Editor;

//Get the current database object
Database activeDatabase = currentEditor.Document.Database;

//Start a transaction
using(Transaction trans = activeDatabase.TransactionManager.StartTransaction())
{
//Open the layer table
ObjectId layertableId = activeDatabase.LayerTableId;
LayerTable layers = (LayerTable)trans.GetObject(layertableId,OpenMode.ForRead);

//Iterate the layerId's in the layer table
foreach (ObjectId layerId in layers)
{
//Open the layer for reading
LayerTableRecord layer = (LayerTableRecord)trans.GetObject(layerId, OpenMode.ForRead);

//Print the layer name to the command line
currentEditor.WriteMessage("\n" + layer.Name);
}
}
}


//Page 15
//Accessing databases in the editor and from a file
[CommandMethod("InsertBlock")]
public void InsertBlock()
{
string sourceFileName = @"C:\OftenUsedBlock.dwg";
string newBlockName = "OftenUsedBlock";

try
{
using(Database sourceDatabase = GetDatabaseFromFile(sourceFileName))
{
//Insert the entities from modelspace of the sourceDatabase into
//a new block table record of the working database
HostApplicationServices.WorkingDatabase.Insert(newBlockName, sourceDatabase, false);
}
}
catch (System.Exception e)
{
Application.ShowAlertDialog(e.Message);
}
}

public Database GetDatabaseFromFile(string fileName)
{
Database databaseFromFile = new Database(false, true);
databaseFromFile.ReadDwgFile(fileName, System.IO.FileShare.None, false, null);
return databaseFromFile;
}



//Page 15 lists the steps, Page 17 lists the code
//Adding objects to a database
//The six steps revealed!
[CommandMethod("CreateCircle")]
public void DrawCircle ()
{
//Step one - Start a transaction
using (Transaction trans = StartActiveDatabaseTransaction())
{
//Step two - Create the new object
Circle newCircle = CreateCircle();

//Step three - Open the symbol table
BlockTableRecord modelSpace = OpenActiveModelSpaceForWrite(trans);

//Step four - Append the object to the symbol table
modelSpace.AppendEntity(newCircle);

//Step five - Inform the transactionmanager of the new object
trans.TransactionManager.AddNewlyCreatedDBObject(newCircle, true);

//Step six - Commit the transaction
trans.Commit();
}
}

private Transaction StartActiveDatabaseTransaction()
{
return HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction();
}

private Circle CreateCircle()
{
Point3d centerPoint = new Point3d(0, 0, 0);
Vector3d normal = new Vector3d(0, 0, 1);
double radius = 4.5;
return new Circle(centerPoint, normal, radius);
}

private BlockTableRecord OpenActiveModelSpaceForWrite(Transaction trans)
{
return (BlockTableRecord)trans.GetObject(GetActiveModelSpaceId(), OpenMode.ForWrite);
}

private ObjectId GetActiveModelSpaceId ()
{
using (Transaction trans = StartActiveDatabaseTransaction())
{
BlockTable bt = (BlockTable)trans.GetObject(HostApplicationServices.WorkingDatabase.BlockTableId, OpenMode.ForRead);

return (ObjectId) bt[BlockTableRecord.ModelSpace];
}
}



//Page 16
//Adding non graphic objects
//Variations of the six steps
public static ObjectId CreateLayer(string layerName, Database targetDatabase)
{
//Step one - Start a transaction
using (Transaction trans =targetDatabase.TransactionManager.StartTransaction())
{
ObjectId layerTableId = targetDatabase.LayerTableId;

//Step three - Open the symbol table
//This table has only been opened for reading
LayerTable layers = (LayerTable)trans.GetObject(layerTableId, OpenMode.ForRead);

if (layers.Has(layerName))
{
return layers[layerName];
}
else
{
//Step two - Create the new object
LayerTableRecord newLayer = new LayerTableRecord();
newLayer.Name = layerName;

//Step three - Open the symbol table for writing
layers.UpgradeOpen();

//Step four - Append the object to the symbol table
layers.Add(newLayer);

//Step five - Inform the transactionmanager of the new object
trans.TransactionManager.AddNewlyCreatedDBObject(newLayer, true);

//Step six - Commit the transaction
trans.Commit();

return newLayer.ObjectId;
}
}
}

[CommandMethod("CreateLayer")]
public void CreateLayer()
{
string newLayerName = "AU2005";
CreateLayer(newLayerName, HostApplicationServices.WorkingDatabase);
}
}
}

Title: Re: AU 2005 code - Part 7 "Digging into the Database"
Post by: TR on December 29, 2005, 11:42:31 AM
Bobby:
I have found that in order for the insert block command to work on multiple drawings in a session you need to close the file in this function. At least this is the case for me in AutoCAD 2005.
Code: [Select]
public Database GetDatabaseFromFile(string fileName)
{
Database databaseFromFile = new Database(false, true);
databaseFromFile.ReadDwgFile(fileName, System.IO.FileShare.None, false, null);
databaseFromFile.CloseInput(true);
return databaseFromFile;
}

Thanks for all the awesome examples and keep em coming. :)
Title: Re: AU 2005 code - Part 7 "Digging into the Database"
Post by: Bobby C. Jones on December 29, 2005, 12:12:15 PM
Bobby:
I have found that in order for the insert block command to work on multiple drawings in a session you need to close the file in this function. At least this is the case for me in AutoCAD 2005.

Thanks for the heads up Tim!
Title: Re: AU 2005 code - Part 7 "Digging into the Database"
Post by: TR on December 29, 2005, 01:15:16 PM
No problem. Just out of curiosity, does your code work with multiple drawings in a single session in 2006? For example running InsertBlock on Drawing1.dwg, creating a new drawing and then running InsertBlock on Drawing2.dwg.
Title: Re: AU 2005 code - Part 7 "Digging into the Database"
Post by: Kerry on January 10, 2006, 03:16:51 PM
Missed this Tim

command handlers run in the application context when they are registered with "CommandFlags.Session"

so you'd need this sort of thing to register the command ;

[CommandMethod("MySuperDuperCommand",CommandFlags.Session)]