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

ADN Club => AutoCAD .NET API => Тема начата: Atomohod от 14-07-2018, 23:14:36

Название: Многоразовый запуск метода через событие. Как реализовать?
Отправлено: Atomohod от 14-07-2018, 23:14:36
Здравствуйте!
Пытаюсь освоить работу с событиями. Суть моей задачи-есть код, вставляющий блок позиции в чертеж. Работает как надо, но один раз. Я хочу заставить его запускаться повторно при наступлении события добавления блока предыдущей позиции в базу данных чертежа неограниченное число раз. Подписался на событие acCurDb.ObjectAppended, но в результате получил зацикливание. В чем я неправ?
Код - C# [Выбрать]
  1. namespace MarksUtilities
  2. {
  3.  
  4.      using Autodesk.AutoCAD.ApplicationServices;
  5.      using Autodesk.AutoCAD.DatabaseServices;
  6.      using Autodesk.AutoCAD.EditorInput;
  7.      using Autodesk.AutoCAD.Geometry;
  8.      using Autodesk.AutoCAD.Runtime;
  9.  
  10.      using Application = Autodesk.AutoCAD.ApplicationServices.Core.Application;
  11.  
  12.      public class InsertPosMark
  13.      {
  14.           protected Point3d GetUserPoint( )
  15.  
  16.           {
  17.                Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  18.                Document acCurDoc = Application.DocumentManager.MdiActiveDocument;
  19.                Database acCurDb = acCurDoc.Database;
  20.  
  21.                PromptPointOptions pickPoint = new PromptPointOptions("Specify the insertion point: ");
  22.                PromptPointResult userPointResult = ed.GetPoint(pickPoint);
  23.  
  24.                return userPointResult.Value;
  25.           }
  26.  
  27.  
  28.           [CommandMethod("InsBlockWithAnAttribute")]
  29.           public void InsertBlockWithAnAttribute( )
  30.           {
  31.                
  32.                Document acDoc = Application.DocumentManager.MdiActiveDocument;
  33.                Database acCurDb = acDoc.Database;
  34.  
  35.                Point3d insertionPoint = GetUserPoint( );
  36.  
  37.                using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction( ))
  38.                {
  39.                     // Open the Block table for read
  40.                     BlockTable acBlkTbl;
  41.                     acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
  42.  
  43.                     ObjectId blkRecId = ObjectId.Null;
  44.  
  45.                     if (!acBlkTbl.Has("PosMark"))
  46.                     {
  47.                          using (BlockTableRecord acBlkTblRec = new BlockTableRecord( ))
  48.                          {
  49.                               acBlkTblRec.Name = "PosMark";
  50.  
  51.                               // Set the insertion point for the block
  52.                               acBlkTblRec.Origin = new Point3d(0, 0, 0);
  53.  
  54.                               // Add a circle to the block
  55.                               using (Circle acCirc = new Circle( ))
  56.                               {
  57.                                    acCirc.Center = new Point3d(0, 0, 0);
  58.                                    acCirc.Radius = 4.5;
  59.  
  60.                                    acBlkTblRec.AppendEntity(acCirc);
  61.  
  62.                                    acBlkTbl.UpgradeOpen( );
  63.                                    acBlkTbl.Add(acBlkTblRec);
  64.                                    acTrans.AddNewlyCreatedDBObject(acBlkTblRec, true);
  65.  
  66.                                    // Add an attribute definition to the block
  67.                                    using (AttributeDefinition posNumber = new AttributeDefinition( ))
  68.                                    {
  69.                                         posNumber.Position = new Point3d(0, 0, 0);
  70.                                         posNumber.Prompt = "Position Number";
  71.                                         posNumber.Tag = "PosNumber";
  72.                                         posNumber.TextString = "1";
  73.                                         posNumber.Height = acCirc.Radius * 0.7;
  74.                                         posNumber.Justify = AttachmentPoint.MiddleCenter;
  75.                                         acBlkTblRec.AppendEntity(posNumber);
  76.                                    }
  77.  
  78.                                    using (AttributeDefinition designation = new AttributeDefinition( ))
  79.                                    {
  80.                                         designation.Position = new Point3d(0, -5, 0);
  81.                                         designation.Prompt = "Designation";
  82.                                         designation.Tag = "Designation";
  83.                                         designation.TextString = "Помещение";
  84.                                         designation.Invisible = true;
  85.                                         designation.Height = 5;
  86.                                         designation.Justify = AttachmentPoint.MiddleCenter;
  87.                                         acBlkTblRec.AppendEntity(designation);
  88.                                    }
  89.  
  90.                                    using (AttributeDefinition spaceNumber = new AttributeDefinition( ))
  91.                                    {
  92.                                         spaceNumber.Position = new Point3d(0, -10, 0);
  93.                                         spaceNumber.Prompt = "Space number";
  94.                                         spaceNumber.Tag = "SpaceNumber";
  95.                                         spaceNumber.TextString = "01525";
  96.                                         spaceNumber.Invisible = true;
  97.                                         spaceNumber.Height = 5;
  98.                                         spaceNumber.Justify = AttachmentPoint.MiddleCenter;
  99.                                         acBlkTblRec.AppendEntity(spaceNumber);
  100.                                    }
  101.  
  102.                                    using (AttributeDefinition mainWatertightCompartment = new AttributeDefinition( ))
  103.                                    {
  104.                                         mainWatertightCompartment.Position = new Point3d(0, -15, 0);
  105.                                         mainWatertightCompartment.Prompt = "Main watertight compartment";
  106.                                         mainWatertightCompartment.Tag = "MWC";
  107.                                         mainWatertightCompartment.TextString = "01";
  108.                                         mainWatertightCompartment.Invisible = true;
  109.                                         mainWatertightCompartment.Height = 5;
  110.                                         mainWatertightCompartment.Justify = AttachmentPoint.MiddleCenter;
  111.                                         acBlkTblRec.AppendEntity(mainWatertightCompartment);
  112.                                    }
  113.  
  114.                                    using (AttributeDefinition gastightContour = new AttributeDefinition( ))
  115.                                    {
  116.                                         gastightContour.Position = new Point3d(0, -20, 0);
  117.                                         gastightContour.Prompt = "Gastight contour";
  118.                                         gastightContour.Tag = "GastightContour";
  119.                                         gastightContour.TextString = "015";
  120.                                         gastightContour.Invisible = true;
  121.                                         gastightContour.Height = 5;
  122.                                         gastightContour.Justify = AttachmentPoint.MiddleCenter;
  123.                                         acBlkTblRec.AppendEntity(gastightContour);
  124.                                    }
  125.  
  126.                                    using (AttributeDefinition fireRatingClass = new AttributeDefinition( ))
  127.                                    {
  128.                                         fireRatingClass.SetDatabaseDefaults(acBlkTbl.Database);
  129.                                         fireRatingClass.Position = new Point3d(0, -25, 0);
  130.                                         fireRatingClass.Prompt = "Fire rating class";
  131.                                         fireRatingClass.Tag = "FireRatingClass";
  132.                                         fireRatingClass.TextString = "1";
  133.                                         fireRatingClass.Invisible = true;
  134.                                         fireRatingClass.Height = 5;
  135.                                         fireRatingClass.Justify = AttachmentPoint.MiddleCenter;
  136.                                         fireRatingClass.Position= new Point3d(0,-50,0);
  137.                                         fireRatingClass.AlignmentPoint=new Point3d(0,50,0);
  138.                                         fireRatingClass.AdjustAlignment(acBlkTbl.Database);
  139.                                         acBlkTblRec.AppendEntity(fireRatingClass);
  140.                                    }
  141.  
  142.                                    blkRecId = acBlkTblRec.Id;
  143.                               }
  144.                          }
  145.                     }
  146.                     else
  147.                     {
  148.                          blkRecId = acBlkTbl ["PosMark"];
  149.                     }
  150.  
  151.                     // Insert the block into the current space
  152.                     if (blkRecId != ObjectId.Null)
  153.                     {
  154.                          BlockTableRecord acBlkTblRec = acTrans.GetObject(blkRecId, OpenMode.ForRead) as BlockTableRecord;
  155.  
  156.                          // Create and insert the new block reference
  157.                          using (BlockReference acBlkRef = new BlockReference(insertionPoint, blkRecId))
  158.                          {
  159.                               BlockTableRecord acCurSpaceBlkTblRec = acTrans.GetObject(acCurDb.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  160.  
  161.                               acCurSpaceBlkTblRec.AppendEntity(acBlkRef);
  162.                               acTrans.AddNewlyCreatedDBObject(acBlkRef, true);
  163.  
  164.                               // Verify block table record has attribute definitions associated with it
  165.                               if (acBlkTblRec.HasAttributeDefinitions)
  166.                               {
  167.                                    foreach (ObjectId objID in acBlkTblRec)
  168.                                    {
  169.                                         DBObject dbObj = acTrans.GetObject(objID, OpenMode.ForRead);
  170.  
  171.                                         if (dbObj is AttributeDefinition)
  172.                                         {
  173.                                              AttributeDefinition acAtt = dbObj as AttributeDefinition;
  174.  
  175.                                              if (!acAtt.Constant)
  176.                                              {
  177.                                                   using (AttributeReference acAttRef = new AttributeReference( ))
  178.                                                   {
  179.                                                        acAttRef.SetAttributeFromBlock(acAtt, acBlkRef.BlockTransform);
  180.                                                        acAttRef.Position = acAtt.Position.TransformBy(acBlkRef.BlockTransform);
  181.                                                        acAttRef.TextString = acAtt.TextString;
  182.                                                        acBlkRef.AttributeCollection.AppendAttribute(acAttRef);
  183.                                                        acTrans.AddNewlyCreatedDBObject(acAttRef, true);
  184.                                                   }
  185.                                              }
  186.                                         }
  187.                                    }
  188.                               }
  189.                          }
  190.                     }
  191.  
  192.                     acTrans.Commit( );
  193.                    
  194.                }
  195.                acCurDb.ObjectAppended += AcCurDb_ObjectAppended;
  196.           }
  197.  
  198.           private void AcCurDb_ObjectAppended(object sender, ObjectEventArgs e)
  199.           {
  200.                this.InsertBlockWithAnAttribute();
  201.           }
  202.      }
  203.  
  204. }
