Author Topic: Delete Block References and Definitions  (Read 12685 times)

0 Members and 1 Guest are viewing this topic.

DBARANAS

  • Guest
Delete Block References and Definitions
« on: September 04, 2006, 05:53:01 AM »
I have been working on this for some time. It is supposed to making test blocks programmably and erasing them programmably

Create some solids
Add them to their own Block Definitions
Add the block Definitions to their own  Block References
Then go back and erase everything....


I can create blocks OK, but when I erase everything the block reference still lives in the db and a manual purge has to be done to really kill it, although things erase off the screen as expected.
I need to erase the block definition and reference from the database completely or I will get ghosts of deleted solids back when I make the block reference again.

I made this is stripped down version for testing.

In the test app (sub adjBlockDef) I can't get the block definition back from a handle.

 I think I might be going about getting it back the wrong way.  It's not making much sense as I have to get at the db.BlockTableId twice in the same sub of get a crash. Open 1st for read then again for write.

I hate to post lot's of code but it is stripped down to just do the 4 things it is supposed to. If anyone could give a quick look I would appreciate it.

Code: [Select]
       Public Sub BlockTest()

        Dim BlockDefHnd(5) As String
        Dim BlockRefHnd(5) As String
        Dim BlockName(5) As String
        Dim i As Integer = 0
        Dim j As Double = 10

        For i = 0 To 5
            BlockDefHnd(i) = vbNullString
            BlockRefHnd(i) = vbNullString
            BlockName(i) = "Blockname" & CStr(i)
        Next

        'Make some block references each containing 1 solid and 1 block definition each
        For i = 0 To 5
            addSomething(i * 10, i * 10, i * 10, BlockName(i), BlockDefHnd(i))
            addBlockRef(BlockName(i), BlockRefHnd(i))
        Next

        'No go and remove everything
        i = 0
        For i = 0 To 5
            adjBlockRef(BlockRefHnd(i))
            adjBlockDef(BlockDefHnd(i))
        Next

    End Sub
    Public Sub addSomething(ByVal x As Double, _
                            ByVal y As Double, _
                            ByVal z As Double, _
                            ByVal BlockName As String, _
                            ByRef BlockDefHnd As String)

        Dim aPnt As New Point3d(0, 0, 0)
        Dim bPnt As New Point3d(55, 0, 0)
        Dim cPnt As New Point3d(55, 5, 0)
        Dim dPnt As New Point3d(0, 5, 0)
        Dim colregion As DBObjectCollection = New DBObjectCollection()
        Dim colPoly As DBObjectCollection = New DBObjectCollection()
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim region As DatabaseServices.Region = New DatabaseServices.Region()
        Dim trans As Transaction = db.TransactionManager.StartTransaction()
        Dim pntCol As New Point3dCollection

        Try
            Dim bt As BlockTable = DirectCast(trans.GetObject(db.BlockTableId, DatabaseServices.OpenMode.ForRead, True), BlockTable)
            If bt Is Nothing Then Return
            Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()
            Dim btr As BlockTableRecord = DirectCast(trans.GetObject(bt(BlockTableRecord.ModelSpace), DatabaseServices.OpenMode.ForWrite, False), BlockTableRecord)
            If btr Is Nothing Then Return

            pntCol.Add(aPnt) : pntCol.Add(bPnt) : pntCol.Add(cPnt) : pntCol.Add(dPnt)
            Dim plRegion As New Polyline3d(Poly3dType.SimplePoly, pntCol, True)
            'create a region from the polyline
            colPoly.Add(plRegion)
            colregion = DatabaseServices.Region.CreateFromCurves(colPoly)
            region = CType(colregion(0), DatabaseServices.Region)
            'create the solid
            Dim solid As Solid3d = New Solid3d()
            solid.Extrude(region, 5, 0)

            Dim vector As New Vector3d(x, y, z)
            Dim matrix As Matrix3d = Matrix3d.Displacement(vector)
            solid.TransformBy(solid.Ecs.PostMultiplyBy(matrix))

            'need this to get at db again for write...have to do this or get a crash!!
            Dim btDef As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
            Dim BlockDefId As ObjectId
            If (bt.Has(BlockName)) Then
                BlockDefId = btDef(BlockName) 'Already there...no need to recreate it
                Dim BlockDef As BlockTableRecord = trans.GetObject(bt(BlockName), OpenMode.ForWrite)
                BlockDef.AppendEntity(solid)
                trans.AddNewlyCreatedDBObject(solid, True)
                BlockDefHnd = BlockDef.ObjectId.Handle.ToString()
            Else 'Create a new block definition
                Dim BlockDef As BlockTableRecord = New BlockTableRecord()
                BlockDef.Name = BlockName
                BlockDefId = btDef.Add(BlockDef)
                trans.AddNewlyCreatedDBObject(BlockDef, True)
                BlockDef.AppendEntity(solid)
                trans.AddNewlyCreatedDBObject(solid, True)
                BlockDefHnd = BlockDef.ObjectId.Handle.ToString()
            End If

            trans.Commit()
            doclock.Dispose()
            colPoly.Dispose()
            colregion.Dispose()
            plRegion.Dispose()
            pntCol.Dispose()
            region.Dispose()
            solid.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            trans.Abort()
            MsgBox(ex.StackTrace)
        Finally
            trans.Dispose()
        End Try

    End Sub

    Public Sub addBlockRef(ByVal BlockName As String, ByRef BlockRefHnd As String)

        Dim db As Database = HostApplicationServices.WorkingDatabase()
        Dim trans As Transaction = db.TransactionManager.StartTransaction()
        Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()

        Dim block As BlockReference = Nothing

        Try
            Dim bt As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
            Dim mspace As BlockTableRecord = trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)

            block = New BlockReference(New Point3d(0, 0, 0), bt(BlockName))

            mspace.AppendEntity(block)
            trans.AddNewlyCreatedDBObject(block, True)

            BlockRefHnd = block.ObjectId.Handle.Value.ToString() 'return handle to calling sub
            trans.Commit()
            doclock.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            trans.Abort()
            MsgBox(ex.StackTrace)
        Finally
            trans.Dispose()
        End Try

    End Sub

    Public Sub adjBlockRef(ByVal BlockRefHnd As String)

        Dim db As Database = HostApplicationServices.WorkingDatabase()
        Dim ed As EditorInput.Editor = AcAp.DocumentManager.MdiActiveDocument.Editor()
        Dim trans As Transaction = db.TransactionManager.StartTransaction()

        Try

            Dim id As ObjectId = db.GetObjectId(False, New Handle(Convert.ToInt64(BlockRefHnd)), 0)
            Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()
            Dim Block As BlockReference = DirectCast(trans.GetObject(id, DatabaseServices.OpenMode.ForWrite), BlockReference)

            Dim br As BlockTableRecord = DirectCast(trans.GetObject(Block.BlockTableRecord, DatabaseServices.OpenMode.ForRead, False), BlockTableRecord)
            For Each obj As ObjectId In br
                Dim ent As Entity = DirectCast(trans.GetObject(obj, DatabaseServices.OpenMode.ForWrite), Entity)
                ent.ObjectId.Handle.ToString()
                ent.Erase()
            Next obj

            Block.Erase()
            BlockRefHnd = vbNullString

            trans.Commit()
            db.Dispose()
            doclock.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            trans.Abort()
            MsgBox(ex.StackTrace)
        Finally
            trans.Dispose()
        End Try

    End Sub
    Public Sub adjBlockDef(ByVal BlockDefHnd As String)

        Dim db As Database = AcAp.DocumentManager.MdiActiveDocument.Database
        Dim ed As EditorInput.Editor = AcAp.DocumentManager.MdiActiveDocument.Editor()
        Dim trans As Transaction = db.TransactionManager.StartTransaction()

        Try

            Dim id As ObjectId = db.GetObjectId(False, New Handle(Convert.ToInt64(BlockDefHnd)), 0)
            Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()
            Dim BlockDef As BlockReference = DirectCast(trans.GetObject(id, DatabaseServices.OpenMode.ForWrite), BlockReference)

            BlockDef.Erase()
            BlockDefHnd = vbNullString

            trans.Commit()
            db.Dispose()
            doclock.Dispose()

        Catch ex As AcRu.Exception
            trans.Abort()
            MsgBox(ex.StackTrace)
        Finally
            trans.Dispose()
        End Try

    End Sub




