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

ADN Club => AutoCAD .NET API => Тема начата: Andrey от 13-10-2014, 11:17:08

Название: Установка текущего слоя
Отправлено: Andrey от 13-10-2014, 11:17:08
Добрый день!
Есть задача: в процессе выполнения программы поменять текущие значения слоя, цвета, веса линии,
дать пользователю нанести полилинию (так чтобы в прцессе нанесения были выставлены новые текущие значения)
и вернуть исходные текущие значения.
Код:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.Colors;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Runtime;
  6. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  7. using AcCl = Autodesk.AutoCAD.Colors.Color;
  8.  
  9. namespace AcadTest
  10. {
  11.     public class Commands
  12.     {
  13.         [CommandMethod("testCmd")]
  14.         public void CmdTest()
  15.         {
  16.             Document acDoc = AcAp.DocumentManager.MdiActiveDocument;
  17.             if (acDoc == null)
  18.                 return;
  19.             Database acCurDb = acDoc.Database;
  20.             Editor ed = acDoc.Editor;
  21.  
  22.             using (DocumentLock docLock = acDoc.LockDocument())
  23.             {
  24.                 AcCl CurrentColor = acCurDb.Cecolor;
  25.                 acCurDb.Cecolor = Color.FromColorIndex(ColorMethod.None, 30);
  26.  
  27.                 LineWeight CurrentLWHT = acCurDb.Celweight;
  28.                 acCurDb.Celweight = LineWeight.LineWeight100;
  29.  
  30.                 ObjectId CurrentLayerID = acCurDb.Clayer;
  31.                 using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  32.                 {
  33.                     LinetypeTable acLineTypTbl = acTrans.GetObject(acCurDb.LinetypeTableId, OpenMode.ForWrite) as LinetypeTable;
  34.                     LayerTable acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
  35.  
  36.                     if (!acLyrTbl.Has("New Layer"))
  37.                     {
  38.                         LayerTableRecord acLyrTblRec = new LayerTableRecord();
  39.  
  40.                         acLyrTblRec.Name = "New Layer";
  41.  
  42.                         acLyrTbl.UpgradeOpen();
  43.                         acLyrTbl.Add(acLyrTblRec);
  44.                         acTrans.AddNewlyCreatedDBObject(acLyrTblRec, true);
  45.                         ed.WriteMessage("\n'New Layer' created");
  46.                     }
  47.                     acCurDb.Clayer = acLyrTbl["New Layer"];
  48.                     acTrans.Commit();
  49.                 }
  50.                 acDoc.SendStringToExecute("_PLINE ", false, false, false);
  51.  
  52.                 //AcadApplication acAppComObj = (AcadApplication)Marshal.GetActiveObject("AutoCAD.Application.19");
  53.                 //acAppComObj.ActiveDocument.SendCommand("_PLINE ");
  54.  
  55.                 acCurDb.Cecolor = CurrentColor;
  56.                 acCurDb.Clayer = CurrentLayerID;
  57.                 acCurDb.Celweight = CurrentLWHT;
  58.             }
  59.         }
  60.     }
  61. }
  62.  
