Тема: Автоматическое размещение объекта на нужном слое
Исходники взяты отсюда https://sites.google.com/site/bushmansn … ox/stati/x
Автору огромное спасибо.
Немного изменено под свои нужды. Но...
При подгрузке DLL все работает замечательно.
При открытии или создании нового файла происходит Fatal Error и акад захлопывается. В чем проблема не пойму.
using Autodesk.AutoCAD.ApplicationServices; using acad = Autodesk.AutoCAD.ApplicationServices.Application; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Colors; using System.Linq; using System.Collections; using System.Collections.Generic; using System.Xml.Linq; using Autodesk.AutoCAD.Runtime; using System.IO; using System; using Autodesk.AutoCAD.EditorInput; using System.Text; using System.Threading.Tasks; using Autodesk.AutoCAD.Geometry; namespace Bushman.AutoCAD.Samples { public class Class1 : IExtensionApplication { //Словарь, в котором каждой команде сопоставлен свой слой Dictionary<string, LayerTableRecord> dict; //Объекты общих настроек и настроек слоёв XElement settings, layersInfo; //Полное имя каталога, в котором находится данная сборка string currentDir; //Имя слоя, который был текущим до того, как была выполнена команда string previousLayerName; public void Initialize() { //Получаем путь к каталогу, в котором находится данная сборка currentDir = new FileInfo(this.GetType().Assembly.Location).DirectoryName; //Считываем данные файла настроек settings = XElement.Load(Path.Combine(currentDir, "Settings.xml")); //Считываем информацию о локализации ресурсов, установленной пользователем. string localization = settings.Element("CurrentResourcesLocalization").Value.Trim(); //На основании указанной локализации, определяем, какой файл описания слоёв следует использовать в работе layersInfo = localization == string.Empty ? XElement.Load(Path.Combine(currentDir, "Layers.xml")) : XElement.Load(Path.Combine(currentDir, string.Format("Layers.{0}.xml", localization))); //Создаём словарь, в котором каждой интересующей нас команде сопоставляем нужный слой, согласно указанной локализации dict = new Dictionary<string, LayerTableRecord>(); //получаем таблицу типов линий Document dwg = acad.DocumentManager.MdiActiveDocument; Database db = dwg.Database; LinetypeTable LineTypeTblRec; using (Transaction t = db.TransactionManager.StartTransaction()) { //открытие таблицы типов линий для чтения LineTypeTblRec = t.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable; t.Commit(); } //Заполняем словарь данными foreach (XElement layer in layersInfo.Elements("Layer")) { LayerTableRecord lt = new LayerTableRecord(); lt.Name = layer.Element("Name").Value.Trim(); lt.Description = layer.Element("Description").Value.Trim(); lt.LineWeight = (LineWeight)Enum.Parse(typeof(LineWeight), layer.Element("LineWeight").Value.Trim()); short color; color = Convert.ToInt16(layer.Element("Color").Value.Trim()); lt.Color = Color.FromColorIndex(ColorMethod.ByAci, color); string lineTypeName; lineTypeName = layer.Element("LineType").Value.Trim(); if (LineTypeTblRec.Has(lineTypeName)) lt.LinetypeObjectId = LineTypeTblRec[lineTypeName]; dict.Add(layer.Attribute("Commands").Value.Trim(), lt); } //Подписываемся на событие открытия документа Application.DocumentManager.DocumentCreated += new DocumentCollectionEventHandler(DocumentManager_DocumentCreated); //Подготавливаем текущий чертёж MainMethod(); } public void Terminate() { } private void MainMethod() { Document dwg = acad.DocumentManager.MdiActiveDocument; Database db = dwg.Database; #region Подписка на события обработки команд dwg.CommandWillStart += new CommandEventHandler(acDoc_CommandWillStart); dwg.CommandCancelled += new CommandEventHandler(acDoc_CommandEFC); dwg.CommandEnded += new CommandEventHandler(acDoc_CommandEFC); dwg.CommandFailed += new CommandEventHandler(acDoc_CommandEFC); #endregion //начало транзакции using (Transaction t = db.TransactionManager.StartTransaction()) { //открытие таблицы слоев для чтения LayerTable layersTable; layersTable = t.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; //проверка, есть ли уже слои с таким же именем foreach (KeyValuePair<string, LayerTableRecord> i in dict) { if (!layersTable.Has(i.Value.Name)) { layersTable.UpgradeOpen(); layersTable.Add(i.Value); t.AddNewlyCreatedDBObject(i.Value, true); } } t.Commit(); } } //создание документа private void DocumentManager_DocumentCreated(object sender, DocumentCollectionEventArgs e) { MainMethod(); } //начало команды private void acDoc_CommandWillStart(object sender, CommandEventArgs e) { //установка текущего слоя для размеров, текста и т.д... previousLayerName = (string)acad.GetSystemVariable("CLAYER"); foreach (KeyValuePair<string, LayerTableRecord> item in dict) { if (item.Key.Split(';').Contains(e.GlobalCommandName)) { acad.SetSystemVariable("CLAYER", dict[item.Key].Name); break; } } } //конец, ошибка, отмена команды private void acDoc_CommandEFC(object sender, CommandEventArgs e) { //восстановление текущего слоя foreach (KeyValuePair<string, LayerTableRecord> item in dict) { if (item.Key.Split(';').Contains(e.GlobalCommandName)) { acad.SetSystemVariable("CLAYER", previousLayerName); break; } } } } }
Путем практических исключений вывелось что проблема вот в этой строке метода MainMethod()
t.AddNewlyCreatedDBObject(i.Value, true);
Может база не готова к моменту когда меиод начинает работу... не знаю.
Просьба оказать посильную помощь кто может.
Autocad 2014 x64 Win7x64