Название: Re: Многоразовый запуск метода через событие. Как реализовать?
Отправлено: Александр Ривилис от 15-07-2018, 00:34:23
Подписался на событие acCurDb.ObjectAppended, но в результате получил зацикливание.
А чего ты ожидал? Ты даже не проверяешь что добавляется в базу.
Название: Re: Многоразовый запуск метода через событие. Как реализовать?
Отправлено: Atomohod от 15-07-2018, 00:40:06
Ты даже не проверяешь что добавляется в базу.
Я думал, что мой новый blockReference. Ведь между окончанием работы моей команды и событием нет никакого иного действия. Я работаю с ним внутри транзакции к как только ее закрываю, то перехватываю событие и запускаю метод заново. Видимо что-то не то думал... Как мне исправить код?
Название: Re: Многоразовый запуск метода через событие. Как реализовать?
Отправлено: Александр Ривилис от 16-07-2018, 00:03:44
Я думал, что мой новый blockReference.
Думал неправильно. Запусти под отладчиком и посмотри. Кроме того в событиях (почти во всех) нельзя интерактивно обращаться к AutoCAD (т.е. то что делается в твоём методе GetUserPoint).
P.S.: Я думаю тебе следует отказаться от самой идеи это делать. Если хочешь изучать события в AutoCAD .NET API, то найди какое-то другое применение им.
В крайнем случае если твой блок вставляется только по команде InsBlockWithAnAttribute, то используй событие завершение команды InsBlockWithAnAttribute (CommandEnded). Хотя и это тоже полный бред.
Название: Re: Многоразовый запуск метода через событие. Как реализовать?
Отправлено: Александр Ривилис от 16-07-2018, 00:09:31
И почему вместо всех этих извращений с событиями просто не зациклить твой метод до нажатия Enter вместо указания точки. Только метод GetUserPoint придётся переделать, чтобы можно было понять указал ли пользователь точку, нажал Enter или Esc. Чего уж проще...
Название: Re: Многоразовый запуск метода через событие. Как реализовать?
Отправлено: Дмитрий Загорулькин от 16-07-2018, 11:59:29
Подписался на событие acCurDb.ObjectAppended, но в результате получил зацикливание. В чем я неправ?
Конечно же, будет зацикливание. Тут рекурсия в чистом виде. Добавляется объект в чертёж - запускается обработка события ObjectAppended, в котором также добавляются объекты в чертёж - при каждом добавлении объекта снова запускается обработка события ObjectAppended... И так лавинообразно до тех пор, пока не возникнет Exception переполнения памяти или ещё какой-нибудь. Более того, при обработке события ObjectAppended запускается метод, в котором ещё раз подписываемся на это событие. В .NET повторная подписка на событие означает, что обработчик будет вызываться несколько раз, при возникновении одного события. Это ещё больше усугубляет ситуацию.