AutoCAD 2023 .NET C#中AddTransient无法绘制临时线条问题求助
鼠标悬停线条时无法显示偏移临时线条的问题
我需要实现鼠标悬停在线条上时,绘制一条偏移固定距离的临时线条,但调用ctm.AddTransient(line, AcGi.TransientDrawingMode.Main, 128, ints)后,临时线条完全不显示。此前用该方法添加块引用(bref),搭配AcGi.TransientDrawingMode.DirectShortTerm模式可正常工作。
已尝试的无效操作:
- 切换
AcGi.TransientDrawingMode.Main和DirectShortTerm模式 - 将临时线条坐标改为固定值
- 添加
ctm.UpdateTransient(bref, ints)方法
原代码
using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.EditorInput; using System; using AcGi = Autodesk.AutoCAD.GraphicsInterface; public class PointMonitorTooltips { [CommandMethod("SM")] public static void StartMonitor() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.PointMonitor += new PointMonitorEventHandler(ed_PointMonitor); } [CommandMethod("XM")] public static void StopMonitor() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.TurnForcedPickOn(); ed.PointMonitor - new PointMonitorEventHandler(ed_PointMonitor); } static void ed_PointMonitor(object sender, PointMonitorEventArgs e) { Editor ed = (Editor)sender; AcGi.TransientManager ctm = AcGi.TransientManager.CurrentTransientManager; IntegerCollection ints = new IntegerCollection(new int[] { }); try { FullSubentityPath[] paths = e.Context.GetPickedEntities(); // Open a transaction to create the transient line using (Transaction tr = ed.Document.TransactionManager.StartTransaction()) { foreach (FullSubentityPath path in paths) { ObjectId[] ids = path.GetObjectIds(); if (ids.Length > 0) { ObjectId id = ids[ids.GetUpperBound(0)]; // Get the entity Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead); Type objtype = ent.GetType(); // Create a transient line based on the entity's position and orientation if (objtype == typeof(Line)) { Line linecoor = (Line)ent.Clone(); Point3d start = linecoor.StartPoint; start = start.Add(new Vector3d(5.0, 5.0, 0.0)); Point3d end = linecoor.EndPoint; end = end.Add(new Vector3d(5.0, 5.0, 0.0)); Line line = new Line(start, end); // Add the transient line ed.WriteMessage("\nAdding transient line..."); // This part constantly sending messages ctm.AddTransient(line, AcGi.TransientDrawingMode.Main, 128, ints); // This is the part that is not working } } } tr.Commit(); } } catch { // Exception handling code here } } }
具体解决建议
1. 修复StopMonitor方法的语法错误
原代码中移除事件的语句少了=,导致事件无法正常移除,修改为:
ed.PointMonitor -= new PointMonitorEventHandler(ed_PointMonitor);
2. 每次触发时清理旧的临时图形
PointMonitor事件会随鼠标移动频繁触发,每次都会添加新的临时线条,旧的线条不会自动清除,会导致显示异常。在添加新线条前先清除同模式下的旧线条:
// 在try块开头添加 ctm.EraseTransients(AcGi.TransientDrawingMode.DirectShortTerm, 1, ints);
3. 移除不必要的事务
临时线条是内存中的图形,不需要加入AutoCAD数据库,因此不需要用Transaction包裹,直接打开实体使用即可(用完记得关闭):
// 替换原事务内的代码 foreach (FullSubentityPath path in paths) { ObjectId[] ids = path.GetObjectIds(); if (ids.Length > 0) { ObjectId id = ids[ids.GetUpperBound(0)]; using (Entity ent = (Entity)id.Open(OpenMode.ForRead)) { if (ent is Line lineEntity) { // 创建偏移线条 Point3d start = lineEntity.StartPoint.Add(new Vector3d(1.0, 1.0, 0.0)); Point3d end = lineEntity.EndPoint.Add(new Vector3d(1.0, 1.0, 0.0)); using (Line transLine = new Line(start, end)) { // 使用DirectShortTerm模式,优先级设为1(最高) ctm.AddTransient(transLine, AcGi.TransientDrawingMode.DirectShortTerm, 1, ints); } } } } }
4. 选择合适的临时图形模式
DirectShortTerm模式适合动态临时图形,它会在AutoCAD下次刷新时自动清除,更适合鼠标悬停这种高频触发的场景,避免手动清理的麻烦。
5. 确保线条在视图范围内
可以先把偏移量改小(比如1.0),避免偏移后的线条超出当前视图导致看不到;同时确保线条的坐标系与当前空间一致(模型空间用世界坐标,布局空间注意转换)。
修改后的完整代码
using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.EditorInput; using System; using AcGi = Autodesk.AutoCAD.GraphicsInterface; public class PointMonitorTooltips { [CommandMethod("SM")] public static void StartMonitor() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.PointMonitor += new PointMonitorEventHandler(ed_PointMonitor); ed.WriteMessage("\n点监视器已启动,鼠标悬停线条查看偏移临时线"); } [CommandMethod("XM")] public static void StopMonitor() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.TurnForcedPickOn(); ed.PointMonitor -= new PointMonitorEventHandler(ed_PointMonitor); // 停止时清除所有临时线条 AcGi.TransientManager.CurrentTransientManager.EraseTransients(AcGi.TransientDrawingMode.DirectShortTerm, 1, new IntegerCollection()); ed.WriteMessage("\n点监视器已停止"); } static void ed_PointMonitor(object sender, PointMonitorEventArgs e) { Editor ed = (Editor)sender; AcGi.TransientManager ctm = AcGi.TransientManager.CurrentTransientManager; IntegerCollection ints = new IntegerCollection(new int[] { }); try { FullSubentityPath[] paths = e.Context.GetPickedEntities(); // 先清除旧的临时线条 ctm.EraseTransients(AcGi.TransientDrawingMode.DirectShortTerm, 1, ints); foreach (FullSubentityPath path in paths) { ObjectId[] ids = path.GetObjectIds(); if (ids.Length > 0) { ObjectId id = ids[ids.GetUpperBound(0)]; using (Entity ent = (Entity)id.Open(OpenMode.ForRead)) { if (ent is Line lineEntity) { // 创建偏移1单位的线条 Point3d start = lineEntity.StartPoint.Add(new Vector3d(1.0, 1.0, 0.0)); Point3d end = lineEntity.EndPoint.Add(new Vector3d(1.0, 1.0, 0.0)); using (Line transLine = new Line(start, end)) { // 设置临时线条颜色(可选,方便区分) transLine.ColorIndex = 1; // 红色 ctm.AddTransient(transLine, AcGi.TransientDrawingMode.DirectShortTerm, 1, ints); } } } } } } catch (Exception ex) { ed.WriteMessage($"\n错误:{ex.Message}"); } } }
内容的提问来源于stack exchange,提问作者Ali Bera Kurunç
相关产品推荐
相关产品推荐

