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

insertion doesnt redefine

8 REPLIES 8
Reply
Message 1 of 9
Anonymous
320 Views, 8 Replies

insertion doesnt redefine

Ok, I know that the "insert block with attributes" thing has been beat
to death here so Im not asking about that. I do have some code that inserts
an external block, with attributes and it seems to work fine. Doing this
programmatically seems to have a "side effect" though.
If I insert a block, for simplicity sake, just a circle, into a drawing,
it looks just fine. If, while still in the drawing, I open up the block on disc
and change the circle to a square, then run the program again something strange happens.
The block inserts as a square, but the existing circle block does not change!
The block definition, as viewed with the insert or block command shows the new block
definition, but the pre-existing block reference does not get altered. How can it
be possible to have to block references that look different when they reference the
same block definition???
If I do the same process manually, with the insert command, pre-existing blocks are
redefined, why not when done via code?
Thanks, Perry
8 REPLIES 8
Message 2 of 9
Anonymous
in reply to: Anonymous

So whats the deal? After a blockdef is redefined are we supposed to delete all references, then reinsert them
for them to reflect the new definition? Is that what Acad does behind the scenes when a user issues the insert
command and answers "yes" to the redefine prompt?
I still dont see how references can remain unchanged when the definition has been altered.
Message 3 of 9
Anonymous
in reply to: Anonymous

After your block definition is updated you can call the
.RecordGraphicsModified(true) method of each block reference to updated the
graphics.
--
Bobby C. Jones

"perry" wrote in message
news:5159663@discussion.autodesk.com...
So whats the deal? After a blockdef is redefined are we supposed to delete
all references, then reinsert them
for them to reflect the new definition? Is that what Acad does behind the
scenes when a user issues the insert
command and answers "yes" to the redefine prompt?
I still dont see how references can remain unchanged when the definition has
been altered.
Message 4 of 9
Anonymous
in reply to: Anonymous

For proper undo/redo handling, within the same transaction
in which you update the block's definition, you should also
open each block reference and call its AssertWriteEnabled()
member, passing true for both arguments.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005/2006/2007
http://www.acadxtabs.com

"perry" wrote in message news:5159663@discussion.autodesk.com...
So whats the deal? After a blockdef is redefined are we supposed to delete all references, then reinsert them
for them to reflect the new definition? Is that what Acad does behind the scenes when a user issues the insert
command and answers "yes" to the redefine prompt?
I still dont see how references can remain unchanged when the definition has been altered.
Message 5 of 9
Anonymous
in reply to: Anonymous

Thanks guys.
At first, I thought that .RecordGraphicsModified was'nt doing the trick either as I did not see a change
on screen. I then stumbled into the fact that a "Regen" must be issued as well. I couldnt find how to do that
in .Net! Found out here that regen is not exposed in .Net so had to use "SendStringToExecute". blah.
Well, at least now my function appears to work as intended, finally !
As for AssertWriteEnabled(), couldnt use that at all! According to Visual Studio it is not a member of
BlockReferences or BlockDefinitions ?
Perry
Message 6 of 9
Anonymous
in reply to: Anonymous

Oops. Sorry, The AssertWriteEanbled() trick doesn't work in
managed code (but does in native ObjectARX).

First, RecordGraphicsModified is not doing anything, if you
are doing a regen anyways. A regen alone will do it, but the
whole point (or so I thought) was to do it without requiring
a complete regen of the drawing.

You should not have to regen the entire drawing to update
block references. And, if you have a large drawing, doing
that is highly undesireable.

The easiest way to do it, is to open each block reference for
write in the same transaction where you update the block
definition, and set the BlockTableRecord property to the same
value it currently has:

BlockRefererence blkref = trans.GetObject(id, OpenMode.ForWrite);

blkref.BlockTableRecord = blkref.BlockTableRecord;

trans.Commit();

In fact, you may not even need to set the BlockTableRecord
property at all, just open the blockreference for write may be
all you need to do.

This works when your code is running in a registered command
handler registere to run in the document context. In the case
your code is running modelessly (application context), things
are a bit different.


--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005/2006/2007
http://www.acadxtabs.com

"perry" wrote in message news:5161557@discussion.autodesk.com...
Thanks guys.
At first, I thought that .RecordGraphicsModified was'nt doing the trick either as I did not see a change
on screen. I then stumbled into the fact that a "Regen" must be issued as well. I couldnt find how to do that
in .Net! Found out here that regen is not exposed in .Net so had to use "SendStringToExecute". blah.
Well, at least now my function appears to work as intended, finally !
As for AssertWriteEnabled(), couldnt use that at all! According to Visual Studio it is not a member of
BlockReferences or BlockDefinitions ?
Perry
Message 7 of 9
Anonymous
in reply to: Anonymous