DBARANAS

  • Guest
Re: Delete Block References and Definitions
« Reply #1 on: September 04, 2006, 08:22:46 AM »
I found a mistake

BlockDefHnd = BlockDef.ObjectId.Handle.ToString() .....should be

BlockDefHnd = BlockDef.ObjectId.Handle.Value.ToString()

....Now it works for the first pass. When I try the whole thing again I get eWasErased errors on these 2 lines. Interestingly on the second pass where it checks if block definitions exist ....(bt.Has(BlockName))... they do not exist as is expected because they got erased at the end of the first pass. So they get made again.

There has got to be something funny going on with the databases. I must be missing something being put where I can't find it again

sub adjBlockRef.......
     
      Dim br As BlockTableRecord = DirectCast(trans.GetObject(Block.BlockTableRecord, DatabaseServices.OpenMode.ForWrite, False), BlockTableRecord)

end sub

sub adjBlockDef.......

Dim BlockDef As BlockTableRecord = trans.GetObject(bt(BlockName), OpenMode.ForWrite)

end sub

Glenn R

  • Guest
Re: Delete Block References and Definitions
« Reply #2 on: September 04, 2006, 08:32:58 PM »
A very quick scan revealed some things you might consider:

You open the blocktable for read earlier, then you open it for write with another transaction statement.
You don't need to do that, you can do it like this:

if (!blockTable.IsWriteEnabled)
  blockTable.UpgradeOpen();

Cheers,
Glenn.

DBARANAS

  • Guest
Re: Delete Block References and Definitions
« Reply #3 on: September 04, 2006, 10:36:12 PM »

You open the blocktable for read earlier, then you open it for write with another transaction statement.
You don't need to do that, you can do it like this:

if (!blockTable.IsWriteEnabled)
  blockTable.UpgradeOpen();

Thanks Glenn

I pasted it in ........
Code: [Select]
         'need this to get at db again for write...have to do this or get a crash!!
            If Not bt.IsWriteEnabled Then bt.UpgradeOpen()
            'Dim btDef As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
            Dim BlockDefId As ObjectId
            If (bt.Has(BlockName)) Then
                BlockDefId = bt(BlockName) 'Already there...no need to recreate it
                Dim BlockDef As BlockTableRecord = trans.GetObject(bt(BlockName), OpenMode.ForWrite)
                BlockDef.AppendEntity(solid)
                trans.AddNewlyCreatedDBObject(solid, True)
                BlockDefHnd = BlockDef.ObjectId.Handle.Value.ToString()
            Else 'Create a new block definition
                Dim BlockDef As BlockTableRecord = New BlockTableRecord()
                BlockDef.Name = BlockName
                BlockDefId = bt.Add(BlockDef)
                trans.AddNewlyCreatedDBObject(BlockDef, True)
                BlockDef.AppendEntity(solid)
                trans.AddNewlyCreatedDBObject(solid, True)
                BlockDefHnd = BlockDef.ObjectId.Handle.Value.ToString()
            End If

Unfortunately It stopped the loop from going through the first time.

