
- using Autodesk.AutoCAD.DatabaseServices;
- using Autodesk.AutoCAD.EditorInput;
- using Autodesk.AutoCAD.Geometry;
- using Autodesk.AutoCAD.Runtime;
- /// <summary>
- /// 带方向的多重引线绘制交互类
- /// 继承自EntityJig,用于通过用户交互动态创建带方向的多重引线(MLeader)
- /// 支持实时更新引线终点位置,并根据终点与起点的位置关系自动调整文字方向
- /// </summary>
- public class DirectionalLeaderJig : EntityJig
- {
- #region 私有字段
- /// <summary>
- /// 引线的固定起点坐标(用户初始指定的起点)
- /// </summary>
- private readonly Point3d _start;
- /// <summary>
- /// 引线的实时终点坐标(用户鼠标移动/输入的动态终点)
- /// </summary>
- private Point3d _end;
- /// <summary>
- /// 多重引线中引线簇的索引(用于标识当前操作的引线簇)
- /// </summary>
- private int _index;
- /// <summary>
- /// 引线簇中线段的索引(用于标识当前操作的线段)
- /// </summary>
- private int _lineIndex;
- /// <summary>
- /// 绘制状态标记:true表示已开始绘制(引线已初始化),false表示未开始
- /// 用于避免起点与终点过近时误创建引线
- /// </summary>
- private bool _started;
- /// <summary>
- /// 与引线关联的多行文字对象(存储引线的文字内容及格式)
- /// </summary>
- private readonly MText _mtext;
- #endregion
- #region 构造函数
- /// <summary>
- /// 初始化DirectionalLeaderJig实例
- /// </summary>
- /// <param name="start">引线的固定起点坐标</param>
- /// <param name="ld">需要交互绘制的多重引线对象</param>
- /// <param name="mtext">与引线关联的多行文字对象(包含文字内容和格式)</param>
- public DirectionalLeaderJig(Point3d start, MLeader ld, MText mtext) : base(ld)
- {
- _start = start; // 初始化起点(固定不变)
- _end = start; // 初始终点设为起点(避免初始位置异常)
- _started = false; // 初始标记为未开始绘制
- _mtext = mtext; // 关联多行文字对象
- }
- #endregion
- #region 重写方法
- /// <summary>
- /// 输入采样处理:获取用户实时输入的引线终点坐标
- /// 继承自EntityJig,用于处理用户交互输入
- /// </summary>
- /// <param name="prompts">交互提示对象,用于获取用户输入</param>
- /// <returns>采样状态:NoChange(坐标未变)、OK(输入有效)、Cancel(用户取消)</returns>
- protected override SamplerStatus Sampler(JigPrompts prompts)
- {
- // 创建点输入提示,指导用户操作
- var pointOptions = new JigPromptPointOptions("\n指定引线终点或[右键取消]: ");
-
- // 配置输入规则:允许3D坐标输入,不接受空响应(避免误操作)
- pointOptions.UserInputControls =
- UserInputControls.Accept3dCoordinates |
- UserInputControls.NoNegativeResponseAccepted;
- // 获取用户输入的点
- PromptPointResult inputResult = prompts.AcquirePoint(pointOptions);
- // 若输入的终点与当前终点相同,返回无变化状态(避免无效更新)
- if (_end == inputResult.Value)
- {
- return SamplerStatus.NoChange;
- }
- // 若用户输入有效,更新终点坐标并返回成功状态
- else if (inputResult.Status == PromptStatus.OK)
- {
- _end = inputResult.Value;
- return SamplerStatus.OK;
- }
- // 其他情况(如用户按ESC取消),返回取消状态
- return SamplerStatus.Cancel;
- }
- /// <summary>
- /// 更新引线几何图形:根据实时终点坐标动态调整引线形状和文字方向
- /// 继承自EntityJig,在用户输入变化时触发
- /// </summary>
- /// <returns>是否更新成功(始终返回true,确保交互流畅)</returns>
- protected override bool Update()
- {
- // 将当前操作的实体转换为多重引线对象(构造函数传入的是MLeader,转换安全)
- MLeader leader = (MLeader)Entity;
- // 首次初始化:当起点与终点距离超过容差时,创建引线基础结构
- if (!_started)
- {
- // 检查起点与终点的距离是否超过全局点容差(避免点击过近时误创建)
- if (_start.DistanceTo(_end) > Tolerance.Global.EqualPoint)
- {
- // 配置引线内容:关联多行文字(而非块或其他类型)
- leader.ContentType = ContentType.MTextContent;
- leader.MText = _mtext; // 绑定预设的多行文字对象
- // 创建引线簇和线段结构
- _index = leader.AddLeader(); // 添加新的引线簇
- _lineIndex = leader.AddLeaderLine(_index); // 在簇中添加线段
- // 设置线段的起点和初始终点
- leader.AddFirstVertex(_lineIndex, _start); // 线段起点固定为初始起点
- leader.AddLastVertex(_lineIndex, _end); // 线段终点设为当前输入终点
- _started = true; // 标记为已开始绘制(后续进入更新逻辑)
- }
- }
- // 后续更新:已创建引线后,实时调整终点位置
- else
- {
- leader.Visible = true; // 强制显示引线(避免初始化时的闪烁问题)
- leader.SetLastVertex(_lineIndex, _end); // 更新线段终点为最新输入坐标
- }
- // 调整文字方向:根据终点与起点的X坐标关系设置狗腿线方向
- if (_started)
- {
- // 狗腿线方向向量:终点在起点右侧则向右(X正方向),左侧则向左(X负方向)
- Vector3d doglegVector = new Vector3d(
- _end.X >= _start.X ? 1 : -1, // X方向:右侧为正,左侧为负
- 0, 0 // Y、Z方向不变
- );
- leader.SetDogleg(_index, doglegVector); // 应用狗腿线方向,确保文字朝向正确
- }
- return true; // 确认更新成功
- }
- #endregion
- }

