using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
#pragma warning disable 0618
namespace AcadTest
{
public class DynBlockTest
{
public static RXClass AttDefRXCLass = RXClass.GetClass(typeof(AttributeDefinition));
static int counter = 0;
[CommandMethod("TestDynBlockBackgroundPaste1")]
public void InsertAndSettings()
{
Document adoc = Application.DocumentManager.MdiActiveDocument;
Editor ed = adoc.Editor;
Database db = adoc.Database;
PromptEntityOptions entOpts = new PromptEntityOptions("\nSelect dynamic block: ");
entOpts.SetRejectMessage("This is not block!");
entOpts.AddAllowedClass(typeof(BlockReference), true);
PromptEntityResult entRes = ed.GetEntity(entOpts);
if (entRes.Status != PromptStatus.OK) return;
ObjectId bTabRecId = ObjectId.Null;
Dictionary<string, object> blkDynProps = new Dictionary<string, object>();
Dictionary<string, string> attribs = new Dictionary<string, string>();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockReference bref = tr.GetObject
(entRes.ObjectId, OpenMode.ForRead) as BlockReference;
if (bref.IsDynamicBlock)
{
bTabRecId = bref.DynamicBlockTableRecord;
foreach (DynamicBlockReferenceProperty dynProp
in bref.DynamicBlockReferencePropertyCollection)
{
blkDynProps[dynProp.PropertyName] = dynProp.Value;
}
foreach (ObjectId attRefId in bref.AttributeCollection)
{
AttributeReference attRef = tr.GetObject
(attRefId, OpenMode.ForRead) as AttributeReference;
attribs[attRef.Tag] = attRef.TextString;
}
}
tr.Commit();
}
if (bTabRecId.IsNull || blkDynProps.Count == 0)
{
ed.WriteMessage("\nBlock without dynamic props! Exit.");
return;
}
if (attribs.Count == 0)
{
ed.WriteMessage("\nBlock without attribs! Exit.");
return;
}
string dir = Path.GetDirectoryName(adoc.Name);
PromptSaveFileOptions saveFileOpt = new PromptSaveFileOptions("Drawing for save: ");
saveFileOpt.Filter = "Drawing (*.dwg)|*.dwg";
saveFileOpt.InitialDirectory = dir;
saveFileOpt.InitialFileName = $"DynBlkTarget{++counter}.dwg";
PromptFileNameResult saveFileRes = ed.GetFileNameForSave(saveFileOpt);
string newFilePath = saveFileRes.StringResult;
PromptKeywordOptions keyOpts = new PromptKeywordOptions("\nUse transaction?");
keyOpts.Keywords.Add("Yes");
keyOpts.Keywords.Add("No");
keyOpts.Message += keyOpts.Keywords.GetDisplayString(true);
PromptResult keyRes = ed.GetKeywords(keyOpts);
if (keyRes.Status != PromptStatus.OK) return;
bool useTrans = keyRes.StringResult == "Yes";
using (Database newDb = new Database(true, false))
{
ObjectIdCollection ids = new ObjectIdCollection();
ids.Add(bTabRecId);
IdMapping mapping = new IdMapping();
newDb.WblockCloneObjects(ids, newDb.BlockTableId,
mapping, DuplicateRecordCloning.Replace, false);
ObjectId newBTabRecId = mapping[bTabRecId].Value;
Transaction tr = useTrans ?
newDb.TransactionManager.StartTransaction()
: newDb.TransactionManager.StartOpenCloseTransaction();
ObjectId bRefId;
using (tr)
{
BlockReference blkRef = new BlockReference(Point3d.Origin, newBTabRecId);
ObjectId mSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(newDb);
BlockTableRecord mSpace = tr.GetObject
(mSpaceId, OpenMode.ForWrite) as BlockTableRecord;
bRefId = mSpace.AppendEntity(blkRef);
tr.AddNewlyCreatedDBObject(blkRef, true);
BlockTableRecord blkRec = tr.GetObject
(newBTabRecId, OpenMode.ForRead) as BlockTableRecord;
foreach (ObjectId attDefId in blkRec)
{
if (!attDefId.ObjectClass.Equals(AttDefRXCLass)) continue;
AttributeDefinition attDef = tr.GetObject
(attDefId, OpenMode.ForRead) as AttributeDefinition;
if (!attDef.Constant)
{
AttributeReference attRef = new AttributeReference();
attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
if (!attDef.HasFields
&& attribs.ContainsKey(attDef.Tag))
{
attRef.TextString = attribs[attDef.Tag];
}
blkRef.AttributeCollection.AppendAttribute(attRef);
tr.AddNewlyCreatedDBObject(attRef, true);
// Атрибут должен быть закрыт перед
// присвоением динамических свойств блоку
if (!useTrans) attRef.Close();
}
}
// BlockTableRecord нашего блока должна быть закрыта
// перед присвоением динамических свойств блоку
if (!useTrans) blkRec.Close();
DynamicBlockReferencePropertyCollection dynProps =
blkRef.DynamicBlockReferencePropertyCollection;
foreach (DynamicBlockReferenceProperty dynProp in dynProps)
{
KeyValuePair<string, object> propData = blkDynProps
.FirstOrDefault(item => item.Key.Equals
(dynProp.PropertyName, StringComparison.InvariantCultureIgnoreCase));
if (propData.Value != null && dynProp.PropertyName != "Origin")
{
try
{
dynProp.Value = propData.Value;
}
catch (System.Exception ex)
{
Application.DocumentManager.MdiActiveDocument.
Editor.WriteMessage("\n{0}", ex);
}
}
}
tr.Commit();
}
// Дополнительная обработка атрибутов, ссылающихся
// полем на значения динпараметров блока
ObjectId bTabRecId1;
ObjectId[] attRefIds;
Matrix3d blkTransform;
using (BlockReference blkRef = bRefId.Open(OpenMode.ForRead) as BlockReference)
{
bTabRecId1 = blkRef.BlockTableRecord;
attRefIds = blkRef.AttributeCollection.Cast<ObjectId>().ToArray();
blkTransform = blkRef.BlockTransform;
}
Dictionary<string, ObjectId> attDefDict = new Dictionary<string, ObjectId>();
using (BlockTableRecord blkTabRec = bTabRecId1.Open(OpenMode.ForRead) as BlockTableRecord)
{
ObjectId[] attDefIds = blkTabRec.Cast<ObjectId>().Where(id => id.ObjectClass.Equals(AttDefRXCLass)).ToArray();
foreach (ObjectId attDefId in attDefIds)
{
using (AttributeDefinition attDef = attDefId.Open(OpenMode.ForRead) as AttributeDefinition)
{
attDefDict[attDef.Tag] = attDefId;
}
}
}
foreach (ObjectId attRefId in attRefIds)
{
using (AttributeReference attRef = attRefId.Open(OpenMode.ForRead) as AttributeReference)
{
if (attRef.HasFields && attDefDict.ContainsKey(attRef.Tag))
{
using (AttributeDefinition attDef = attDefDict[attRef.Tag].Open(OpenMode.ForRead) as AttributeDefinition)
{
attRef.UpgradeOpen();
attRef.SetAttributeFromBlock(attDef, blkTransform);
attRef.DowngradeOpen();
}
}
}
}
newDb.SaveAs(newFilePath, DwgVersion.Current);
}
Document newDoc = Application.DocumentManager.Open(newFilePath, false);
Application.DocumentManager.MdiActiveDocument = newDoc;
}
}
}