Tony Tanzillo wrote:
> Oops. Sorry, The AssertWriteEanbled() trick doesn't work in
> managed code (but does in native ObjectARX).

No problem Tony.
Quite true, I really do not want to do a regen if possible.
It seems that RecordGraphicsModified did not work as expected
because I had the blockref open for READ. When I changed it to
write mode it updated on screen just like I wanted. This brings
me to a couple other questions I'll do another post on.
In the meantime I posted my finished method below, hopefully
some other .Net newbies will find it useful. I believe its
pretty good & flexible. If anyone has any improvements to it,
Im all ears.
Thanks, Perry



///
/// Inserts an external drawing with or without attributes as a block into the current drawing.
/// Redefines current block if it already exists.
///

/// null-terminated string that specifies the name of the input file.
///boolean, if true inserts into current paperspace, otherwise inserts into modelspace.
///3Dpoint object, insertion point for block.
public static void insertBlock(string fileName, bool PaperSpace, Point3d location)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
// If file doesnt exist, bail
if (!File.Exists(fileName))
return;
// Create a block definition name
//the block def name will be same as file name minus path & extension
string insert = fileName;
//remove path
int pos = 0;
pos = insert.LastIndexOf("\\");
insert = insert.Remove(0, pos + 1);
//remove extension
int len;
len = insert.Length;
if (insert.ToUpper().Contains(".DWG"))
insert = insert.Remove(len - 4, 4);

using (Database db = new Database(false, false))
{
// Read the external drawing file into our temporary database
db.ReadDwgFile(fileName, FileShare.Read, true, null);
using (Transaction t = doc.TransactionManager.StartTransaction())
{
//get the block table
BlockTable bt = (BlockTable)t.GetObject(doc.Database.BlockTableId, OpenMode.ForWrite);
//get the (x)space table record
BlockTableRecord btr;
if (PaperSpace)
btr = (BlockTableRecord)t.GetObject(bt[BlockTableRecord.PaperSpace], OpenMode.ForWrite);
else
btr = (BlockTableRecord)t.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
//if the block already exists in the database, redefine the definition
//and update all the references
if (bt.Has(insert))
{
ObjectId idBTR = doc.Database.Insert(insert, db, true);
foreach (ObjectId objId in btr)
{
// For each object in the block table record, cast it to a block reference
DBObject dbObj = t.GetObject(objId, OpenMode.ForWrite);
BlockReference blkRef = dbObj as BlockReference;
string blkName = "";
if (blkRef != null)
{
// If it is a block reference, first check its name to see if its the one we want
BlockTableRecord blkDef = (BlockTableRecord)t.GetObject(blkRef.BlockTableRecord, OpenMode.ForWrite);
blkName = blkDef.Name.ToString();
if (blkName == insert)
{
blkRef.RecordGraphicsModified(true); // As per Bobby Jones
//when openmode above was "read" the RecordGraphicsModified didnt work
}
}
}
}
// Else, create a new definition and insert a new reference.
else
{
ObjectId idBTR = doc.Database.Insert(insert, db, true);
// Now create a new block reference
BlockReference bref = new BlockReference(location, idBTR);
//Add the block reference to the model space
btr.AppendEntity(bref);
//let the transaction know
t.TransactionManager.AddNewlyCreatedDBObject(bref, true);
//copy attributes from defintion to reference
Entity ent;
BlockTableRecord newbtr = (BlockTableRecord)t.GetObject(idBTR, OpenMode.ForWrite);
foreach (ObjectId id in newbtr)
{
ent = (Entity)t.GetObject(id, OpenMode.ForWrite);
if (ent is AttributeDefinition)
{
AttributeDefinition attDef = new AttributeDefinition();
AttributeReference attRef = new AttributeReference();
attDef = (AttributeDefinition)ent;
attRef.SetAttributeFromBlock(attDef, bref.BlockTransform);
bref.AttributeCollection.AppendAttribute(attRef);
t.TransactionManager.AddNewlyCreatedDBObject(attRef, true);
}
}
}
t.Commit();
}//end using transaction t
}//end using database
}
Message 8 of 9
Anonymous
in reply to: Anonymous

You don't need to call RecordGraphicsModified, just
open the object for write, and that should do it.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005/2006/2007
http://www.acadxtabs.com

"perry" wrote in message news:5164035@discussion.autodesk.com...
Tony Tanzillo wrote:
> Oops. Sorry, The AssertWriteEanbled() trick doesn't work in
> managed code (but does in native ObjectARX).

