
AutoCAD .NET API 实战C# 调用 5 种 Utility 方法实现精准用户交互在CAD二次开发领域用户交互的精准度和流畅度直接决定了插件的专业水准。本文将深入解析AutoCAD .NET API中Utility类的五大核心交互方法通过实战代码演示如何构建健壮的用户输入逻辑并分享封装技巧与异常处理经验。1. 环境准备与基础架构1.1 项目配置要点开发AutoCAD插件时需特别注意以下环境配置// 必需引用设置Copy LocalFalse using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry;版本兼容性对照表AutoCAD版本.NET Framework版本推荐VS版本2020-20224.8VS20192023-2025.NET 6.0VS20221.2 交互类基础封装建议创建独立的交互服务类统一管理事务和错误处理public class CadInteractionService { private readonly Document _doc; private readonly Editor _editor; public CadInteractionService() { _doc Application.DocumentManager.MdiActiveDocument; _editor _doc.Editor; } // 统一事务处理方法 public T ExecuteInTransactionT(FuncTransaction, T action) { using (var tr _doc.TransactionManager.StartTransaction()) { try { var result action(tr); tr.Commit(); return result; } catch (Autodesk.AutoCAD.Runtime.Exception ex) { _editor.WriteMessage($\n错误{ex.Message}); tr.Abort(); return default; } } } }2. 点坐标获取GetPoint2.1 基础实现与增强GetPoint方法用于获取用户指定的三维坐标点public Point3d? GetPointWithPreview(string prompt, Point3d basePoint) { var opts new PromptPointOptions(prompt) { BasePoint basePoint, UseBasePoint true, AllowNone false }; opts.Keywords.Add(Cancel); PromptPointResult result _editor.GetPoint(opts); if (result.Status PromptStatus.Keyword) return null; return result.Value; }视觉增强技巧通过PromptPointOptions.UseDashedLine显示虚线辅助线使用Jig类实现动态拖拽预览效果2.2 坐标系转换陷阱常见错误场景// 错误示例未考虑UCS转换 Point3d worldPoint GetPointWithPreview(指定点, Point3d.Origin); // 正确做法 Matrix3d ucsMatrix _editor.CurrentUserCoordinateSystem; Point3d worldPoint result.Value.TransformBy(ucsMatrix);3. 距离测量GetDistance3.1 动态测量实现public double? GetDynamicDistance(string prompt, Point3d basePoint) { var opts new PromptDistanceOptions(prompt) { BasePoint basePoint, UseBasePoint true, AllowNegative false, AllowZero false }; PromptDoubleResult result _editor.GetDistance(opts); return result.Status PromptStatus.OK ? result.Value : null; }精度控制参数参数说明推荐值AllowArbitraryInput是否允许键盘输入任意值falseAllowNegative是否允许负值根据业务需求AllowZero是否允许零值false3.2 单位制处理// 获取当前图形单位 double unitScale HostApplicationServices.Current.UserMeasurementScale; // 转换为毫米单位 double distanceInMM result.Value * unitScale;4. 实体选择GetEntity4.1 高级选择控制public (ObjectId, Point3d)? SelectEntityWithFilter( string prompt, Type[] allowedTypes) { var opts new PromptEntityOptions(prompt); opts.SetRejectMessage(\n请选择有效实体类型); foreach (var type in allowedTypes) { opts.AddAllowedClass(type); } PromptEntityResult result _editor.GetEntity(opts); if (result.Status ! PromptStatus.OK) return null; return (result.ObjectId, result.PickedPoint); }常用实体类型对照CAD对象类型.NET类型DXF名称直线LineLINE多段线PolylineLWPOLYLINE圆CircleCIRCLE块参照BlockReferenceINSERT4.2 选择集性能优化// 使用预过滤提升大图性能 var filter new SelectionFilter( new[] { new TypedValue((int)DxfCode.Start, LINE), new TypedValue((int)DxfCode.LayerName, 标注层) }); PromptSelectionResult result _editor.GetSelection(filter);5. 关键字输入GetKeyword5.1 多级菜单实现public string GetNestedKeywords(string prompt, Dictionarystring, string[] options) { var opts new PromptKeywordOptions(prompt); foreach (var key in options.Keys) { opts.Keywords.Add(key); } while (true) { PromptResult result _editor.GetKeywords(opts); if (!options.ContainsKey(result.StringResult)) return result.StringResult; // 进入子菜单 opts new PromptKeywordOptions($请选择{result.StringResult}类型); opts.Keywords.Add(返回); foreach (var subOption in options[result.StringResult]) { opts.Keywords.Add(subOption); } } }用户体验优化点使用PromptKeywordOptions.AppendKeywordsToMessage自动显示可选关键字通过PromptKeywordOptions.KeywordsDisplay控制关键字显示顺序6. 数值输入GetInteger6.1 范围限制与默认值public int? GetBoundedInteger( string prompt, int minValue, int maxValue, int? defaultValue null) { var opts new PromptIntegerOptions(prompt) { LowerLimit minValue, UpperLimit maxValue, AllowNone defaultValue.HasValue, DefaultValue defaultValue ?? 0 }; PromptIntegerResult result _editor.GetInteger(opts); if (result.Status PromptStatus.None defaultValue.HasValue) return defaultValue.Value; return result.Status PromptStatus.OK ? result.Value : null; }6.2 输入验证扩展opts.Validate (sender, e) { if (e.Value % 2 ! 0) { e.SetError(请输入偶数); return false; } return true; };7. 综合实战参数化图形生成结合五种交互方法实现柱状图生成器public void CreateParametricColumn() { var service new CadInteractionService(); service.ExecuteInTransaction(tr { // 获取基准点 var basePoint GetPointWithPreview(指定柱体基点, Point3d.Origin); if (!basePoint.HasValue) return; // 获取截面尺寸 double width GetBoundedInteger(输入截面宽度(mm), 100, 1000, 300) ?? 300; double depth GetBoundedInteger(输入截面深度(mm), 100, 1000, 300) ?? 300; // 获取高度 double height GetDynamicDistance(指定柱体高度, basePoint.Value) ?? 3000; // 创建实体 using (var poly new Polyline()) { poly.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0); poly.AddVertexAt(1, new Point2d(width, 0), 0, 0, 0); poly.AddVertexAt(2, new Point2d(width, depth), 0, 0, 0); poly.AddVertexAt(3, new Point2d(0, depth), 0, 0, 0); poly.Closed true; var extrusions new ListSolid3d(); using (var extrusion new Solid3d()) { extrusion.CreateExtrudedSolid(poly, new Vector3d(0, 0, height), new SweepOptions()); extrusions.Add(extrusion); } // 添加到模型空间 var bt (BlockTable)tr.GetObject(_doc.Database.BlockTableId, OpenMode.ForRead); var btr (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); foreach (var solid in extrusions) { btr.AppendEntity(solid); tr.AddNewlyCreatedDBObject(solid, true); } } }); }8. 异常处理与用户体验优化8.1 错误处理模式try { // 交互代码 } catch (Autodesk.AutoCAD.Runtime.Exception ex) { _editor.WriteMessage($\nCAD错误{ex.Message}); } catch (System.Exception ex) { _editor.WriteMessage($\n系统错误{ex.Message}); } finally { // 清理资源 }8.2 用户取消处理if (result.Status PromptStatus.Cancel) { _editor.WriteMessage(\n操作已取消); return; }8.3 性能优化建议对于复杂交互使用Editor.SwitchToModelessDialog()避免界面冻结大量实体操作时先收集所有输入再统一执行事务使用DisableUpdate()和EnableUpdate()控制图形刷新9. 高级技巧自定义Jig交互实现动态拖拽效果示例public class PointJig : EntityJig { private Point3d _position; private readonly string _prompt; public PointJig(Entity ent, string prompt) : base(ent) { _prompt prompt; } protected override SamplerStatus Sampler(JigPrompts prompts) { var opts new JigPromptPointOptions(_prompt); PromptPointResult result prompts.AcquirePoint(opts); if (_position.DistanceTo(result.Value) Tolerance.Global.EqualPoint) return SamplerStatus.NoChange; _position result.Value; return SamplerStatus.OK; } protected override bool Update() { if (Entity is DBPoint point) { point.Position _position; return true; } return false; } }10. 版本兼容性解决方案多版本支持策略使用条件编译指令#if ACAD2020 // 2020特有API #elif ACAD2023 // 2023新特性 #endif动态加载程序集Assembly LoadApiAssembly(string version) { string path $AcCoreMgd_{version}.dll; return Assembly.LoadFrom(path); }功能检测模式try { // 尝试调用新API } catch (MissingMethodException) { // 回退到旧版实现 }