Updating blocks in open non-current drawing

Updating blocks in open non-current drawing

Anonymous
Not applicable
1,697 Views
6 Replies
Message 1 of 7

Updating blocks in open non-current drawing

Anonymous
Not applicable
I'm having two issues. The blocks get updated with the new definitions, but the new versions of the blocks are not being represented ( a regen fixes the problem ), and the new attributes are not showing in the correct location ( a move fixes the problem ).

I thought that if you made the database the working database then the attributes would be updated correctly? This does not seem to be the case when a drawing is opened but not current. How can I fix this?

I have used the draw method on the block references, and they update nicely in the current open drawing, but not in a non-current drawing. I have tried to use the QueueForGraphicsFlush method of the TransactionManager, but that doesn't work unless it is the current document, at least that was the error I got. I tried the Regen method of the Editor, but that only regened the current document. Does anyone have any other suggestions?

Its for Acad '09, and .Net 2.0

Let me know if I didn't provide enough information. Thanks in advance.

{code}
public void Main () {
DocumentCollection DocCol = AcadApp.DocumentManager;
Document Doc = DocCol.MdiActiveDocument;
Database cDb = Doc.Database;
Editor Ed = Doc.Editor;
using ( DocumentLock DocLock = Doc.LockDocument() ) {
using ( CopyBlockDefinitions Dia = new CopyBlockDefinitions() ) {
if ( AcadApp.ShowModalDialog( Dia ) != DialogResult.OK ) return;
foreach ( KeyValuePair> kvp in FinalMappingDict ) {
Database reDb;
Document reOpenDoc = null;
DocumentLock reDocLock = null;
if ( kvp.Value.Count == 0 ) continue;
reOpenDoc = MyUtility.GetDocumentFrom( DocCol, kvp.Key );
if ( reOpenDoc == null ) {
reDb = new Database( false, true );
reDb.ReadDwgFile( kvp.Key, FileShare.ReadWrite, true, null );
}
else {
reDocLock = reOpenDoc.LockDocument();
reDb = reOpenDoc.Database;
}
HostApplicationServices.WorkingDatabase = reDb;
using ( Transaction reTrans = reDb.TransactionManager.StartTransaction() ) {
foreach ( RedefiningBlock rb in kvp.Value ) {
Database deDb;
Document deOpenDoc = null;
DocumentLock deDocLock = null;
ObjectId reObjId = MyUtility.GetNonErasedTableRecordId( reDb.BlockTableId, rb.Name );
if ( reObjId.IsNull ) continue;
deOpenDoc = MyUtility.GetDocumentFrom( DocCol, rb.RedefiningDrawingPath );
if ( deOpenDoc == null ) {
deDb = new Database( false, true );
deDb.ReadDwgFile( rb.RedefiningDrawingPath, FileShare.ReadWrite, true, null );
}
else {
deDocLock = deOpenDoc.LockDocument();
deDb = deOpenDoc.Database;
}
ObjectId deObjId = MyUtility.GetNonErasedTableRecordId( deDb.BlockTableId, rb.RedefiningName );
if ( deObjId.IsNull ) continue;
BlockTableRecord reBlkTblRec = reTrans.GetObject( reObjId, OpenMode.ForWrite ) as BlockTableRecord;
foreach ( ObjectId id in reBlkTblRec ) {
if ( id.IsErased ) continue;
reTrans.GetObject( id, OpenMode.ForWrite ).Erase();
}
using ( Transaction deTrans = deDb.TransactionManager.StartTransaction() ) {
ObjectIdCollection ObjIdCol = new ObjectIdCollection();
BlockTableRecord deBlkTblRec = deTrans.GetObject( deObjId, OpenMode.ForRead ) as BlockTableRecord;
foreach ( ObjectId id in deBlkTblRec ) {
if ( id.IsErased ) continue;
ObjIdCol.Add( id );
}
deDb.WblockCloneObjects( ObjIdCol, reBlkTblRec.ObjectId, new IdMapping(), DuplicateRecordCloning.Ignore, false );
}
reBlkTblRec.DowngradeOpen();
if ( deOpenDoc == null )
deDb.Dispose();
else
deDocLock.Dispose();
MapAttributes( reBlkTblRec.ObjectId, rb.AttributeMapping );
}
reTrans.Commit();
}
HostApplicationServices.WorkingDatabase = cDb;
if ( reOpenDoc == null ) {
reDb.RetainOriginalThumbnailBitmap = true;
reDb.SaveAs( kvp.Key, DwgVersion.Current );
Ed.WriteMessage( "{0} Saved file: {1}", System.Environment.NewLine, reDb.Filename );
reDb.Dispose();
}
else
reDocLock.Dispose();
}
}
}
}
{code}
{code}
void MapAttributes ( ObjectId id, Dictionary mappingDict )
{
using ( Transaction Trans = id.Database.TransactionManager.StartTransaction() ) {
BlockTableRecord BlkTblRec = Trans.GetObject( id, OpenMode.ForRead ) as BlockTableRecord;
foreach ( ObjectId objId in BlkTblRec.GetBlockReferenceIds( true, true ) ) {
if ( objId.IsErased ) continue;
Dictionary Dict = new Dictionary();
BlockReference BlkRef = Trans.GetObject( objId, OpenMode.ForWrite ) as BlockReference;
foreach ( ObjectId attId in BlkRef.AttributeCollection as AttributeCollection ) {
if ( attId.IsErased ) continue;
AttributeReference AttRef = Trans.GetObject( attId, OpenMode.ForWrite ) as AttributeReference;
if ( mappingDict.ContainsKey( AttRef.Tag ) )
Dict.Add( mappingDict[ AttRef.Tag ], AttRef.TextString );
AttRef.Erase();
}
if ( BlkTblRec.HasAttributeDefinitions ) {
foreach ( ObjectId attId in BlkTblRec ) {
if ( attId.IsErased ) continue;
AttributeDefinition AttDef = Trans.GetObject( attId, OpenMode.ForRead ) as AttributeDefinition;
if ( AttDef != null ) {
AttributeReference AttRef = new AttributeReference();
AttRef.SetPropertiesFrom( AttDef );
AttRef.SetAttributeFromBlock( AttDef, BlkRef.BlockTransform );
BlkRef.AttributeCollection.AppendAttribute( AttRef );
if ( Dict.ContainsKey( AttRef.Tag ) )
AttRef.TextString = Dict[ AttRef.Tag ];
Trans.AddNewlyCreatedDBObject( AttRef, true );
}
}
}
BlkRef.DowngradeOpen();
BlkRef.Draw();
}
Trans.Commit();
}
}
{code}
0 Likes
1,698 Views
6 Replies
Replies (6)
Message 2 of 7

