Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: bakaIIHX от 19-10-2014, 17:09:17

Название: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 19-10-2014, 17:09:17
Доброго времени суток. Возможно ли сохранить свойства примитива и его модификации в отдельный файл с расширением, например, .txt?
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 19-10-2014, 19:03:56
Возможно ли сохранить свойства примитива и его модификации в отдельный файл с расширением, например, .txt?
Возможно. Хотя нужно понимать какие именно свойства. Лучше всего (на мой взгляд) сохранять в формате DXF (https://ru.wikipedia.org/wiki/DXF). Он хранить все свойства примитива.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 19-10-2014, 23:35:05
Возможно. Хотя нужно понимать какие именно свойства. Лучше всего (на мой взгляд) сохранять в формате DXF. Он хранить все свойства примитива.

Отлично, у Вас случайно нет примера как это делается?
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 19-10-2014, 23:36:39
Хотя нужно понимать какие именно свойства.


Свойства примитива, например все что выдается через _LIST, просто я не знаю как выразиться.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 20-10-2014, 00:24:57
По тем данным, которые выдаёт команда _LIST, невозможно создать примитив, свойства которого эта команда выдает. Поэтому уточни какова цель записи свойств примитива в текстовый файл.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 20-10-2014, 00:31:30
Отлично, у Вас случайно нет примера как это делается?
А вот это интересный вопрос. В AutoCAD .NET API нет средств работы с DXF. Но много лет назад я делал такой код, использующий вызов P/Invoke acdbEntGet (это функция из ObjectARX):
Код - C# [Выбрать]
  1. //-------------------------------------------------
  2. // В AutoCAD 2005...2006 работать не будет из-за
  3. // ограничений на содержимое ResultBuffer!
  4. //-------------------------------------------------
  5. using System;
  6. using System.Runtime.InteropServices;
  7. using Autodesk.AutoCAD.Runtime;
  8. using Autodesk.AutoCAD.ApplicationServices;
  9. using Autodesk.AutoCAD.DatabaseServices;
  10. using Autodesk.AutoCAD.EditorInput;
  11. using AcRx = Autodesk.AutoCAD.Runtime;
  12. using AcEd = Autodesk.AutoCAD.EditorInput;
  13. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  14. using AcAp = Autodesk.AutoCAD.ApplicationServices;
  15. [assembly: CommandClass(typeof(Rivilis.EntGet))]
  16. namespace Rivilis
  17. {
  18.   public class EntGet
  19.   {
  20.     [System.Security.SuppressUnmanagedCodeSecurity]
  21.     [DllImport("acdb17.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z")]
  22.     private static extern int acdbGetAdsName(long[] name, ObjectId objId);
  23.     [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acdbEntGet")]
  24.     private static extern System.IntPtr acdbEntGet(long[] name);
  25.     [CommandMethod("DXFGet")]
  26.     static public void DXFGet()
  27.     {
  28.       AcEd.Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
  29.       AcEd.PromptEntityOptions entityOpts = new AcEd.PromptEntityOptions("\nSelect entity: ");
  30.       AcEd.PromptEntityResult rc = ed.GetEntity(entityOpts);
  31.       if (rc.Status == AcEd.PromptStatus.OK)
  32.       {
  33.         long[] ent = new long[] { 0, 0 };
  34.         acdbGetAdsName(ent, rc.ObjectId);
  35.         System.IntPtr rb = acdbEntGet(ent);
  36.         AcDb.ResultBuffer dxflist = AcRx.DisposableWrapper.Create(typeof(AcDb.ResultBuffer), rb, true) as AcDb.ResultBuffer;
  37.         if (dxflist != null)
  38.         {
  39.           foreach (TypedValue val in dxflist)
  40.           {
  41.             ed.WriteMessage("\n({0} . {1})", val.TypeCode, val.Value.ToString());
  42.           }
  43.         }
  44.       }
  45.     }
  46.   }
  47. }
Думаю что без переделок в AutoCAD 2012 (особенно x64) работать не будет. Нужно экспериментировать.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 20-10-2014, 00:41:00
Можно пойти и другим путём - использование Reflection: http://spiderinnet1.typepad.com/blog/2012/01/using-c-to-print-out-properties-of-autocad-net-dbobject-or-entity.html
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 03-11-2014, 14:57:15
Можно пойти и другим путём - использование Reflection

Прочитал про Reflection, но можно ли через него получить все свойства? Можно через Reflection получить расширенные данные?
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 03-11-2014, 18:31:19
но можно ли через него получить все свойства?
Проблема может возникнуть только для тех свойств, которые реализованы в виде методов. Тут нужно будет знать какие параметры передавать.
Можно через Reflection получить расширенные данные?
Можно. Но как раз для получения расширенных данных Reflection совершенно не нужен. Для получения расширенных данных есть свойство XData и метод GetXDataForApplication (если нужно получить расширенные данные для конкретного имени приложения).
Примеры здесь:
http://adn-cis.org/ispolzovanie-.netapidlya-dobavleniya-i-udaleniya-rasshirennyix-dannyix.html
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 03-11-2014, 18:42:32
Примеры здесь:
Спасибо.
 
Тут нужно будет знать какие параметры передавать.
Если честно, немного не понимаю.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 03-11-2014, 18:48:54
Если честно, немного не понимаю.
Самый простой пример. Свойство с именем XData и метод с именем GetXDataForApplication. Свойство вызывается по имени, а методу нужно передать еще и параметр (в данном случае строковый параметр с именем приложения).
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 04-11-2014, 00:20:06
Самый простой пример. Свойство с именем XData и метод с именем GetXDataForApplication. Свойство вызывается по имени, а методу нужно передать еще и параметр (в данном случае строковый параметр с именем приложения).
Ну более или менее понятно. Еще вопрос. А возможно ли сделать по типу программы с кругом, который рисовался после действия пользователя?
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 04-11-2014, 00:26:55
А возможно ли сделать по типу программы с кругом, который рисовался после действия пользователя?
Переведи.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 04-11-2014, 00:29:56
Поэтому уточни какова цель записи свойств примитива в текстовый файл.

Мне нужно что бы свойства примитива, а именно координаты, цвет, длина, ширина и т.д. записывался отдельно в файл и его можно было просто прочитать.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 04-11-2014, 00:42:00
Переведи.

http://adn-cis.org/forum/index.php?topic=971.msg4262#msg4262

Просто Вы уже приводили пример, когда круг появлялся во время работы пользователя. С этой программой нужно сделать нечто похожее. Что бы не было необходимости каждый раз указывать примитив, свойства которого нужно сохранить.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 04-11-2014, 00:42:20
Мне нужно что бы свойства примитива, а именно координаты, цвет, длина, ширина и т.д. записывался отдельно в файл и его можно было просто прочитать.
Ты видимо не понимаешь, что указанные тобой свойства есть далеко не у всех примитивов.
Например координаты у полилинии - это координаты её вершин. А у круга - это что? А у текста? А что такое ширина?
Вообще-то я давал уже пример того, как можно вывести все свойства примитива: http://spiderinnet1.typepad.com/blog/2012/01/using-c-to-print-out-properties-of-autocad-net-dbobject-or-entity.html
В этом примере они выводятся в командную строку AutoCAD, а ты можешь вывести их туда, куда считаешь нужным.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 04-11-2014, 00:47:34
Просто Вы уже приводили пример, когда круг появлялся во время работы пользователя. С этой программой нужно сделать нечто похожее. Что бы не было необходимости каждый раз указывать примитив, свойства которого нужно сохранить.
Извини, но я снова ничего не понял. Потрудись, пожалуйста, изложить свою мысль таким образом, чтобы я понял чего ты добиваешься. Объединить ту программу и вывод свойств примитива во внешний файл в фоновом режиме не получится. Как ты себе это представляешь? Программа сканирует весь чертеж и в фоне выводит свойства всех примитивов? Тогда AutoCAD будет постоянно занят этой работой и пользователь не сможет с ним работать. По длительности это будет значительно (в разы, если не в десятки раз) дольше, чем операция сохранения файла.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 04-11-2014, 01:06:48
Извини, но я снова ничего не понял.

Вы давали пример программы, она реагировала на работу пользователя. Каждый раз, когда он совершал какое либо действие программа рисовала примитив. Я хотел в этой программе использовать тоже самое. Просто очень неудобно каждый раз вручную указывать, хотелось бы немного автоматизировать.
Я только сейчас подумал как сильно это загрузит программу. В идеале нужна программа, которой безразлично, что именно нарисовал пользователь,но я даже представить себе не могу возможно ли это.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 04-11-2014, 01:21:42
Извини, но дальше я буду отвечать только на четко поставленные тобой вопросы, так как объяснить что ты хочешь так, чтобы я это понял, ты не можешь. Соответственно я не могу тебе помочь. Увы.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 07-11-2014, 02:18:58
Извини, но дальше я буду отвечать только на четко поставленные тобой вопросы, так как объяснить что ты хочешь так, чтобы я это понял, ты не можешь. Соответственно я не могу тебе помочь. Увы.

Можно ли использовать ManagementEventWatcher, что бы отследить событие модификации объекта?
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 07-11-2014, 09:17:56
Можно ли использовать ManagementEventWatcher, что бы отследить событие модификации объекта?
Нет. Для этой цели есть другие события в AutoCAD .NET API. Посмотри в ObjectARX SDK Documents: Autodesk.AutoCAD.DatabaseServices Namespace > DBObject Class > DBObject Events
Ну и описание событий класса Database:
Код - C# [Выбрать]
  1. Database.ObjectAppended  
  2. Database.ObjectErased  
  3. Database.ObjectModified  
  4. Database.ObjectOpenedForModify  
  5. Database.ObjectReappended  
  6. Database.ObjectUnappended
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 12-11-2014, 14:47:26
Нет. Для этой цели есть другие события в AutoCAD .NET API. Посмотри в ObjectARX SDK Documents: Autodesk.AutoCAD.DatabaseServices Namespace > DBObject Class > DBObject Events
Ну и описание событий класса Database:

Код - C# [Выбрать]
  1. #region Namespaces
  2.  
  3. using System;
  4. using System.Text;
  5. using System.Linq;
  6. using System.Xml;
  7. using System.Reflection;
  8. using System.ComponentModel;
  9. using System.Collections;
  10. using System.Collections.Generic;
  11. using System.Windows;
  12. using System.Windows.Media.Imaging;
  13. using System.Windows.Forms;
  14. using System.Diagnostics;
  15. using System.Drawing;
  16. using System.IO;
  17. using Autodesk.AutoCAD.ApplicationServices;
  18. using Autodesk.AutoCAD.DatabaseServices;
  19. using Autodesk.AutoCAD.Runtime;
  20. using Autodesk.AutoCAD.EditorInput;
  21. using Autodesk.AutoCAD.Geometry;
  22. using Autodesk.AutoCAD.Windows;
  23. using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
  24. using AcadDocument = Autodesk.AutoCAD.ApplicationServices.Document;
  25. using AcadWindows = Autodesk.AutoCAD.Windows;
  26.  
  27. #endregion
  28.  
  29. namespace AcadNetAddinWizard_Namespace
  30. {
  31.  
  32.     public class TestCommands
  33.     {
  34.         Database db = HostApplicationServices.WorkingDatabase;
  35.         Editor ed = AcadApplication.DocumentManager.MdiActiveDocument.Editor;
  36.         void Dump(DBObject obj)
  37.         {
  38.             string msg = string.Format("Properties of the {0} with handle {1}:\n", obj.GetType().Name, obj.Handle);
  39.  
  40.             PropertyInfo[] piArr = obj.GetType().GetProperties();
  41.             foreach (PropertyInfo pi in piArr)
  42.             {
  43.                 object value = null;
  44.                 try
  45.                 {
  46.                     value = pi.GetValue(obj, null);
  47.                 }
  48.                 catch (System.Exception ex)
  49.                 {
  50.                     if (ex.InnerException is Autodesk.AutoCAD.Runtime.Exception &&
  51.                         (ex.InnerException as Autodesk.AutoCAD.Runtime.Exception).ErrorStatus == ErrorStatus.NotApplicable)
  52.                         continue;
  53.                     else
  54.                         throw;
  55.                 }
  56.  
  57.                 msg += string.Format("\t{0}: {1}\n", pi.Name, value);
  58.             }
  59.  
  60.             ed.WriteMessage("\n" + msg);
  61.             MessageBox.Show(msg, "DBObject/Entity Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
  62.         }
  63.      
  64.  
  65.         [CommandMethod("DumpEntityInfo")]
  66.         public void DumpEntityInfo_Method()
  67.         {
  68.             using (Transaction tr = db.TransactionManager.StartTransaction())
  69.             {
  70.                 //TODO: add your code below.    
  71.                 Debug.WriteLine("DumpEntityInfo ran.");
  72.                 ed.WriteMessage("DumpEntityInfo ran.\n");
  73.  
  74.                 PromptEntityResult selRes = ed.GetEntity("Pick an entity:");
  75.                 if (selRes.Status == PromptStatus.OK)
  76.                 {
  77.                     Entity ent = tr.GetObject(selRes.ObjectId, OpenMode.ForRead) as Entity;
  78.                     Dump(ent);
  79.                 }
  80.  
  81.                 tr.Commit();
  82.             }
  83.         }
  84.  
  85.     }
  86. }

Пример, что Вы давали. Возможно ли в нем использовать событие модификации объекта, вместо команды ?
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 12-11-2014, 19:26:50
Возможно ли в нем использовать событие модификации объекта, вместо команды ?
Для чего? Я снова ничего не понял. Тебе нужно вызвать метод Dump() в событии модификации объекта? Так вызови его.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 13-11-2014, 12:39:51
Самый простой пример. Свойство с именем XData и метод с именем GetXDataForApplication. Свойство вызывается по имени, а методу нужно передать еще и параметр (в данном случае строковый параметр с именем приложения).

Так будет выглядеть проверка расширенных данных?

Код - C# [Выбрать]
  1. [CommandMethod("FindAppName")]
  2. static public void FindAppName()
  3. {
  4.     Document doc = Application.DocumentManager.MdiActiveDocument;
  5.     Database db = doc.Database;
  6.     Transaction tr = db.TransactionManager.StartTransaction();
  7.     using (tr)
  8.     {
  9.         Editor ed = doc.Editor;
  10.         try
  11.         {
  12.            PromptEntityResult ers = ed.GetEntity("Выберите примитив ");
  13.            Entity ent = (Entity)tr.GetObject(ers.ObjectId,  OpenMode.ForRead);
  14.  
  15.             ResultBuffer buffer =  ent.GetXDataForApplication("ADSK");
  16.  
  17.             // Если null – нет расширенных данных для приложения ADSK
  18.             if (buffer != null)
  19.             {
  20.                 ed.WriteMessage("Есть расширенные данные с именем приложения ADSK");
  21.                 buffer.Dispose();
  22.             }
  23.             else
  24.             {
  25.                 ed.WriteMessage("Нет расширенных данные с именем приложения ADSK");
  26.             }
  27.             tr.Commit();
  28.         }
  29.         catch
  30.         {
  31.             tr.Abort();
  32.         }
  33.     }
  34. }
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 13-11-2014, 12:43:25
Так будет выглядеть проверка расширенных свойств?
Этот код проверяет наличие расширенных данных (Extended Data) . Что такое "расширенные свойства" и что ты под ними подразумеваешь я не знаю. Надеюсь, что мы говорим об одном и том же.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: bakaIIHX от 13-11-2014, 12:56:57
Этот код проверяет наличие расширенных данных (Extended Data)

Мне нужно все разобрать.
1. Что бы получить свойства можно использовать Reflection.
2. Для получения расширенных данных необходимо использовать XData и метод GetXDataForApplication.
3. Что бы отследить модификацию объекта необходимо использовать  DBObject Events, Database.ObjectModified.
4. Осталась запись свойств в файл.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 13-11-2014, 16:14:50
Тебе нужно не "разобрать", а "собрать". Примеры, которые поотдельности всё это делают я уже давал. Теперь собери их все вместе.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Владимир Шу от 13-05-2015, 15:40:23
Сдается мне, что я знаю для чего все это, особенно в купе с вот этой темой http://adn-cis.org/forum/index.php?topic=1029.15
Встречал я на просторах инета упоминание об этом и для чего в конечном итоге это нужно.


Однако у меня другой интерес, для пакетной обработки.
Хотелось бы выбрать некоторые объекты (Довольно много и в разнобой), сохранить их в виде dxf/dwg и при обработке сверяться с этим набором, т.е.
Можно ли получить dxf/dwg представление объекта, сохранить его на диск и потом из этого представления восстановить объект и добавить его в другой чертеж.
Промежуточное сохранение нужно, потому что пакетная сверка будет запускаться не один раз, а выбирать объекты утомительно.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Дима_ от 13-05-2015, 21:15:41
Можно ли получить dxf/dwg представление объекта, сохранить его на диск и потом ....

Можно Database.Wblock(ObjectId).SaveAs(Path,DwgVersion.Current) - ну или не Current
p.s. Database - это "Ваша" database (экземпляр объекта)
p.p.s Если не 1-го объекта, а все-же набора - то соотв. перегрузка у Wblock так-же есть.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 13-05-2015, 23:58:09
Хотелось бы выбрать некоторые объекты (Довольно много и в разнобой), сохранить их в виде dxf/dwg и при обработке сверяться с этим набором, т.е.
К тому, что сказал Дима_, добавлю, что я бы предпочел бы использовать метод Database.WblockCloneObjects
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Владимир Шу от 14-05-2015, 17:57:03
Так работает.
Код - C# [Выбрать]
  1.  using (Db.Database newDb = new Db.Database(true, false))
  2.                     {
  3.                        
  4.      //            App.Document acDoc = App.Application.DocumentManager.MdiActiveDocument;
  5.      //            Db.Database acCurDb = acDoc.Database;
  6.      //            Db.ObjectIdCollection newCol = new Db.ObjectIdCollection();
  7.                         acCurDb.Wblock(newDb, newCol, Gem.Point3d.Origin, Db.DuplicateRecordCloning.Replace);
  8.                         //Произвольное имя файла, что бы не проверять на совпадения
  9.               string FileNameDXF = "D:\\" + DateTime.Now.Day +
  10.                                                 " " + DateTime.Now.Hour +
  11.                                                 " " + DateTime.Now.Minute +
  12.                                                 " " + DateTime.Now.Second +
  13.                                                 " " + DateTime.Now.Millisecond +
  14.                                                 ".dwg";
  15.                         newDb.SaveAs(FileNameDXF, Db.DwgVersion.Current);
  16.                     }

Database.WblockCloneObjects
А с этим не получилось =( Вываливался в эксепшен или в сохраненном чертеже было пусто.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Андрей Бушман от 14-05-2015, 18:03:36
Произвольное имя файла, что бы не проверять на совпадения
Path.GetRandomFileName() (https://msdn.microsoft.com/ru-ru/library/system.io.path.getrandomfilename%28v=vs.110%29.aspx)
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Владимир Шу от 14-05-2015, 18:05:23
спасибо, стало симпатичнее.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Андрей Бушман от 14-05-2015, 18:07:38
спасибо
В 7-й строке используешь переменную, определённую в 6-й, которая закомментирована.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Владимир Шу от 14-05-2015, 18:09:28
В 7-й строке используешь переменную, определённую в 6-й, которая закомментирована.
Это же выдранный из контекста фрагмент , закоментированные строчки вставил для понятности кода.
Название: Re: Сохранение свойств (AUTOCAD 2012 на C# Visual Studio.)
Отправлено: Александр Ривилис от 14-05-2015, 18:56:11
А с этим не получилось =( Вываливался в эксепшен или в сохраненном чертеже было пусто.
При использовании Database.WblockCloneObjects следует сначала создавать Database. Впрочем возможно причина в другом.