В итоге слой создаётся, но не устанавливается в текущие, так же как и цвет и вес.
Пробовал Jig - результат такой же.
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 13-10-2014, 11:36:03
1) Это вынести за пределы транзакции.
acCurDb.Clayer = acLyrTbl["New Layer"];
2) Этот код выполняется асинхронно, т.е. уже после выполнения команды testCmd
acDoc.SendStringToExecute("_PLINE ", false, false, false);
Соответственно команда _PLINE выполнится тогда, когда ты уже восстановишь исходное состояние текущего слоя, цвета и веса линии.
Название: Re: Установка текущего слоя
Отправлено: Andrey от 13-10-2014, 11:47:19
Подкоректировал код и вызываю отрисовку полилинии через COM
Код - C# [Выбрать]
  1.   public void CmdTest()
  2.         {
  3.             Document acDoc = AcAp.DocumentManager.MdiActiveDocument;
  4.             if (acDoc == null)
  5.                 return;
  6.             Database acCurDb = acDoc.Database;
  7.             Editor ed = acDoc.Editor;
  8.  
  9.             using (DocumentLock docLock = acDoc.LockDocument())
  10.             {
  11.                 AcCl CurrentColor = acCurDb.Cecolor;
  12.                 acCurDb.Cecolor = Color.FromColorIndex(ColorMethod.None, 30);
  13.  
  14.                 LineWeight CurrentLWHT = acCurDb.Celweight;
  15.                 acCurDb.Celweight = LineWeight.LineWeight100;
  16.  
  17.                 ObjectId CurrentLayerID = acCurDb.Clayer;
  18.                 ObjectId newLayer = new ObjectId();
  19.                 using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  20.                 {
  21.                     LinetypeTable acLineTypTbl = acTrans.GetObject(acCurDb.LinetypeTableId, OpenMode.ForWrite) as LinetypeTable;
  22.                     LayerTable acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
  23.  
  24.                     if (!acLyrTbl.Has("New Layer"))
  25.                     {
  26.                         LayerTableRecord acLyrTblRec = new LayerTableRecord();
  27.  
  28.                         acLyrTblRec.Name = "New Layer";
  29.                         acLyrTbl.UpgradeOpen();
  30.                         acLyrTbl.Add(acLyrTblRec);
  31.                         acTrans.AddNewlyCreatedDBObject(acLyrTblRec, true);
  32.                         ed.WriteMessage("\n'New Layer' created");
  33.                         newLayer = acLyrTblRec.ObjectId;
  34.                     }
  35.  
  36.                     acTrans.Commit();
  37.                 }
  38.                 acCurDb.Clayer = newLayer;
  39.  
  40.                 AcadApplication acAppComObj = (AcadApplication)Marshal.GetActiveObject("AutoCAD.Application.19");
  41.                 acAppComObj.ActiveDocument.SendCommand("_PLINE ");
  42.  
  43.                 acCurDb.Cecolor = CurrentColor;
  44.                 acCurDb.Clayer = CurrentLayerID;
  45.                 acCurDb.Celweight = CurrentLWHT;
  46.             }
  47.         }
  48.  