It seems that I have the db objects (I can see all the properties of them when I step through.

On the second pass I can create everything again, but the second time I try to delete those block ref's and def's I get the eWasErased error when I try to cast them back. I am wondering about using a key so I can skip a few steps


Glenn R

  • Guest

Glenn R

  • Guest
Re: Delete Block References and Definitions
« Reply #5 on: September 05, 2006, 02:25:04 AM »
Also, unless you are executing this command from the application context (eg. a modeless dialog), you don't need the document locking code as Autocad will automatically lock the document for you.

I'll try and have more of a look this evening.

Cheers,
Glenn.

DBARANAS

  • Guest
Re: Delete Block References and Definitions
« Reply #6 on: September 05, 2006, 09:25:20 PM »
Also, unless you are executing this command from the application context (eg. a modeless dialog), you don't need the document locking code as Autocad will automatically lock the document for you.

Thanks, Glenn

Yes everything is from the application context

I took a look at Tony's example you pointed out. It makes sense seeing how the db really works. I tried to get it to work in the adjRef sub.

It returns an ObjectID back but fails to convert it into a blockreference.

Code: [Select]
    Public Sub adjBlockRef(ByVal BlockName As String)

        Dim db As Database = HostApplicationServices.WorkingDatabase()
        Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()
        Dim tr As Transaction = db.TransactionManager.StartTransaction()
        Dim objID As ObjectId = ObjectId.Null
        Try

            Dim bt As BlockTable = CType(tr.GetObject(db.BlockTableId, DatabaseServices.OpenMode.ForRead), BlockTable)
            objID = GetNonErasedTableRecordId(db.BlockTableId, BlockName)
            Dim bref As BlockReference = CType(tr.GetObject(objID, DatabaseServices.OpenMode.ForRead), BlockReference)

            tr.Commit()
            db.Dispose()
            doclock.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            tr.Abort()
            MsgBox(ex.StackTrace)
        Finally
            tr.Dispose()
        End Try


    End Sub

Code: [Select]
    Public Function GetNonErasedTableRecordId(ByVal TableId As ObjectId, ByVal Name As String) As ObjectId
        Dim id As ObjectId = ObjectId.Null
        Using tr As Transaction = TableId.Database.TransactionManager.StartTransaction()
            Dim table As SymbolTable = CType(tr.GetObject(TableId, OpenMode.ForRead), SymbolTable)
            If table.Has(Name) Then
                id = table(Name)
                If (Not id.IsErased) Then
                    Return id
                End If
                For Each recId As ObjectId In table
                    If (Not recId.IsErased) Then
                        Dim rec As SymbolTableRecord = CType(tr.GetObject(recId, OpenMode.ForRead), SymbolTableRecord)
                        If String.Compare(rec.Name, Name, True) = 0 Then
                            Return recId
                        End If
                    End If
                Next recId
            End If
        End Using
        Return id
    End Function

Glenn R

  • Guest
Re: Delete Block References and Definitions
« Reply #7 on: September 05, 2006, 10:25:45 PM »
Two things:

1. You're NOT checking the return value from GetNonErasedWhaetever.
if (objId == ObjectId.Null)
  return;

or something like that.

Also, NEVER EVER try and dispose of a databse that AutoCAD owns.
You do this:
Code: [Select]
Dim db As Database = HostApplicationServices.WorkingDatabase()
then later on in that sub you do this:
Code: [Select]
db.Dispose()
Which is almost certain to cause a "welcome to the desktop" crash from Acad.

The golden rule in C++ and to an extent in C# is, if you 'new' it, then delete/dispose it - if not then don't. There are exceptions to this but in general that's it.

Cheers,
Glenn.
« Last Edit: September 05, 2006, 10:27:14 PM by Glenn R »

Glenn R

  • Guest
Re: Delete Block References and Definitions
« Reply #8 on: September 05, 2006, 10:29:20 PM »
Adding to the golden rule I mentioned above, if you 'new' something, then add it to the AutoCAD databse, then autocad owns it, so don't delete/dispose of it.

Glenn R

  • Guest
Re: Delete Block References and Definitions
« Reply #9 on: September 05, 2006, 10:39:32 PM »
Here is a contrived trivial example I started yesterday to demonstrate some concepts.
I will try to keep adding to it, however I'm flat out like a lizard drinking at the moment.

Code: [Select]
[CommandMethod("DaveBCreateBlks")]
static public void DaveBCreateBlksCommand( )
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;

string [ ] blockNames = new string [ ] { "Test1", "Test2" };

foreach (string blkName in blockNames)
CreateBlkDefs(db, blkName);

}

