using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Linq;
namespace AcadTest
{
public class ObjectLinkTest
{
const string HardPointerRecordName = "HardPointer";
const string SoftPointerRecordName = "SoftPointer";
/*
* Handle не пересчитываются автоматически
* и хранятся в виде строки
const string HandleRecordName = "Handle";
* Ownerships коды не записываются в Xrecord
const string HardOwnershipRecordName = "HardOwner";
const string SoftOwnershipRecordName = "SoftOwner";
*/
[CommandMethod("AddSoftPointerLink")]
public void AddSoftPointerLink()
{
AddLink(DxfCode.SoftPointerId);
}
[CommandMethod("AddHardPointerLink")]
public void AddHardPointerLink()
{
AddLink(DxfCode.HardPointerId);
}
[CommandMethod("GetSoftPointerLinkedObject")]
public void GetSoftPointerLinkedObject()
{
SelectLinked(DxfCode.SoftPointerId);
}
[CommandMethod("GetHardPointerLinkedObject")]
public void GetHardPointerLinkedObject()
{
SelectLinked(DxfCode.HardPointerId);
}
static void AddLink(DxfCode code)
{
SupportMethods.InitializeVars(out Document adoc,
out Editor ed, out Database db);
if (!ed.SelectEntity(out ObjectId firstId, "\nSelect object for write: ")
|| !ed.SelectEntity(out ObjectId secondId, "\nSelect object for reference: "))
return;
WriteObjectIdToDict(firstId, secondId, code);
}
static void SelectLinked(DxfCode code)
{
SupportMethods.InitializeVars(out Document adoc,
out Editor ed, out Database db);
if (!ed.SelectEntity(out ObjectId objId, "\nSelect object: "))
return;
ObjectId linkedId = GetObjectIdFromDict(objId, code);
if (linkedId.IsValid
&& linkedId.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(Entity))))
{
ed.SetImpliedSelection(new[] { linkedId });
}
}
static void WriteObjectIdToDict(ObjectId objId, ObjectId writedId, DxfCode code)
{
ObjectId dictId;
#pragma warning disable CS0618 // Type or member is obsolete
using (DBObject obj = objId.Open(OpenMode.ForRead))
#pragma warning restore CS0618 // Type or member is obsolete
{
dictId = obj.ExtensionDictionary;
if (!dictId.IsValid)
{
obj.UpgradeOpen();
obj.CreateExtensionDictionary();
dictId = obj.ExtensionDictionary;
}
}
#pragma warning disable CS0618 // Type or member is obsolete
using (DBDictionary dict = dictId.Open(OpenMode.ForWrite) as DBDictionary)
#pragma warning restore CS0618 // Type or member is obsolete
using (Xrecord xrec = new Xrecord())
using (ResultBuffer resBuff = new ResultBuffer(new TypedValue((int)code, writedId)))
{
string entryName = GetLinkRecordName(code);
if (dict.Contains(entryName))
{
dict.Remove(entryName);
}
xrec.Data = resBuff;
dict.SetAt(entryName, xrec);
}
}
static ObjectId GetObjectIdFromDict(ObjectId objId, DxfCode code)
{
ObjectId dictId = ObjectId.Null;
#pragma warning disable CS0618 // Type or member is obsolete
using (DBObject obj = objId.Open(OpenMode.ForRead))
#pragma warning restore CS0618 // Type or member is obsolete
{
dictId = obj.ExtensionDictionary;
}
string entryName = GetLinkRecordName(code);
if (!dictId.IsValid) return ObjectId.Null;
ObjectId xrecId = ObjectId.Null;
#pragma warning disable CS0618 // Type or member is obsolete
using (DBDictionary dict = dictId.Open(OpenMode.ForRead) as DBDictionary)
#pragma warning restore CS0618 // Type or member is obsolete
{
if (dict.Contains(entryName))
{
xrecId = dict.GetAt(entryName);
}
}
if (!xrecId.IsValid) return ObjectId.Null;
#pragma warning disable CS0618 // Type or member is obsolete
using (Xrecord xrec = xrecId.Open(OpenMode.ForRead) as Xrecord)
#pragma warning restore CS0618 // Type or member is obsolete
using (ResultBuffer resBuf = xrec.Data)
{
TypedValue[] tVals;
if (resBuf != null && (tVals = resBuf.AsArray()).Length > 0)
{
object val = tVals.FirstOrDefault
(item => item.TypeCode == (int)code).Value;
if (val != null && val is ObjectId id)
{
return id;
}
}
}
return ObjectId.Null;
}
static string GetLinkRecordName(DxfCode code)
{
switch (code)
{
case DxfCode.HardPointerId:
return HardPointerRecordName;
case DxfCode.SoftPointerId:
return SoftPointerRecordName;
default:
throw new ArgumentException("Undefinded dxf code");
}
}
}
static class Support
{
public static void InitializeVars(out Document adoc, out Editor ed, out Database db)
{
adoc = Application.DocumentManager.MdiActiveDocument;
ed = adoc.Editor;
db = adoc.Database;
}
public static bool SelectEntity(this Editor ed, out ObjectId id, string msg = "\nSelect entity: ")
{
PromptEntityResult entRes = ed.GetEntity(msg);
id = entRes.ObjectId;
return entRes.Status == PromptStatus.OK;
}
}
}