Безрезультатно(
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 13-10-2014, 21:41:05
Подкоректировал код и вызываю отрисовку полилинии через COM
А я что обещал что так будет работать?
Безрезультатно(
Этого как раз следовало ожидать.
Почитай здесь: http://adn-cis.org/forum/index.php?topic=810.msg3198#msg3198
Для AutoCAD 2015 будут особенности, так как приведенные выше алгоритмы не работают.
Для 2015 читай пример использования Editor.CommandAsync для вызова команды с ожиданием её завершения здесь: http://adn-cis.org/zumirovanie-do-granicz-okna-s-ispolzovaniem-commandasync.html

Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 13-10-2014, 21:58:58
Замечание на будущее. Так писать не следует:
Код - C# [Выбрать]
  1. AcadApplication acAppComObj = (AcadApplication)Marshal.GetActiveObject("AutoCAD.Application.19");
Таким образом ты ограничиваешь свой код версиями 2013 и 2014. В общем случае должно быть:
Код - C# [Выбрать]
  1. AcadApplication acAppComObj = AcAp.Application.AcadApplication as AcadApplication;
или даже:
Код - C# [Выбрать]
  1. dynamic acAppComObj = AcAp.Application.AcadApplication;
Название: Re: Установка текущего слоя
Отправлено: Andrey от 14-10-2014, 12:05:39
Попробовал таким образом:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.Colors;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Runtime;
  6. using System.Runtime.InteropServices;
  7. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  8. using AcCl = Autodesk.AutoCAD.Colors.Color;
  9.  
  10. [assembly: CommandClass(typeof(AcadTest.Commands))]
  11.  
  12. namespace AcadTest
  13. {
  14.     public class Commands
  15.     {
  16.         [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, EntryPoint = "acedCmd")]
  17.         private static extern int acedCmd(System.IntPtr vlist);
  18.  
  19.         [CommandMethod("testCmd")]
  20.         public void CmdTest()
  21.         {
  22.             Document acDoc = AcAp.DocumentManager.MdiActiveDocument;
  23.             if (acDoc == null)
  24.                 return;
  25.             Database acCurDb = acDoc.Database;
  26.             Editor ed = acDoc.Editor;
  27.  
  28.             using (DocumentLock docLock = acDoc.LockDocument())
  29.             {
  30.                 AcCl CurrentColor = acCurDb.Cecolor;
  31.                 acCurDb.Cecolor = Color.FromColorIndex(ColorMethod.None, 30);
  32.  
  33.                 LineWeight CurrentLWHT = acCurDb.Celweight;
  34.                 acCurDb.Celweight = LineWeight.LineWeight100;
  35.  
  36.                 ObjectId CurrentLayerID = acCurDb.Clayer;
  37.                 ObjectId newLayer = new ObjectId();
  38.                 using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  39.                 {
  40.                     LinetypeTable acLineTypTbl = acTrans.GetObject(acCurDb.LinetypeTableId, OpenMode.ForWrite) as LinetypeTable;
  41.                     LayerTable acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
  42.  
  43.                     if (!acLyrTbl.Has("New Layer"))
  44.                     {
  45.                         LayerTableRecord acLyrTblRec = new LayerTableRecord();
  46.  
  47.                         acLyrTblRec.Name = "New Layer";
  48.                         acLyrTbl.UpgradeOpen();
  49.                         acLyrTbl.Add(acLyrTblRec);
  50.                         acTrans.AddNewlyCreatedDBObject(acLyrTblRec, true);
  51.                         ed.WriteMessage("\n'New Layer' created");
  52.                         newLayer = acLyrTblRec.ObjectId;
  53.                     }
  54.                     else
  55.                         newLayer = acLyrTbl["New Layer"];
  56.  
  57.                     acTrans.Commit();
  58.                 }
  59.                 acCurDb.Clayer = newLayer;
  60.                 ed.Regen();
  61.                 ed.UpdateScreen();
  62.  
  63.                 ResultBuffer rb = new ResultBuffer();
  64.                 rb.Add(new TypedValue(5005, "_.PLINE"));
  65.  
  66.                 acedCmd(rb.UnmanagedObject);
  67.  
  68.                 bool quit = false;
  69.                 while (!quit)
  70.                 {
  71.                     string cmdNames = (string)Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CMDNAMES");
  72.                     if (cmdNames.ToUpper().IndexOf("PLINE") >= 0)
  73.                     {
  74.                         rb = new ResultBuffer();
  75.                         rb.Add(new TypedValue(5005, "\\"));
  76.                         acedCmd(rb.UnmanagedObject);
  77.                     }
  78.                     else
  79.                         quit = true;
  80.                 }
  81.  
  82.                 acCurDb.Cecolor = CurrentColor;
  83.                 acCurDb.Clayer = CurrentLayerID;
  84.                 acCurDb.Celweight = CurrentLWHT;
  85.             }
  86.         }
  87.     }
  88. }
Результат:
https://screencast.autodesk.com/Main/Details/02d880d6-c130-4376-a02b-d111cb83a44b
В моем варианте отсутствуют параметры ввода и контекстное меню для полилинии. Можно это исправить?
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 14-10-2014, 12:10:29
В моем варианте отсутствуют параметры ввода и контекстное меню для полилинии. Можно это исправить?
Установи системную переменную CMDECHO в 1 на время выполнения команды _PLINE
Название: Re: Установка текущего слоя
Отправлено: Andrey от 14-10-2014, 12:41:18
Спасибо!
Попробовал с блоком
Код - C# [Выбрать]
  1.                 ResultBuffer rb = new ResultBuffer();
  2.  
  3.                 rb.Add(new TypedValue(5005, "_.INSERT"));
  4.                 rb.Add(new TypedValue(5005, "PICKET"));
  5.                 rb.Add(new TypedValue(5005, "Scale"));
  6.                 rb.Add(new TypedValue(5005, "1"));
  7.  
  8.                 acedCmd(rb.UnmanagedObject);
  9.  
  10.                 short echo = (short)AcAp.GetSystemVariable("CMDECHO");
  11.                 if (echo == 0)
  12.                     AcAp.SetSystemVariable("CMDECHO", 1);
  13.  
  14.                 bool quit = false;
  15.                 while (!quit)
  16.                 {
  17.                     string cmdNames = (string)AcAp.GetSystemVariable("CMDNAMES");
  18.                     if (cmdNames.ToUpper().IndexOf("INSERT") >= 0)
  19.                     {
  20.                         rb = new ResultBuffer();
  21.                         rb.Add(new TypedValue(5005, "\\"));
  22.                         acedCmd(rb.UnmanagedObject);
  23.                     }
  24.                     else
  25.                         quit = true;
  26.                 }
  27.  
  28.                 AcAp.SetSystemVariable("CMDECHO", echo);
  29.  
Но значения в панеле свойств и в панелях слоёв и цвета разные?
https://screencast.autodesk.com/Main/Details/a1541329-3d8a-472d-8583-0727db16eb7a
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 14-10-2014, 12:50:42
Внешне похоже на глюк, так как если у тебя ничего не выбрано, то цвет и слой должны быть одинаковы и там и там. Но с учетом того, что ты показал только часть кода я ничего сказать не могу. Возможно не закрыта транзакция.
Для полилинии у тебя всё получилось нормально?
Название: Re: Установка текущего слоя
Отправлено: Andrey от 14-10-2014, 12:54:33
Код точно такой же как и для полилинии
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.Colors;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Runtime;
  6. using System.Runtime.InteropServices;
  7. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  8. using AcCl = Autodesk.AutoCAD.Colors.Color;
  9.  
  10. [assembly: CommandClass(typeof(AcadTest.Commands))]
  11.  
  12. namespace AcadTest
  13. {
  14.     public class Commands
  15.     {
  16.         [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, EntryPoint = "acedCmd")]
  17.         private static extern int acedCmd(System.IntPtr vlist);
  18.  
  19.         [CommandMethod("testCmd")]
  20.         public void CmdTest()
  21.         {
  22.             Document acDoc = AcAp.DocumentManager.MdiActiveDocument;
  23.             if (acDoc == null)
  24.                 return;
  25.             Database acCurDb = acDoc.Database;
  26.             Editor ed = acDoc.Editor;
  27.  
  28.             using (DocumentLock docLock = acDoc.LockDocument())
  29.             {
  30.                 AcCl CurrentColor = acCurDb.Cecolor;
  31.                 acCurDb.Cecolor = Color.FromColorIndex(ColorMethod.None, 30);
  32.  
  33.                 LineWeight CurrentLWHT = acCurDb.Celweight;
  34.                 acCurDb.Celweight = LineWeight.LineWeight100;
  35.  
  36.                 ObjectId CurrentLayerID = acCurDb.Clayer;
  37.                 ObjectId newLayer = new ObjectId();
  38.                 using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  39.                 {
  40.                     LinetypeTable acLineTypTbl = acTrans.GetObject(acCurDb.LinetypeTableId, OpenMode.ForWrite) as LinetypeTable;
  41.                     LayerTable acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
  42.  
  43.                     if (!acLyrTbl.Has("New Layer"))
  44.                     {
  45.                         LayerTableRecord acLyrTblRec = new LayerTableRecord();
  46.  
  47.                         acLyrTblRec.Name = "New Layer";
  48.                         acLyrTbl.UpgradeOpen();
  49.                         acLyrTbl.Add(acLyrTblRec);
  50.                         acTrans.AddNewlyCreatedDBObject(acLyrTblRec, true);
  51.                         ed.WriteMessage("\n'New Layer' created");
  52.                         newLayer = acLyrTblRec.ObjectId;
  53.                     }
  54.                     else
  55.                         newLayer = acLyrTbl["New Layer"];
  56.  
  57.                     acTrans.Commit();
  58.                 }
  59.                 acCurDb.Clayer = newLayer;
  60.  
  61.                 ResultBuffer rb = new ResultBuffer();
  62.  
  63.                 rb.Add(new TypedValue(5005, "_.INSERT"));
  64.                 rb.Add(new TypedValue(5005, "PICKET"));
  65.                 rb.Add(new TypedValue(5005, "Scale"));
  66.                 rb.Add(new TypedValue(5005, "1"));
  67.  
  68.                 acedCmd(rb.UnmanagedObject);
  69.  
  70.                 short echo = (short)AcAp.GetSystemVariable("CMDECHO");
  71.                 if (echo == 0)
  72.                     AcAp.SetSystemVariable("CMDECHO", 1);
  73.  
  74.                 bool quit = false;
  75.                 while (!quit)
  76.                 {
  77.                     string cmdNames = (string)AcAp.GetSystemVariable("CMDNAMES");
  78.                     if (cmdNames.ToUpper().IndexOf("INSERT") >= 0)
  79.                     {
  80.                         rb = new ResultBuffer();
  81.                         rb.Add(new TypedValue(5005, "\\"));
  82.                         acedCmd(rb.UnmanagedObject);
  83.                     }
  84.                     else
  85.                         quit = true;
  86.                 }
  87.  
  88.                 AcAp.SetSystemVariable("CMDECHO", echo);
  89.  
  90.                 acCurDb.Cecolor = CurrentColor;
  91.                 acCurDb.Clayer = CurrentLayerID;
  92.                 acCurDb.Celweight = CurrentLWHT;
  93.             }
  94.         }
  95.     }
  96. }
