事件监听 ——CAD C#二次开发

一、AutoCAD .NET API 事件机制

  1. 事件监听核心
  • Database.ModifyObjects 事件

当数据库中的实体(如图形对象)发生修改时触发,包括:

  • 几何属性变更(移动、缩放、旋转)。

  • 非几何属性变更(颜色、线型、图层)。

  • 删除或复制操作(需结合事件参数判断)。

  • 事件参数 ObjectModifiedEventArgs

  • GetModifiedObjectIds(OpenMode) :获取修改的实体ID列表, OpenMode 控制访问权限(如 ForRead 或 ForWrite )。

  • 通过遍历实体ID,获取对应的 Entity 对象进行操作。

二、实体移动检测原理

  1. 几何包围盒( GeometricExtents )
  • 定义:

每个实体( Entity )都有一个 GeometricExtents 属性,表示其在三维空间中的最小包围盒,包含:

  • MinPoint :包围盒最小角点坐标(X,Y,Z)。

  • MaxPoint :包围盒最大角点坐标(X,Y,Z)。

  • 中心点计算:

中心点 = (MinPoint + MaxPoint) / 2 ,用于表征实体的位置。

移动判断逻辑:若修改前后中心点坐标差异超过阈值(如 1e-9 ),则认为实体发生移动

核心逻辑流程

  1. 事件注册:

通过 RegisterIndexEvent 命令绑定 ModifyObjects 事件,开始监听实体修改。

  1. 移动检测:
  • 遍历所有修改的实体,获取新旧版本的包围盒中心点。

  • 对比中心点差异,判断是否为移动操作。

  1. 颜色变更:
  • 生成随机 ColorIndex ,排除绿色(3号)和当前颜色索引。

  • 直接设置 entity.ColorIndex = newIndex ,触发视觉更新。

  1. 事件注销:

通过 UnregisterIndexEvent 移除事件监听,释放资源。

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using System;

public class ColorIndexChangeDemo

{

private Document doc;

private Database db;

private Editor ed;

private const int GreenColorIndex = 3; // 绿色对应的ColorIndex(3号色为标准绿色)

private readonly Random random = new Random();

CommandMethod("RegisterIndexEvent")

public void RegisterIndexEvent()

{

doc = Application.DocumentManager.MdiActiveDocument;

db = doc.Database;

ed = doc.Editor;

db.ModifyObjects += OnEntityMoved; // 注册移动事件

ed.WriteMessage("\n已启用ColorIndex变色功能(避免3号绿色)");

}

private void OnEntityMoved(object sender, ObjectModifiedEventArgs e)

{

try

{

using (Transaction trans = doc.TransactionManager.StartTransaction())

{

foreach (ObjectId objId in e.GetModifiedObjectIds(OpenMode.ForWrite))

{

Entity entity = trans.GetObject(objId, OpenMode.ForWrite) as Entity;

if (entity == null) continue;

// 检测移动(基于包围盒中心点)

if (IsEntityMoved(entity, trans))

{

ChangeColorByIndex(entity); // 修改ColorIndex

ed.WriteMessage($"\n实体{entity.GetType().Name}颜色已更新为索引{entity.ColorIndex}");

}

}

trans.Commit();

}

}

catch (Exception ex)

{

ed.WriteMessage($"\n错误:{ex.Message}");

}

}

/// <summary>

/// 检测实体移动(包围盒中心点变化)

/// </summary>

private bool IsEntityMoved(Entity entity, Transaction trans)

{

using (DBObject oldObj = trans.GetObject(entity.Id, OpenMode.ForRead, true))

{

if (oldObj is not Entity oldEntity) return false;

return !GetCenter(oldEntity).IsEqualTo(GetCenter(entity), 1e-9);

}

}

/// <summary>

/// 获取包围盒中心点

/// </summary>

private Point3d GetCenter(Entity entity)

{

GeometricExtents extents = entity.GeometricExtents;

return extents.IsValid ?

new Point3d((extents.MinPoint.X + extents.MaxPoint.X)/2,

(extents.MinPoint.Y + extents.MaxPoint.Y)/2,

(extents.MinPoint.Z + extents.MaxPoint.Z)/2) :

Point3d.Origin;

}

/// <summary>

/// 安全修改ColorIndex(避开绿色和当前索引)

/// </summary>

private void ChangeColorByIndex(Entity entity)

{

int currentIndex = entity.ColorIndex; // 获取当前索引

int newIndex;

do

{

// 生成1-255的随机索引(ColorIndex范围:0=随层,1-255为具体颜色)

newIndex = random.Next(1, 256);

} while (newIndex == GreenColorIndex || newIndex == currentIndex); // 排除绿色和当前索引

entity.ColorIndex = newIndex; // 直接设置索引

}

CommandMethod("UnregisterIndexEvent")

public void UnregisterIndexEvent()

{

if (db != null)

{

db.ModifyObjects -= OnEntityMoved;

ed.WriteMessage("\n已停止ColorIndex变色功能");

}

}

}

相关推荐
暴走约伯17 小时前
【VFX工具链源码拆解 09】终极工业化闭环:基于 ID 规则驱动的全自动场景建档、骨骼挂载与男转女场景迁移
unity·c#·游戏引擎·材质
用户788477316342 天前
WinForms 迁移 WPF:Upgrade Assistant 覆盖 30%,剩下 70% 我手写了六周
c#
寂寞的船2 天前
【Unity知识速递】第13期 Unity 内存泄漏排查实战:从 Memory Profiler 到 Lua 引用泄漏的生产级全链路诊断
unity·junit·c#·游戏引擎·lua
用户3721574261352 天前
C# 提取 PDF 附件:包括文档附件和页面注释附件
c#
寂寞的船2 天前
【Unity Bug挑战】第12期 Awaitable 二次 await 死锁之谜 —— 为什么同一个异步操作等两次就卡死?
unity·c#·游戏引擎·bug
huaqianzkh4 天前
WinForm C#:循环修改控件UI闪烁卡顿?SuspendLayout / ResumeLayout 与 BeginUpdate 优化
开发语言·ui·c#
用户3721574261355 天前
C# 实现 Excel 单元格保护:锁定公式并允许编辑指定区域
c#·ai编程·编程语言
公子小六5 天前
基于.NET的Windows窗体编程之WinForms数据持久化(1)
windows·microsoft·c#·.net·winforms
三雷科技5 天前
第6章第4节:自定义分词器
开发语言·c#
zhanghaha13145 天前
C# 系列教程_12 字符串 string 保姆级系统教程(面向新手,大量示例 + 原理讲解)
开发语言·数据库·c#