Anonymous
Not applicable
Hi Tim. Can't read your code (it was reformatted),
but have might want to have a look at the docs for
the AcDbText::adjustAlignment() method, and its
managed counterpart (AdjustAlignment).

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD
Supporting AutoCAD 2000 through 2011

http://www.acadxtabs.com

Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");

wrote in message news:[email protected]...
I'm having two issues. The blocks get updated with the new definitions, but the
new versions of the blocks are not being represented ( a regen fixes the
problem ), and the new attributes are not showing in the correct location ( a
move fixes the problem ). I thought that if you made the database the working
database then the attributes would be updated correctly? This does not seem to
be the case when a drawing is opened but not current. How can I fix this? I have
used the draw method on the block references, and they update nicely in the
current open drawing, but not in a non-current drawing. I have tried to use the
QueueForGraphicsFlush method of the TransactionManager, but that doesn't work
unless it is the current document, at least that was the error I got. I tried
the Regen method of the Editor, but that only regened the current document. Does
anyone have any other suggestions? Its for Acad '09, and .Net 2.0 Let me know if
I didn't provide enough information. Thanks in advance. {code} public void Main
() { DocumentCollection DocCol = AcadApp.DocumentManager; Document Doc =
DocCol.MdiActiveDocument; Database cDb = Doc.Database; Editor Ed = Doc.Editor;
using ( DocumentLock DocLock = Doc.LockDocument() ) { using (
CopyBlockDefinitions Dia = new CopyBlockDefinitions() ) { if (
AcadApp.ShowModalDialog( Dia ) != DialogResult.OK ) return; foreach (
KeyValuePair> kvp in FinalMappingDict ) { Database reDb; Document reOpenDoc =
null; DocumentLock reDocLock = null; if ( kvp.Value.Count == 0 ) continue;
reOpenDoc = MyUtility.GetDocumentFrom( DocCol, kvp.Key ); if ( reOpenDoc ==
null ) { reDb = new Database( false, true ); reDb.ReadDwgFile( kvp.Key,
FileShare.ReadWrite, true, null ); } else { reDocLock =
reOpenDoc.LockDocument(); reDb = reOpenDoc.Database; }
HostApplicationServices.WorkingDatabase = reDb; using ( Transaction reTrans =
reDb.TransactionManager.StartTransaction() ) { foreach ( RedefiningBlock rb in
kvp.Value ) { Database deDb; Document deOpenDoc = null; DocumentLock deDocLock =
null; ObjectId reObjId = MyUtility.GetNonErasedTableRecordId( reDb.BlockTableId,
rb.Name ); if ( reObjId.IsNull ) continue; deOpenDoc =
MyUtility.GetDocumentFrom( DocCol, rb.RedefiningDrawingPath ); if ( deOpenDoc ==
null ) { deDb = new Database( false, true ); deDb.ReadDwgFile(
rb.RedefiningDrawingPath, FileShare.ReadWrite, true, null ); } else { deDocLock
= deOpenDoc.LockDocument(); deDb = deOpenDoc.Database; } ObjectId deObjId =
MyUtility.GetNonErasedTableRecordId( deDb.BlockTableId, rb.RedefiningName ); if
( deObjId.IsNull ) continue; BlockTableRecord reBlkTblRec = reTrans.GetObject(
reObjId, OpenMode.ForWrite ) as BlockTableRecord; foreach ( ObjectId id in
reBlkTblRec ) { if ( id.IsErased ) continue; reTrans.GetObject( id,
OpenMode.ForWrite ).Erase(); } using ( Transaction deTrans =
deDb.TransactionManager.StartTransaction() ) { ObjectIdCollection ObjIdCol = new
ObjectIdCollection(); BlockTableRecord deBlkTblRec = deTrans.GetObject( deObjId,
OpenMode.ForRead ) as BlockTableRecord; foreach ( ObjectId id in deBlkTblRec )
{ if ( id.IsErased ) continue; ObjIdCol.Add( id ); } deDb.WblockCloneObjects(
ObjIdCol, reBlkTblRec.ObjectId, new IdMapping(), DuplicateRecordCloning.Ignore,
false ); } reBlkTblRec.DowngradeOpen(); if ( deOpenDoc == null ) deDb.Dispose();
else deDocLock.Dispose(); MapAttributes( reBlkTblRec.ObjectId,
rb.AttributeMapping ); } reTrans.Commit(); }
HostApplicationServices.WorkingDatabase = cDb; if ( reOpenDoc == null ) {
reDb.RetainOriginalThumbnailBitmap = true; reDb.SaveAs( kvp.Key,
DwgVersion.Current ); Ed.WriteMessage( "{0} Saved file: {1}",
System.Environment.NewLine, reDb.Filename ); reDb.Dispose(); } else
reDocLock.Dispose(); } } } } {code} {code} void MapAttributes ( ObjectId id,
Dictionary mappingDict ) { using ( Transaction Trans =
id.Database.TransactionManager.StartTransaction() ) { BlockTableRecord BlkTblRec
= Trans.GetObject( id, OpenMode.ForRead ) as BlockTableRecord; foreach (
ObjectId objId in BlkTblRec.GetBlockReferenceIds( true, true ) ) { if (
objId.IsErased ) continue; Dictionary Dict = new Dictionary(); BlockReference
BlkRef = Trans.GetObject( objId, OpenMode.ForWrite ) as BlockReference; foreach
( ObjectId attId in BlkRef.AttributeCollection as AttributeCollection ) { if (
attId.IsErased ) continue; AttributeReference AttRef = Trans.GetObject( attId,
OpenMode.ForWrite ) as AttributeReference; if ( mappingDict.ContainsKey(
AttRef.Tag ) ) Dict.Add( mappingDict[ AttRef.Tag ], AttRef.TextString );
AttRef.Erase(); } if ( BlkTblRec.HasAttributeDefinitions ) { foreach ( ObjectId
attId in BlkTblRec ) { if ( attId.IsErased ) continue; AttributeDefinition
AttDef = Trans.GetObject( attId, OpenMode.ForRead ) as AttributeDefinition; if
( AttDef != null ) { AttributeReference AttRef = new AttributeReference();
AttRef.SetPropertiesFrom( AttDef ); AttRef.SetAttributeFromBlock( AttDef,
BlkRef.BlockTransform ); BlkRef.AttributeCollection.AppendAttribute( AttRef );
if ( Dict.ContainsKey( AttRef.Tag ) ) AttRef.TextString = Dict[ AttRef.Tag ];
Trans.AddNewlyCreatedDBObject( AttRef, true ); } } } BlkRef.DowngradeOpen();
BlkRef.Draw(); } Trans.Commit(); } } {code}
0 Likes
Message 3 of 7