- using Autodesk.AutoCAD.ApplicationServices;
- using Autodesk.AutoCAD.DatabaseServices;
- using Autodesk.AutoCAD.EditorInput;
- using Autodesk.AutoCAD.Runtime;
- /// <summary>
- /// 方向性多重引线命令类
- /// 包含创建带方向的多重引线(MLeader)的核心命令逻辑
- /// 支持用户输入文字内容、指定起点,并通过动态拖动(Jig)实时调整引线终点
- /// </summary>
- public class DirectionalLeaderCommands
- {
- /// <summary>
- /// 创建方向性引线的命令入口(命令名:DL)
- /// 执行流程:获取文字内容 → 获取起点 → 创建引线相关对象 → 启动动态拖动 → 提交数据库操作
- /// </summary>
- [CommandMethod("DL")]
- public void DirectionalLeader()
- {
- // 获取当前活动文档及编辑器(用于用户交互)和数据库(用于对象存储)
- Document doc = Application.DocumentManager.MdiActiveDocument;
- Editor editor = doc.Editor;
- Database db = doc.Database;
- #region 步骤1:获取用户输入的文字内容
- // 创建文字输入选项,允许包含空格(支持多单词内容)
- PromptStringOptions textInputOptions = new PromptStringOptions("\n输入文字内容: ");
- textInputOptions.AllowSpaces = true;
- // 执行文字输入并检查结果
- PromptResult textInputResult = editor.GetString(textInputOptions);
- if (textInputResult.Status != PromptStatus.OK)
- {
- // 用户取消输入或输入失败,直接退出命令
- editor.WriteMessage("\n文字内容输入取消或失败。");
- return;
- }
- #endregion
- #region 步骤2:获取用户指定的引线起点
- // 提示用户指定引线起点
- PromptPointResult startPointResult = editor.GetPoint("\n指定引线起点: ");
- if (startPointResult.Status != PromptStatus.OK)
- {
- // 用户取消选择或选择失败,退出命令
- editor.WriteMessage("\n引线起点选择取消或失败。");
- return;
- }
- Point3d leaderStartPoint = startPointResult.Value; // 保存起点坐标
- #endregion
- #region 步骤3:数据库事务处理(创建并存储引线对象)
- // 使用using语句自动管理事务生命周期(确保异常时自动回滚)
- using (Transaction transaction = db.TransactionManager.StartTransaction())
- {
- try
- {
- // 打开块表(只读,用于获取当前空间)
- BlockTable blockTable = (BlockTable)transaction.GetObject(
- db.BlockTableId,
- OpenMode.ForRead,
- false
- );
- // 打开当前空间块表记录(可写,用于添加新对象)
- BlockTableRecord currentSpace = (BlockTableRecord)transaction.GetObject(
- db.CurrentSpaceId,
- OpenMode.ForWrite,
- false
- );
- // 确保文字样式已创建并设置(调用外部文字处理逻辑)
- 文字相关.CreateAndSetTextStyle();
- #region 创建多重引线样式及相关对象
- // 创建自定义多重引线样式(样式名:XPF_MLeader),返回样式ID
- ObjectId mLeaderStyleId = 多重引线相关.CreateMleaderStyle("XPF_MLeader");
- // 打开样式对象(只读,用于配置多行文字)
- MLeaderStyle mLeaderStyle = (MLeaderStyle)transaction.GetObject(
- mLeaderStyleId,
- OpenMode.ForRead
- );
- // 创建多重引线对象(初始不可见,避免拖动前闪烁)
- MLeader multiLeader = new MLeader();
- multiLeader.MLeaderStyle = mLeaderStyleId; // 应用自定义样式
- multiLeader.Visible = false; // 初始隐藏,拖动时再显示
- // 创建多行文字对象(MText):绑定样式、设置内容(带宽度因子0.8)和高度0.75
- MText leaderText = CreateMtext(
- mLeaderStyle,
- $"{{\\W0.8x{textInputResult.StringResult}}}", // 文字内容带宽度因子格式
- 0.75 // 文字高度
- );
- #endregion
- #region 启动动态拖动(Jig)交互
- // 初始化Jig对象:传入起点、多重引线、多行文字
- DirectionalLeaderJig leaderJig = new DirectionalLeaderJig(
- leaderStartPoint,
- multiLeader,
- leaderText
- );
- // 将多重引线添加到当前空间并注册到事务(确保数据库跟踪)
- currentSpace.AppendEntity(multiLeader);
- transaction.AddNewlyCreatedDBObject(multiLeader, true);
- // 启动动态拖动:用户通过鼠标移动实时调整引线终点
- PromptResult dragResult = editor.Drag(leaderJig);
- #endregion
- #region 提交或回滚事务
- if (dragResult.Status == PromptStatus.OK)
- {
- // 拖动成功,提交事务(永久保存所有对象到数据库)
- transaction.Commit();
- editor.WriteMessage("\n方向性引线创建成功。");
- }
- else
- {
- // 拖动取消或失败,事务自动回滚(不保存任何对象)
- editor.WriteMessage("\n引线创建已取消。");
- }
- #endregion
- }
- catch (System.Exception ex)
- {
- // 捕获异常并提示错误信息
- editor.WriteMessage($"\n命令执行出错:{ex.Message}");
- // 异常时事务自动回滚,无需手动处理
- }
- }
- #endregion
- }
- /// <summary>
- /// 创建并配置与多重引线关联的多行文字对象(MText)
- /// </summary>
- /// <param name="style">关联的多重引线样式(用于继承基础格式)</param>
- /// <param name="content">文字内容(支持格式化代码,如宽度因子)</param>
- /// <param name="height">文字高度</param>
- /// <returns>配置完成的MText对象</returns>
- private MText CreateMtext(MLeaderStyle style, string content, double height)
- {
- MText mtext = new MText();
- mtext.Contents = content; // 设置文字内容(含格式)
- mtext.Height = height; // 设置文字高度
- // 可根据需要添加更多格式配置(如颜色、字体等,可从style继承)
- return mtext;
- }
- }