No problem Tony.
Quite true, I really do not want to do a regen if possible.
It seems that RecordGraphicsModified did not work as expected
because I had the blockref open for READ. When I changed it to
write mode it updated on screen just like I wanted.
Message 9 of 9
Anonymous
in reply to: Anonymous

Thank you for sharing this code.

Roland Feletic


"perry" schrieb im Newsbeitrag
news:5164035@discussion.autodesk.com...
Tony Tanzillo wrote:
> Oops. Sorry, The AssertWriteEanbled() trick doesn't work in
> managed code (but does in native ObjectARX).

No problem Tony.
Quite true, I really do not want to do a regen if possible.
It seems that RecordGraphicsModified did not work as expected
because I had the blockref open for READ. When I changed it to
write mode it updated on screen just like I wanted. This brings
me to a couple other questions I'll do another post on.
In the meantime I posted my finished method below, hopefully
some other .Net newbies will find it useful. I believe its
pretty good & flexible. If anyone has any improvements to it,
Im all ears.
Thanks, Perry



///
/// Inserts an external drawing with or without attributes as a
block into the current drawing.
/// Redefines current block if it already exists.
///

/// null-terminated string that specifies
the name of the input file.
///boolean, if true inserts into current
paperspace, otherwise inserts into modelspace.
///3Dpoint object, insertion point for
block.
public static void insertBlock(string fileName, bool PaperSpace,
Point3d location)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
// If file doesnt exist, bail
if (!File.Exists(fileName))
return;
// Create a block definition name
//the block def name will be same as file name minus path &
extension
string insert = fileName;
//remove path
int pos = 0;
pos = insert.LastIndexOf("\\");
insert = insert.Remove(0, pos + 1);
//remove extension
int len;
len = insert.Length;
if (insert.ToUpper().Contains(".DWG"))
insert = insert.Remove(len - 4, 4);

using (Database db = new Database(false, false))
{
// Read the external drawing file into our temporary
database
db.ReadDwgFile(fileName, FileShare.Read, true, null);
using (Transaction t =
doc.TransactionManager.StartTransaction())
{
//get the block table
BlockTable bt =
(BlockTable)t.GetObject(doc.Database.BlockTableId, OpenMode.ForWrite);
//get the (x)space table record
BlockTableRecord btr;
if (PaperSpace)
btr =
(BlockTableRecord)t.GetObject(bt[BlockTableRecord.PaperSpace],
OpenMode.ForWrite);
else
btr =
(BlockTableRecord)t.GetObject(bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite);
//if the block already exists in the database, redefine
the definition
//and update all the references
if (bt.Has(insert))
{
ObjectId idBTR = doc.Database.Insert(insert, db,
true);
foreach (ObjectId objId in btr)
{
// For each object in the block table record,
cast it to a block reference
DBObject dbObj = t.GetObject(objId,
OpenMode.ForWrite);
BlockReference blkRef = dbObj as
BlockReference;
string blkName = "";
if (blkRef != null)
{
// If it is a block reference, first check
its name to see if its the one we want
BlockTableRecord blkDef =
(BlockTableRecord)t.GetObject(blkRef.BlockTableRecord, OpenMode.ForWrite);
blkName = blkDef.Name.ToString();
if (blkName == insert)
{
blkRef.RecordGraphicsModified(true);
// As per Bobby Jones
//when openmode above was "read" the
RecordGraphicsModified didnt work
}
}
}
}
// Else, create a new definition and insert a new
reference.
else
{
ObjectId idBTR = doc.Database.Insert(insert, db,
true);
// Now create a new block reference
BlockReference bref = new BlockReference(location,
idBTR);
//Add the block reference to the model space
btr.AppendEntity(bref);
//let the transaction know
t.TransactionManager.AddNewlyCreatedDBObject(bref,
true);
//copy attributes from defintion to reference
Entity ent;
BlockTableRecord newbtr =
(BlockTableRecord)t.GetObject(idBTR, OpenMode.ForWrite);
foreach (ObjectId id in newbtr)
{
ent = (Entity)t.GetObject(id,
OpenMode.ForWrite);
if (ent is AttributeDefinition)
{
AttributeDefinition attDef = new
AttributeDefinition();
AttributeReference attRef = new
AttributeReference();
attDef = (AttributeDefinition)ent;
attRef.SetAttributeFromBlock(attDef,
bref.BlockTransform);
bref.AttributeCollection.AppendAttribute(attRef);
t.TransactionManager.AddNewlyCreatedDBObject(attRef,
true);
}
}
}
t.Commit();
}//end using transaction t
}//end using database
}

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