private static void CreateBlkDefs(Database db, string blkName) {

using (Transaction tr = db.TransactionManager.StartTransaction()) {

                // Deliberately open for read here as an example of UpgradeOpen below...
                BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead, false) as BlockTable;
                if (bt == null)
                                return;

                BlockTableRecord btr = new BlockTableRecord();
                                btr.Name = blkName;
                btr.Origin = Point3d.Origin;

                if (!bt.IsWriteEnabled)
                    bt.UpgradeOpen();

                bt.Add(btr);
                tr.AddNewlyCreatedDBObject(btr, true);

                tr.Commit();
                }
}

Cheers,
Glenn.
« Last Edit: September 05, 2006, 10:40:52 PM by Glenn R »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Delete Block References and Definitions
« Reply #10 on: September 05, 2006, 10:44:13 PM »
....  however I'm flat out like a lizard drinking at the moment.

Cheers,
Glenn.

That makes 6 of us  ... I'm sneaking a quick peek here and having lunch while my system is doing attribute extraction ..
.. really peeved that I can't make the time to contribute .. 
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

DBARANAS

  • Guest
Re: Delete Block References and Definitions
« Reply #11 on: September 06, 2006, 04:09:34 AM »
Well This is what I came up with. I have looked through everything block related both in the swamp and over at AD .Net (about 100 threads so far). I did try everything else for clues and most examples do only a part of what I need to have working.

I ended up doing it the way I do most everything....get the handle of something, store it in a binary file and use it to return an object.

This is unorthodox (hacked by trial and error), but I think it gets rid of the isErased issues inherit in the acad DB. I am thinking that if I have the real handle then I can get the real object back and don't care about orphaned clutter in the DB. In the test case things seem to be proving this. I will find out shortly when I try to plug it into the app. I am not really satisfied with it after seeing better approaches, but it's all I know for now and it's working.

here it is in VB and C# below(converted)

VB
Code: [Select]
    Public Sub BlockTest()

        Dim blkDefHnd As String = vbNullString
        Dim blkRefHnd As String = vbNullString
        Dim blkName As String = "TESTBLOCK"

        'Make a block reference containing 1 solid and 1 block definition
        addSomething(blkName, blkDefHnd)
        'No go and remove everything
        addBlockRef(blkName, blkRefHnd)
        adjBlockDef(blkDefHnd, blkName)
        adjBlockRef(blkName, blkRefHnd)

    End Sub

Code: [Select]
    Public Sub addSomething(ByVal blkName As String, _
                            ByRef BlockDefHnd As String)

        Dim aPnt As New Point3d(0, 0, 0)
        Dim bPnt As New Point3d(55, 0, 0)
        Dim cPnt As New Point3d(55, 5, 0)
        Dim dPnt As New Point3d(0, 5, 0)
        Dim colregion As DBObjectCollection = New DBObjectCollection()
        Dim colPoly As DBObjectCollection = New DBObjectCollection()
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim region As DatabaseServices.Region = New DatabaseServices.Region()
        Dim tr As Transaction = db.TransactionManager.StartTransaction()
        Dim pntCol As New Point3dCollection

        Try
            Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()
            Dim bt As BlockTable = tr.GetObject(db.BlockTableId, DatabaseServices.OpenMode.ForWrite, True)
            If bt Is Nothing Then Return
            pntCol.Add(aPnt) : pntCol.Add(bPnt) : pntCol.Add(cPnt) : pntCol.Add(dPnt)
            Dim plRegion As New Polyline3d(Poly3dType.SimplePoly, pntCol, True)
            'create a region from the polyline
            colPoly.Add(plRegion)
            colregion = DatabaseServices.Region.CreateFromCurves(colPoly)
            region = CType(colregion(0), DatabaseServices.Region)
            'create the solid
            Dim solid As Solid3d = New Solid3d()
            solid.Extrude(region, 5, 0)

            If (bt.Has(blkName)) Then
                Dim btr As BlockTableRecord = TryCast(tr.GetObject(bt(blkName), OpenMode.ForWrite, False), BlockTableRecord)
                If btr Is Nothing Then Return
                btr.AppendEntity(solid)
                tr.AddNewlyCreatedDBObject(solid, True)
                BlockDefHnd = btr.ObjectId.Handle.Value.ToString()
            Else 'Create a new block definition
                Dim btr As BlockTableRecord = New BlockTableRecord()
                btr.Name = blkName
                bt.Add(btr)
                tr.AddNewlyCreatedDBObject(btr, True)
                btr.AppendEntity(solid)
                tr.AddNewlyCreatedDBObject(solid, True)
                BlockDefHnd = btr.ObjectId.Handle.Value.ToString()
            End If

            tr.Commit()
            doclock.Dispose()
            colPoly.Dispose()
            colregion.Dispose()
            plRegion.Dispose()
            pntCol.Dispose()
            region.Dispose()
            solid.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            tr.Abort()
            MsgBox(ex.StackTrace)
        Finally
            tr.Dispose()
        End Try

    End Sub