Название: Re: Установка текущего слоя
Отправлено: Andrey от 14-10-2014, 12:55:33
Да, с полилинией всё отработало как надо.
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 14-10-2014, 12:57:13
Хм. Попробуй пройтись под отладчиком. Явных ошибок я не вижу.
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 14-10-2014, 13:27:18
Я проверил под чистым AutoCAD 2013 SP3 - ситуация точно такая же как у тебя. Фактически не обновляется Панель свойств. Если её выключить и включить, то она обновится и станет нормальной.
Название: Re: Установка текущего слоя
Отправлено: Andrey от 14-10-2014, 16:27:11
Почему-то при попытке нанести блок происходит "залипание" панели свойств...
Попробовал нанесение полилинии записать в событие "Button_Click" для кнопки в PaletteSet
https://screencast.autodesk.com/Main/Details/e3326b97-1eb0-4251-b073-33b619718452
И ничего не получилось...
Проект в Autocad Civil 2014
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 14-10-2014, 16:49:15
Попробовал нанесение полилинии записать в событие "Button_Click" для кнопки в PaletteSet
https://screencast.autodesk.com/Main/Details/e3326b97-1eb0-4251-b073-33b619718452
И ничего не получилось...
Проект в Autocad Civil 2014
Попробуй воспользоваться Editor.StartUserInteraction: http://adndevblog.typepad.com/autocad/2012/05/taking-mouse-inputs-from-a-modal-dialog-box.html
Впрочем это тоже скорее всего не поможет. Синхронно запустить команду можно только из контекста документа, а код из палитры выполняется в контексте приложения. Выход может быть такой. В событие "Button_Click" ты запускаешь (при помощи Document.SendStringToExecute) команду из которой уже и строишь полилинию (т.е. в твоём случае это команда TESTCMD). Но она будет выполнена асинхронно.
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 14-10-2014, 16:50:56
Почему-то при попытке нанести блок происходит "залипание" панели свойств...
Я же написал, что это скорее всего баг AutoCAD. Проверю в AutoCAD 2015 и если там тоже самое - отправлю в ADN DevHelp.
Название: Re: Установка текущего слоя
Отправлено: Дмитрий Загорулькин от 14-10-2014, 18:50:29
Но значения в панеле свойств и в панелях слоёв и цвета разные?
https://screencast.autodesk.com/Main/Details/a1541329-3d8a-472d-8583-0727db16eb7a
Интересно, а где правильные? Если проверить значения переменных CLAYER и т.п., что покажут?
Если неправильные значения в ленте, то, может быть, есть какой-то дополнительный метод "обновить ленту"?
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 14-10-2014, 20:06:19
Интересно, а где правильные?
Правильные в ленте, а неправильные в Панели свойств. Причем даже если после этого выбрать что-то на экране (чтобы Панель свойств обновилась), а потом отменить выбор, то всё-равно в Панели свойств будут неправильные значения. И только пара команд _PROPERTIESCLOSE/_PROPERTIES приводят Панель свойств в нормальное состояние.
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 16-10-2014, 14:57:46
Отправил запрос в ADN DevHelp. Подождем их реакцию.
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 17-10-2014, 13:52:59
Пока ждал реакцию из ADN DevHelp решил проверить как работает аналогичный код в чистом ObjectARX:
Код - C++ [Выбрать]
  1. //-----------------------------------------------------------------------------
  2. //----- acrxEntryPoint.cpp
  3. //-----------------------------------------------------------------------------
  4. #include "StdAfx.h"
  5. #include "axlock.h"
  6. #include "resource.h"
  7.  
  8. //-----------------------------------------------------------------------------
  9. #define szRDS _RXST("")
  10.  
  11. //-----------------------------------------------------------------------------
  12. //----- ObjectARX EntryPoint
  13. class CTestCmdArxApp : public AcRxArxApp {
  14.  
  15. public:
  16.   CTestCmdArxApp () : AcRxArxApp () {}
  17.  
  18.   virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
  19.     // TODO: Load dependencies here
  20.  
  21.     // You *must* call On_kInitAppMsg here
  22.     AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
  23.  
  24.     // TODO: Add your initialization code here
  25.  
  26.     return (retCode) ;
  27.   }
  28.  
  29.   virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
  30.     // TODO: Add your code here
  31.  
  32.     // You *must* call On_kUnloadAppMsg here
  33.     AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
  34.  
  35.     // TODO: Unload dependencies here
  36.  
  37.     return (retCode) ;
  38.   }
  39.  
  40.   virtual void RegisterServerComponents () {
  41.   }
  42.  
  43.   static void RanTestCmd () {
  44.     if (curDoc() == NULL) return;
  45.     AcDbDatabase *pDb = curDoc()->database();
  46.     AcAxDocLock doclock(pDb);
  47.     AcDbObjectId newLayerId;
  48.     resbuf _cmdecho; _cmdecho.restype = RTSHORT; _cmdecho.resval.rint = 0;
  49.     acedGetVar(_T("CMDECHO"),&_cmdecho);
  50.     if (_cmdecho.resval.rint == 0)  {
  51.       _cmdecho.resval.rint = 1;
  52.       acedSetVar(_T("CMDECHO"),&_cmdecho);
  53.       _cmdecho.resval.rint = 0;
  54.     }
  55.     {
  56.       AcDbLayerTablePointer pLT(pDb->layerTableId(), AcDb::kForRead);
  57.       if (pLT.openStatus() != Acad::eOk) return;
  58.       if (pLT->getAt(_T("New Layer"), newLayerId) != Acad::eOk) {
  59.         AcDbLayerTableRecordPointer pLTR;   pLTR.create();
  60.         pLTR->setName(_T("New Layer"));
  61.         if (pLT->upgradeOpen() != Acad::eOk) return;
  62.         if (pLT->add(newLayerId,pLTR) != Acad::eOk) return;
  63.       }
  64.     }
  65.     pDb->setClayer(newLayerId);
  66.     AcCmColor _cecolor = pDb->cecolor();
  67.     AcDbObjectId _clayer = pDb->clayer();
  68.     AcCmColor color; color.setColorIndex(30);
  69.     pDb->setCecolor(color);
  70.     AcDb::LineWeight _celweight = pDb->celweight();
  71.     pDb->setCelweight(AcDb::kLnWt100);
  72.     resbuf *rb = acutBuildList(RTSTR,_T("_INSERT"), RTSTR,_T("PICKET"),RTSTR,_T("_SCALE"), RTSTR,_T("1"), NULL);
  73.     acedCmd(rb);
  74.     while (true) {
  75.       resbuf rbNames; rbNames.restype = RTSTR; rbNames.resval.rstring = NULL;
  76.       acedGetVar(_T("CMDNAMES"), &rbNames);
  77.       if (rbNames.resval.rstring != NULL && CString(rbNames.resval.rstring).MakeUpper().Find(_T("INSERT")) >= 0) {
  78.         acutRelRb(rb); rb = acutBuildList(RTSTR,_T("\\"),NULL);
  79.         if (acedCmd(rb) != RTNORM) break;
  80.       } else break;
  81.     }
  82.     acedSetVar(_T("CMDECHO"),&_cmdecho);
  83.     pDb->setClayer(_clayer);
  84.     pDb->setCecolor(_cecolor);
  85.     pDb->setCelweight(_celweight);
  86.   }
  87. } ;
  88.  
  89. //-----------------------------------------------------------------------------
  90. IMPLEMENT_ARX_ENTRYPOINT(CTestCmdArxApp)
  91.  
  92. ACED_ARXCOMMAND_ENTRY_AUTO(CTestCmdArxApp, Ran, TestCmd, TestCmd, ACRX_CMD_MODAL, NULL)

