【问题标题】:How to get Only one acadobject by selection set如何通过选择集仅获取一个 acadobject
【发布时间】:2013-06-20 18:21:30
【问题描述】:

我在选择目标acadObject 时遇到了一些麻烦。我通过selectionset.SelectonScreen 方法获得输入。

在这里,我可以根据我的过滤条件从模型空间中获取更多数量的对象。但我只需要来自用户的一个对象。

这里我在下面提到了我的代码:

AcadSelectionSet selset= null;
selset=currDoc.selectionset.add("Selset");
short[] ftype=new short[1];
object[] fdata=new object[1];
ftype[0]=2;//for select the blockreference
fdata[0]=blkname;
selset.selectOnScreen ftype,fdata;  // Here i can select any no. of blocks according to filter value but i need only one block reference.

请帮我解决这个问题。

【问题讨论】:

  • 一个简单的方法是if count > 1, show message and select again

标签: c# autocad


【解决方案1】:

这是来自 AutoCAD 开发人员帮助的直接引用

http://docs.autodesk.com/ACD/2013/ENU/index.html?url=files/GUID-CBECEDCF-3B4E-4DF3-99A0-47103D10DADD.htm,topicNumber=d30e724932

AutoCAD .NET API 有大量文档。

你需要有

[assembly: CommandClass(typeof(namespace.class))]

如果您希望能够在NetLoad .dll 之后从命令行调用此命令(如果它是类库),请在命名空间上方。

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;

[CommandMethod("SelectObjectsOnscreen")]
public static void SelectObjectsOnscreen()
{
  // Get the current document and database
  Document acDoc = Application.DocumentManager.MdiActiveDocument;
  Database acCurDb = acDoc.Database;

  // Start a transaction
  using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  {
      // Request for objects to be selected in the drawing area
      PromptSelectionResult acSSPrompt = acDoc.Editor.GetSelection();

      // If the prompt status is OK, objects were selected
      if (acSSPrompt.Status == PromptStatus.OK)
      {
          SelectionSet acSSet = acSSPrompt.Value;

          // Step through the objects in the selection set
          foreach (SelectedObject acSSObj in acSSet)
          {
              // Check to make sure a valid SelectedObject object was returned
              if (acSSObj != null)
              {
                  // Open the selected object for write
                  Entity acEnt = acTrans.GetObject(acSSObj.ObjectId,
                                                   OpenMode.ForWrite) as Entity;

                  if (acEnt != null)
                  {
                      // Change the object's color to Green
                      acEnt.ColorIndex = 3;
                  }
              }
          }

          // Save the new object to the database
          acTrans.Commit();
      }

      // Dispose of the transaction
  }
}

【讨论】:

    【解决方案2】:

    使用其他 Autocad .NET 库(而不是 Interop 库)可以做到这一点。但幸运的是,一个不排斥另一个。

    您需要引用包含以下命名空间的库:

    using Autodesk.Autocad.ApplicationServices
    using Autodesk.Autocad.EditorInput
    using Autodesk.Autocad.DatabaseServices
    

    (您可以从 Autodesk 免费下载 Object Arx 库):

    您需要从 AutoCAD Document 访问 Editor。 根据您显示的代码,您可能正在使用AcadDocument 文档。 因此,要将AcadDocument 转换为Document,请执行以下操作:

    //These are extension methods and must be in a static class
    //Will only work if Doc is saved at least once (has full name) - if document is new, the name will be 
    public static Document GetAsAppServicesDoc(this IAcadDocument Doc)
        {
            return Application.DocumentManager.OfType<Document>().First(D => D.Name == Doc.FullOrNewName());
        }
    

     public static string FullOrNewName(this IAcadDocument Doc)
        {
            if (Doc.FullName == "")
                return Doc.Name;
            else
                return Doc.FullName;
        }
    

    获得Document 后,获取EditorGetSelection(Options, Filter)

    选项包含属性SingleOnlySinglePickInSpace。将其设置为 true 可以满足您的需求。 (尝试两者,看看哪个效果更好)

    //Seleciton options, with single selection
    PromptSelectionOptions Options = new PromptSelectionOptions();
    Options.SingleOnly = true;
    Options.SinglePickInSpace = true;
    
    //This is the filter for blockreferences
    SelectionFilter Filter = new SelectionFilter(new TypedValue[] { new TypedValue(0, "INSERT") });
    
    
    //calls the user selection
    PromptSelectionResult Selection = Document.Editor.GetSelection(Options, Filter);
    
    if (Selection.Status == PromptStatus.OK)
    {
        using (Transaction Trans = Document.Database.TransactionManager.StartTransaction())
        {
            //This line returns the selected items
           AcadBlockReference SelectedRef = (AcadBlockReference)(Trans.GetObject(Selection.Value.OfType<SelectedObject>().First().ObjectId, OpenMode.ForRead).AcadObject);
        }
    }
    

    【讨论】:

    • 这不是一个干净的解决方案,但这是我找到的。由于这些事务和复杂的过滤器,我讨厌使用那些 Arx 库,但有时它们会更好地工作。
    • 您的解决方案可能是 OP 的最佳解决方案,但是您的术语不正确。 “ARX”是严格的原生 C++。托管 API 的正确术语是“AutoCAD .NET API”,而对于本机 C++ API,它是“ObjectARX”。
    • 好....直到现在我才知道其中的区别。 Autodesk 关于这些问题的文档非常差。
    • 互操作程序集是Autodesk.Autocad.Interop.dll;Autodesk.Autocad.Interop.Common.dll; 这些绝对相互排除。 Inprocess 程序集是AcDbMgd.dllacmgd.dll
    • 你好,@BKSpureon,多年来我不再使用 Autocad,但我认为它会阻止用户在你希望他们只选择一个元素时一次选择很多元素。
    猜你喜欢
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多