Code: [Select]
    Public Sub addBlockRef(ByVal blkName As String, ByRef blkRefhnd As String)

        Dim db As Database = HostApplicationServices.WorkingDatabase()
        Dim tr As Transaction = db.TransactionManager.StartTransaction()
        Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()

        Dim block As BlockReference = Nothing

        Try
            Dim bt As BlockTable = tr.GetObject(db.BlockTableId, DatabaseServices.OpenMode.ForRead, True)
            Dim btr As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, True)

            block = New BlockReference(New Point3d(0, 0, 0), bt(blkName))
            btr.AppendEntity(block)
            tr.AddNewlyCreatedDBObject(block, True)
            blkRefhnd = block.ObjectId.Handle.Value.ToString() 'return handle to calling sub
            tr.Commit()
            doclock.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            tr.Abort()
            MsgBox(ex.StackTrace)
        Finally
            tr.Dispose()
        End Try

    End Sub

Code: [Select]
    Public Sub adjBlockRef(ByVal blkName As String, ByVal BlockRefHnd As String)

        Dim db As Database = HostApplicationServices.WorkingDatabase()
        Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()
        Dim tr As Transaction = db.TransactionManager.StartTransaction()
        Try

            Dim id As ObjectId = db.GetObjectId(False, New Handle(Convert.ToInt64(BlockRefHnd)), 0)
            Dim Block As BlockReference = DirectCast(tr.GetObject(id, DatabaseServices.OpenMode.ForWrite), BlockReference)

            Block.Erase()
            tr.Commit()
            doclock.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            tr.Abort()
            MsgBox(ex.StackTrace)
        Finally
            tr.Dispose()
        End Try

    End Sub

Code: [Select]
    Public Sub adjBlockDef(ByVal BlockDefHnd As String, ByVal blkName As String)

        Dim db As Database = AcAp.DocumentManager.MdiActiveDocument.Database
        Dim trans As Transaction = db.TransactionManager.StartTransaction()

        Try

            Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()
            Dim bt As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
            Dim id As ObjectId = db.GetObjectId(False, New Handle(Convert.ToInt64(BlockDefHnd)), 0)
            Dim BlockDef As BlockTableRecord = trans.GetObject(id, OpenMode.ForWrite)

            BlockDef.Erase()
            BlockDef.IsUnloaded = True
            BlockDefHnd = vbNullString

            trans.Commit()
            doclock.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            trans.Abort()
            MsgBox(ex.StackTrace)
        Finally
            trans.Dispose()
        End Try

    End Sub

C#