Anonymous
Not applicable
Thanks Tony. I'll post back after some experimentation.

Is there a way to post code so that both web/newsreader people can see it?
0 Likes
Message 4 of 7

Hallex
Advisor
Advisor
Select 'Plain Text' tab in the message box and
put your code between the code tags (curled brackets):

{ code } your code goes here { code } <-- remove spaces

do not use backslash in the last tag as usual

~'J'~
_____________________________________
C6309D9E0751D165D0934D0621DFF27919
0 Likes
Message 5 of 7

Anonymous
Not applicable
That appears to be how I did it J, so I'm not sure why it got messed up in the first place then. I'll just post a text file incase someone wants to see the code better.

Tony,

I tried to use the AdjustAlignment method on the AttributeReference objects, but that didn't seem to help. The database is the current working database, like the help says it has to be, so I'm not sure why it didn't work for me. I tried placing it before and after my call to AddNewlyCreatedDBObject on my transaction.

I'll see if I can find anything else that might help.
0 Likes
Message 6 of 7

Anonymous
Not applicable
I was afraid of that.

In short, the only way to workaround this problem is to
use native ObjectARX to switch the 'Current' document,
because there is no managed wrapper for doing that.

For databases that are not open in the editor, setting
the database to the current working database as you
are doing, is enough, but for documents that are open
in AutoCAD but not the active document when their
database is modified, there is another requirement,
which is that the associated document must be set to
the 'Current' document when the change occurs.

You can see this post on AUGI for a discussion on
updating graphics in open, non-active documents, and
a C++/CLI wrapper for the native ObjectARX code that
must be used:

http://forums.augi.com/showthread.php?t=107464

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD
Supporting AutoCAD 2000 through 2011

http://www.acadxtabs.com

Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");

wrote in message news:[email protected]...
That appears to be how I did it J, so I'm not sure why it got messed up in the
first place then. I'll just post a text file incase someone wants to see the
code better.

Tony,

I tried to use the AdjustAlignment method on the AttributeReference objects, but
that didn't seem to help. The database is the current working database, like
the help says it has to be, so I'm not sure why it didn't work for me. I tried
placing it before and after my call to AddNewlyCreatedDBObject on my
transaction.

I'll see if I can find anything else that might help.
0 Likes
Message 7 of 7

Anonymous
Not applicable
Thanks for the information and the link Tony. I'll see how I want to proceed.
0 Likes