Код делает абсолютно тоже самое, что и исходный код на C#. И результат точно такой же, т.е. в Панели Свойств и в Ленте получаем разные значения. В Панели Свойств значения неправильные. Интересный факт. Отправил тоже в ADN DevHelp.
Название: Re: Установка текущего слоя
Отправлено: Andrey от 17-10-2014, 14:43:40
И в AutoCAD 2015 также работает?
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 17-10-2014, 21:27:28
И в AutoCAD 2015 также работает?
Я пока не проверял. В таком виде этот код не будет работать в AutoCAD 2015, т.к. в нём нельзя использовать acedCmd, а нужно использовать acedCmdC/acedCmdS в ObjectARX и Editor.Command/Editor.CommandAsync в .NET
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 18-10-2014, 18:19:06
Уже проверил и для AutoCAD 2015 SP2 - ситуация точно такая же. На всякий случай привожу код. Он может быть полезен для понимания того как в AutoCAD 2015 можно запустить команду с запросом к пользователю и дождаться завершения её выполнения:
Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Autodesk.AutoCAD.ApplicationServices;
  7. using Autodesk.AutoCAD.Colors;
  8. using Autodesk.AutoCAD.DatabaseServices;
  9. using Autodesk.AutoCAD.EditorInput;
  10. using Autodesk.AutoCAD.Runtime;
  11. using System.Runtime.InteropServices;
  12. using AcAp = Autodesk.AutoCAD.ApplicationServices;
  13. using AcCl = Autodesk.AutoCAD.Colors;
  14.  
  15. [assembly: CommandClass(typeof(AcadTest.Commands))]
  16.  
  17. namespace AcadTest
  18. {
  19.   public class Commands
  20.   {
  21.     // Вспомогательная функция для проверки работает ли команда _INSERT
  22.     public static bool isInsertActive()
  23.     {
  24.       string str = (string)Application.GetSystemVariable("CMDNAMES");
  25.       if (str.ToUpper().Contains("INSERT") == true) {
  26.         return true;
  27.       }
  28.       return false;
  29.     }
  30.     [CommandMethod("testCmd")]
  31.     public static async void CmdTest()
  32.     {
  33.       Document acDoc = AcAp.Application.DocumentManager.MdiActiveDocument;
  34.       if (acDoc == null)
  35.         return;
  36.       Database acCurDb = acDoc.Database;
  37.       Editor ed = acDoc.Editor;
  38.  
  39.       using (DocumentLock docLock = acDoc.LockDocument())
  40.       {
  41.         AcCl.Color CurrentColor = acCurDb.Cecolor;
  42.         acCurDb.Cecolor = Color.FromColorIndex(ColorMethod.ByAci, 30);
  43.  
  44.         LineWeight CurrentLWHT = acCurDb.Celweight;
  45.         acCurDb.Celweight = LineWeight.LineWeight100;
  46.  
  47.         ObjectId CurrentLayerID = acCurDb.Clayer;
  48.         ObjectId newLayer = new ObjectId();
  49.         using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  50.         {
  51.           LinetypeTable acLineTypTbl = acTrans.GetObject(acCurDb.LinetypeTableId, OpenMode.ForWrite) as LinetypeTable;
  52.           LayerTable acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
  53.  
  54.           if (!acLyrTbl.Has("New Layer"))
  55.           {
  56.             LayerTableRecord acLyrTblRec = new LayerTableRecord();
  57.  
  58.             acLyrTblRec.Name = "New Layer";
  59.             acLyrTbl.UpgradeOpen();
  60.             acLyrTbl.Add(acLyrTblRec);
  61.             acTrans.AddNewlyCreatedDBObject(acLyrTblRec, true);
  62.             ed.WriteMessage("\n'New Layer' created");
  63.             newLayer = acLyrTblRec.ObjectId;
  64.           }
  65.           else
  66.             newLayer = acLyrTbl["New Layer"];
  67.  
  68.           acTrans.Commit();
  69.         }
  70.         acCurDb.Clayer = newLayer;
  71.  
  72.         await ed.CommandAsync(new object[] { "_.INSERT", "PICKET", "_SCALE", "1"});
  73.         short echo = (short)AcAp.Application.GetSystemVariable("CMDECHO");
  74.         if (echo == 0) AcAp.Application.SetSystemVariable("CMDECHO", 1);
  75.  
  76.         while (isInsertActive())
  77.         {
  78.           await ed.CommandAsync(new object[] { Editor.PauseToken });
  79.         }
  80.  
  81.         AcAp.Application.SetSystemVariable("CMDECHO", echo);
  82.  
  83.         acCurDb.Cecolor = CurrentColor;
  84.         acCurDb.Clayer = CurrentLayerID;
  85.         acCurDb.Celweight = CurrentLWHT;
  86.       }
  87.     }
  88.   }
  89. }
Название: Re: Установка текущего слоя
Отправлено: Andrey от 21-10-2014, 12:35:38
Спасибо!
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 24-10-2014, 01:47:18
В ADN DevHelp подтвердили проблему и передали команде инженеров. В качестве временного решения предложили запускать команду _PROPERTIES, которая действительно обновляет окно свойств. Но запуск её ни через SendStringToExecute, ни через acedCmd, ни через Editor.Command/Editor.CommandAsync не приводит к обновлению окна Панели свойств. Во всяком случае в AutoCAD 2015. Для меня это загадка. Подождём дополнительной информации из ADN DevHelp.
Название: Re: Установка текущего слоя
Отправлено: Александр Ривилис от 27-10-2014, 20:28:18
Команда ADN DevHelp также удивлена таким поведением и направила этот вопрос команде инженеров. Вот так с какой-то мелочи был найден древний баг в AutoCAD API. :)