Code: [Select]
public void BlockTest()
{

string blkDefHnd = Microsoft.VisualBasic.Constants.vbNullString;
string blkRefHnd = Microsoft.VisualBasic.Constants.vbNullString;
string blkName = "TESTBLOCK";

//Make a block reference containing 1 solid and 1 block definition
addSomething(blkName, blkDefHnd);
//No go and remove everything
addBlockRef(blkName, blkRefHnd);
adjBlockDef(blkDefHnd, blkName);
adjBlockRef(blkName, blkRefHnd);
       {

Code: [Select]
public void addSomething(string blkName, ref string BlockDefHnd)
{

Point3d aPnt = new Point3d(0, 0, 0);
Point3d bPnt = new Point3d(55, 0, 0);
Point3d cPnt = new Point3d(55, 5, 0);
Point3d dPnt = new Point3d(0, 5, 0);
DBObjectCollection colregion = new DBObjectCollection();
DBObjectCollection colPoly = new DBObjectCollection();
Database db = HostApplicationServices.WorkingDatabase;
DatabaseServices.Region region = new DatabaseServices.Region();
Transaction tr = db.TransactionManager.StartTransaction();
Point3dCollection pntCol = new Point3dCollection();

try
{
DocumentLock doclock = AcAp.DocumentManager.MdiActiveDocument.LockDocument();
BlockTable bt = tr.GetObject(db.BlockTableId, DatabaseServices.OpenMode.ForWrite, true);
if (bt == null)
{
return;
}
pntCol.Add(aPnt);
pntCol.Add(bPnt);
pntCol.Add(cPnt);
pntCol.Add(dPnt);
Polyline3d plRegion = new Polyline3d(Poly3dType.SimplePoly, pntCol, true);
//create a region from the polyline
colPoly.Add(plRegion);
colregion = DatabaseServices.Region.CreateFromCurves(colPoly);
region = (DatabaseServices.Region)(colregion(0));
//create the solid
Solid3d solid = new Solid3d();
solid.Extrude(region, 5, 0);

if (bt.Has(blkName))
{
BlockTableRecord btr = tr.GetObject(bt(blkName), Microsoft.VisualBasic.OpenMode.ForWrite, false) as BlockTableRecord;
if (btr == null)
{
return;
}
btr.AppendEntity(solid);
tr.AddNewlyCreatedDBObject(solid, true);
BlockDefHnd = btr.ObjectId.Handle.Value.ToString();
}
else //Create a new block definition
{
BlockTableRecord btr = new BlockTableRecord();
btr.Name = blkName;
bt.Add(btr);
tr.AddNewlyCreatedDBObject(btr, true);
btr.AppendEntity(solid);
tr.AddNewlyCreatedDBObject(solid, true);
BlockDefHnd = btr.ObjectId.Handle.Value.ToString();
}

tr.Commit();
doclock.Dispose();
colPoly.Dispose();
colregion.Dispose();
plRegion.Dispose();
pntCol.Dispose();
region.Dispose();
solid.Dispose();

}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
tr.Abort();
MessageBox.Show(ex.StackTrace);
}
finally
{
tr.Dispose();
}

}

Code: [Select]
public void addBlockRef(string blkName, ref string blkRefhnd)
{

Database db = HostApplicationServices.WorkingDatabase();
Transaction tr = db.TransactionManager.StartTransaction();
DocumentLock doclock = AcAp.DocumentManager.MdiActiveDocument.LockDocument();

BlockReference block = null;

try
{
BlockTable bt = tr.GetObject(db.BlockTableId, DatabaseServices.OpenMode.ForRead, true);
BlockTableRecord btr = tr.GetObject(bt(BlockTableRecord.ModelSpace), Microsoft.VisualBasic.OpenMode.ForWrite, true);

block = new BlockReference(new Point3d(0, 0, 0), bt(blkName));
btr.AppendEntity(block);
tr.AddNewlyCreatedDBObject(block, true);
blkRefhnd = block.ObjectId.Handle.Value.ToString(); //return handle to calling sub
tr.Commit();
doclock.Dispose();

}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
tr.Abort();
MessageBox.Show(ex.StackTrace);
}
finally
{
tr.Dispose();
}

}

