在 AutoCAD C# 二次开发中,`DocumentCollectionEventHandler` 是一个委托(delegate),用于处理与 AutoCAD 文档集合(DocumentCollection)相关的事件。它属于 AutoCAD .NET API 的事件处理机制,本质上是一种**反应器(Reactor)模式**的实现,用于响应文档生命周期事件(如创建、激活、销毁文档等)。
本例为每激活一个文档,当前文档画一个圆。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
[assembly:CommandClass(typeof(IfoxDemo.DEMO))]
namespace IfoxDemo
{
public class DEMO
{
[CommandMethod("xx")]
public void CreatExcel()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
ed.WriteMessage("\n开始批量提取块属性");
}
}
public class DocumentEventReactor
{
public DocumentEventReactor()// 初始化时订阅事件
{
DocumentCollection docCol = Application.DocumentManager;
docCol.DocumentActivated += OnDocumentActivated;
}
// 订阅事件(仅允许调用一次)
public void Subscribe()
{
DocumentCollection docCol = Application.DocumentManager;
docCol.DocumentActivated -= OnDocumentActivated; // 避免重复订阅
docCol.DocumentActivated += OnDocumentActivated;
}
public void Unsubscribe() // 清理时取消订阅(重要!)
{
DocumentCollection docCol = Application.DocumentManager;
docCol.DocumentActivated -= OnDocumentActivated;
}
// 文档激活事件处理
public void OnDocumentActivated(object sender, DocumentCollectionEventArgs e)
{
Document activeDoc = e.Document;
Editor ed = activeDoc.Editor;
Database db = activeDoc.Database;
// 获取文档名称(不含路径)
string docName = System.IO.Path.GetFileName(activeDoc.Name);
// 在命令行显示提示
ed.WriteMessage($"\n切换到文档: {docName} | 事件类型: {e.GetType().Name}");
// 示例扩展操作:检查文档是否只读
if (activeDoc.IsReadOnly) ed.WriteMessage("\n警告:当前文档为只读模式!");//
// 锁定文档上下文(确保操作在正确文档中执行)
using (DocumentLock docLock = activeDoc.LockDocument())
{
Circle c = new Circle(new Point3d(0, 0, 0), Vector3d.ZAxis, 5.0);
c.ColorIndex = 1; // 设置颜色索引
Application.DocumentManager.MdiActiveDocument.Database.AddEntityToModeSpace(c); // 添加圆到模型空间
Application.DocumentManager.MdiActiveDocument.Editor.ZoomExtents(); // 缩放到适合视图
}
}
}
// 在插件入口初始化
//public class PluginCommands : IExtensionApplication
//{
// private static DocumentEventReactor _reactor;
// public void Initialize()
// {
// _reactor = new DocumentEventReactor();
// Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(
// "\n文档事件反应器已启动");
// }
// public void Terminate()
// {
// _reactor?.Unsubscribe();
// }
//}
}
他常用事件处理示例:
响应文档创建事件
Application.DocumentManager.DocumentCreated += (sender, e) =>
{
Editor ed = e.Document.Editor;
ed.WriteMessage($"\n新文档已创建: {e.Document.Name}");
};
```
#### 响应文档关闭事件
```csharp
Application.DocumentManager.DocumentToBeDestroyed += (sender, e) =>
{
// 保存自定义数据到外部文件
string backupPath = $"C:\\Backups\\{e.Document.Name}.settings";
SaveCustomData(e.Document, backupPath);
};
```
通过合理利用 `DocumentCollectionEventHandler`,您可以构建响应 AutoCAD 文档环境变化的智能插件,显著提升用户体验和自动化水平。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
[assembly:CommandClass(typeof(IfoxDemo.DEMO))]
namespace IfoxDemo
{
public class DEMO
{
[CommandMethod("xx")]
public void CreatExcel()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
ed.WriteMessage("\n开始批量提取块属性");
}
}
public class DocumentEventReactor
{
public static void DocumentEventReactor1()// 初始化时订阅事件
{
DocumentCollection docCol = Application.DocumentManager;
docCol.DocumentActivated += OnDocumentActivated;
// 也可以订阅其他事件,如 DocumentCreated、DocumentToBeDestroyed 等
docCol.DocumentToBeDeactivated += onDocumentToBeDeactivated; // 这里为了示例使用同一处理方法,实际可分开处理不同事件
docCol.DocumentToBeDestroyed += onDocumentToBeDeactivated; // 这里为了示例使用同一处理方法,实际可分开处理不同事件
}
// 订阅事件(仅允许调用一次)
public static void Subscribe()
{
DocumentCollection docCol = Application.DocumentManager;
docCol.DocumentActivated -= OnDocumentActivated; // 避免重复订阅
docCol.DocumentActivated += OnDocumentActivated;
}
public static void Unsubscribe() // 清理时取消订阅(重要!)
{
DocumentCollection docCol = Application.DocumentManager;
docCol.DocumentActivated -= OnDocumentActivated;
}
// 文档激活事件处理
public static void OnDocumentActivated(object sender, DocumentCollectionEventArgs e)
{
try
{
DocumentCollection dc = sender as DocumentCollection;
// if (dc == null) return; // 确保 sender 是 DocumentCollection
// 先取消旧订阅,避免重复
dc.MdiActiveDocument.ImpliedSelectionChanged -= Doc_ImpliedSelectionChanged;
dc.MdiActiveDocument.ImpliedSelectionChanged += Doc_ImpliedSelectionChanged; // 订阅 ImpliedSelectionChanged 事件
}
catch (Exception)
{
throw;
}
Document activeDoc = e.Document;
Editor ed = activeDoc.Editor;
Database db = activeDoc.Database;
// 获取文档名称(不含路径)
string docName = System.IO.Path.GetFileName(activeDoc.Name);
// 在命令行显示提示
ed.WriteMessage($"\n切换到文档: {docName} | 事件类型: {e.GetType().Name}");
// 示例扩展操作:检查文档是否只读
if (activeDoc.IsReadOnly) ed.WriteMessage("\n警告:当前文档为只读模式!");//
// 锁定文档上下文(确保操作在正确文档中执行)
using (DocumentLock docLock = activeDoc.LockDocument())
{
Circle c = new Circle(new Point3d(0, 0, 0), Vector3d.ZAxis, 5.0);
c.ColorIndex = 1; // 设置颜色索引
Application.DocumentManager.MdiActiveDocument.Database.AddEntityToModeSpace(c); // 添加圆到模型空间
// Application.DocumentManager.MdiActiveDocument.Editor.ZoomExtents(); // 缩放到适合视图
}
}
public static void onDocumentToBeDeactivated(object sender, DocumentCollectionEventArgs e)
{
try
{
DocumentCollection dc = sender as DocumentCollection;
// if (dc == null) return; // 确保 sender 是 DocumentCollection
dc.MdiActiveDocument.ImpliedSelectionChanged -= Doc_ImpliedSelectionChanged; // 订阅 ImpliedSelectionChanged 事件
}
catch (Exception)
{
throw;
}
}
// 文档隐含选择集变化事件处理
public static void Doc_ImpliedSelectionChanged(object sender, EventArgs e)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
using (DocumentLock dl = doc.LockDocument())
{
Editor ed = doc.Editor;
ed.WriteMessage("\nImpliedSelectionChanged 事件触发!");
// 获取当前选择集
var psr = ed.SelectImplied();
if (psr.Status != PromptStatus.OK) return;
// 开启事务
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
try
{
// 遍历选择集中的实体
foreach (ObjectId id in psr.Value.GetObjectIds())
{
// 通过事务获取实体(需指定OpenMode)
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent != null)
{
// 在命令行显示实体类型和ID
ed.WriteMessage($"\n实体类型: {ent.GetType().Name}, ID: {id}");
// 此处若需要修改实体,需将OpenMode设为ForWrite并在事务中提交
}
}
// 事务完成后提交(只读操作可省略,但建议显式调用以明确意图)
tr.Commit();
}
catch (Exception ex)
{
ed.WriteMessage($"\n事务处理错误: {ex.Message}");
tr.Abort(); // 异常时回滚事务
}
//try
//{
// // 1. 创建空的选择集
// SelectionSet emptySelection = null;
// // 2. 使用SetImpliedSelection设置空选择集,清空当前选择
// ed.SetImpliedSelection(emptySelection);
// ed.WriteMessage("\n当前选择集已清空!");
//}
//catch (Exception ex)
//{
// ed.WriteMessage($"\n清空选择集失败: {ex.Message}");
//}
}
}
}
}
public class MyPlugin2 : IExtensionApplication
{
public void Initialize()
{
string str = "";//"输入命令\"ywxl\"执行 \n";
Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"\n插件已加载!(CAD插件定制:山水qq443440204)\n{str}\n");
DocumentEventReactor.Subscribe(); // 订阅事件(仅一次)
Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n文档事件反应器已启动");
}
public void Terminate()
{
//Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\n结束");
DocumentEventReactor.Unsubscribe();
}
}
}