You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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ç

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:02:54