事件监听 ——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变色功能");

}

}

}

相关推荐
CoderIsArt3 小时前
C#中的CLR属性、依赖属性与附加属性
c#
IGP98 小时前
20250606-C#知识:委托和事件
开发语言·c#
Kookoos9 小时前
ABP VNext 与 Neo4j:构建基于图数据库的高效关系查询
数据库·c#·.net·neo4j·abp vnext
张鱼小丸子_微辣9 小时前
.Net Framework 4/C# LINQ*
c#
..活宝..11 小时前
【Emgu CV教程】11.2、Scharr边缘检测
图像处理·计算机视觉·c#·emgu cv·图像分析
The Kite12 小时前
MPLAB X IDE 软件安装与卸载
ide·c#·嵌入式
张鱼小丸子_微辣15 小时前
.Net Framework 4/C# 集合和索引器
c#
布伦鸽15 小时前
C# WPF 左右布局实现学习笔记(1)
笔记·学习·c#·wpf
InCerry16 小时前
C# 模式匹配全解:原理、用法与易错点
c#