Code: [Select]
public void adjBlockRef(string blkName, string BlockRefHnd)
{

Database db = HostApplicationServices.WorkingDatabase();
DocumentLock doclock = AcAp.DocumentManager.MdiActiveDocument.LockDocument();
Transaction tr = db.TransactionManager.StartTransaction();
try
{

ObjectId id = db.GetObjectId(false, new Handle(Convert.ToInt64(BlockRefHnd)), 0);
BlockReference Block = (BlockReference)(tr.GetObject(id, DatabaseServices.OpenMode.ForWrite));

Block.Erase();
tr.Commit();
doclock.Dispose();

}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
tr.Abort();
MessageBox.Show(ex.StackTrace);
}
finally
{
tr.Dispose();
}

}

Code: [Select]
    Public Sub adjBlockDef(ByVal BlockDefHnd As String, ByVal blkName As String)

        Dim db As Database = AcAp.DocumentManager.MdiActiveDocument.Database
        Dim trans As Transaction = db.TransactionManager.StartTransaction()

        Try

            Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()
            Dim bt As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
            Dim id As ObjectId = db.GetObjectId(False, New Handle(Convert.ToInt64(BlockDefHnd)), 0)
            Dim BlockDef As BlockTableRecord = trans.GetObject(id, OpenMode.ForWrite)

            BlockDef.Erase()
            BlockDef.IsUnloaded = True
            BlockDefHnd = vbNullString

            trans.Commit()
            doclock.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            trans.Abort()
            MsgBox(ex.StackTrace)
        Finally
            trans.Dispose()
        End Try

    End Sub

DBARANAS

  • Guest
Re: Delete Block References and Definitions
« Reply #12 on: September 06, 2006, 09:56:38 AM »
I spoke too soon. It still works correct only on the first pass. I thought it was working because it was not throwing anymore exceptions and I could hammer it after I saw the first solid flicker by on the screen (which is quicker than my braindead eyes now). I plugged it in to the main app to find this out.

When I make a block again this line

            block = New BlockReference(New Point3d(0, 0, 0), bt(blkName))


has to be getting the isErased blockdef that was deleted before. The btr that I append the solid to is good when I step though, so when I add it to the blockref it must be inserting empty space....kinda like what's behind my eyes


DBARANAS

  • Guest
Re: Delete Block References and Definitions
« Reply #13 on: September 06, 2006, 10:21:07 AM »
Yep that was it....I had to do it by passing the handle.

So this is what I got.....

I can make solid assemblies from parameters
Throw everything into a block
Modify, Delete, Dis-Assemble, etc from the app without selecting anything (all parameters and commands on tool palette)
Everything automatic

Thanks Glenn for helping me, anyone else wanting this functionality should find this useful I hope.

Code: [Select]
    Public Sub addBlockRef(ByVal blkDefhnd As String, ByRef blkRefhnd As String)

        Dim db As Database = HostApplicationServices.WorkingDatabase()
        Dim tr As Transaction = db.TransactionManager.StartTransaction()
        Dim doclock As DocumentLock = AcAp.DocumentManager.MdiActiveDocument.LockDocument()

        Dim block As BlockReference = Nothing

        Try
            Dim bt As BlockTable = tr.GetObject(db.BlockTableId, DatabaseServices.OpenMode.ForRead, True)
            Dim id As ObjectId = db.GetObjectId(False, New Handle(Convert.ToInt64(blkDefhnd)), 0)
            Dim btr As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, True)

            block = New BlockReference(New Point3d(0, 0, 0), id)
            btr.AppendEntity(block)
            tr.AddNewlyCreatedDBObject(block, True)
            blkRefhnd = block.ObjectId.Handle.Value.ToString() 'return handle to calling sub
            tr.Commit()
            doclock.Dispose()

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            tr.Abort()
            MsgBox(ex.StackTrace)
        Finally
            tr.Dispose()
        End Try

    End Sub