当前位置: 首页 > backend >正文

objectArx ---反应器

目录

  • 一、概述
    • 1.1 概念
    • 1.2 种类
  • 二、数据库反应器
    • 2.1 反应器创建
    • 2.2 类文件修改
    • 2.3 注册卸载反应器
  • 三、编辑反应器
    • 3.1 反应器创建
    • 3.2 类文件修改
    • 3.3 注册卸载反应器
  • 四、配置文件管理器反应器
    • 4.1 反应器创建
    • 4.2 类文件修改
    • 4.3 测试文件
    • 4.4 效果
  • 五、上下文反应器
    • 5.1 反应器创建
    • 5.2 类文件修改
    • 5.3 注册卸载反应器
    • 5.4 效果

一、概述

1.1 概念

  • 定义:反应器机制是观察者模式(设计模式)的一种实现,在该机制下,有事件通知者事件接收者,负责接收事件的称为反应器
  • 反应器列表:在反应器可以从通知者处接收消息之前,必须显式地将反应器添加到通知者的反应器列表中(观察者模式中的通知对象列表)。
  • 反应器部分类继承关系
    在这里插入图片描述

1.2 种类

  • 常用反应器种类
    类型派生示例
    数据库反应器派生于AcDbDatabaseReactor,负责接收与数据库状态相关的事件对象被加入、删除、修改到数据库中,这种反应器的通知发送者是数据库,此种反应器被加入到数据库的反应器列表中
    对象反应器(自定义类中详述)派生于AcDbObjectReactor
    负责接收对象(object)级别的事件
    复制、删除、修改一个对象,它也可以被加入到任何AcDbObject对象的反应器列表中
    编辑反应器派生于AcEditorReactor
    负责接收AutoCAD的特殊事件
    例如加载或卸载一张图,开始或结束一个命令以及其他类型的用户交互。AcEditor对象是AcEditorReactor反应器的唯一通知发送者
    配置文件管理器反应器派生于AcApProfileManagerReactor,负责接收配置文件操作的事件例如对配置文件的增删改查
    输入上下文反应器派生于AcEdInputContextReactor,负责接收用户输入动作的事件例如:用户在屏幕上点选、获取角度、获取距离等

  • 反应器使用原则
    • 不要依赖反应器激活的顺序
    • 不要依赖通知间操作的顺序:通知只负责告知有无不负责先后
    • 不要在通知回调函数中使用任何用户交互函数

  • 临时反应器
    • 使用过程:从ARX内建的一系列反应器类中挑选一个合适的类派生,实现相关函数并注册反应器。
    • 特点:非数据库对象,由开发者负责注册、卸载
    • 包含:数据库反应器、编辑反应器

  • 永久反应器
    • 特点:永久反应器由AutoCAD负责删除
    • 包含:对象反应器

二、数据库反应器

2.1 反应器创建

  • 向导创建
    在这里插入图片描述
    在这里插入图片描述

2.2 类文件修改

  • CDatabaseReactor.h
    class /*DLLIMPEXP*/ CDatabaseReactor : public AcDbDatabaseReactor {...	
    public:...	// 重写基类AcDbDatabaseReactor 相应方法virtual void objectAppended(const AcDbDatabase* dwg, const AcDbObject* dbObj);virtual void objectModified(const AcDbDatabase* dwg, const AcDbObject* dbObj);virtual void objectErased(const AcDbDatabase* dwg, const AcDbObject* dbObj,Adesk::Boolean bErased);
    } ;
    ...
    
  • CDatabaseReactor.cpp
    #include "StdAfx.h"
    #include "CDatabaseReactor.h"// 定义全局变量
    class CDatabaseReactor;
    CDatabaseReactor *pDRec = NULL;...	void printObj(const AcDbObject* pObj)
    {	// 纠错:防止传入空对象if (pObj == NULL){acutPrintf(_T("(NULL)"));return;}// 句柄:用于获取对象句柄对象AcDbHandle objHand;// 句柄名称:用于获取对象句柄名称字符串ACHAR handbuf[128];// 获取 句柄对象 的方法pObj->getAcDbHandle(objHand);// 获取 对象句柄 名称字符串 方法:通过句柄对象objHand.getIntoAsciiBuffer(handbuf, 128);// s表示字符串,l表示数据为长整型,x表示输出十六进制acutPrintf(_T("\n (类名:%s, 句柄:%s, 对象id:%lx)"), // 类名pObj->isA()->name(), // 句柄对象 名称handbuf, // asOldId方法:将对象id转换为长整型 long 格式pObj->objectId().asOldId());
    }// 新增实体后,反应器进行的操作
    void CDatabaseReactor::objectAppended(const AcDbDatabase* dwg, const AcDbObject* dbObj)
    {acutPrintf(_T("\n调用反应器 对象新增 方法"));printObj(dbObj);
    }// 修改实体后,反应器进行的操作
    void CDatabaseReactor::objectModified(const AcDbDatabase* dwg, const AcDbObject* dbObj)
    {acutPrintf(_T("\n调用反应器 对象修改 方法"));printObj(dbObj);
    }// 删除实体后,反应器进行的操作
    void CDatabaseReactor::objectErased(const AcDbDatabase* dwg, const AcDbObject* dbObj, 
    Adesk::Boolean bErased)
    {if (bErased){acutPrintf(_T("\n调用反应器 对象删除 方法"));printObj(dbObj);}else{acutPrintf(_T("\n调用反应器 对象删除 方法(恢复删除)"));printObj(dbObj);}
    }
    

2.3 注册卸载反应器

  • Commands.h
    #include "stdafx.h"void AddCommands();
    void addReactor();
    void removeReactor();
    
  • Commands.cpp
    #include "stdafx.h"
    #include "Commands.h"
    #include "Editor.h"
    #include "CDatabaseReactor.h"
    // 声明全局变量pDRec:数据库反应器指针
    extern CDatabaseReactor *pDRec;void AddCommands()
    {	Editor::AddCommand(L"c-addReactor", ACRX_CMD_MODAL, addReactor);Editor::AddCommand(L"c-removeReactor", ACRX_CMD_MODAL, removeReactor);
    }void addReactor()
    {if (pDRec == NULL){		      pDRec = new CDatabaseReactor();}// 在当前活动数据库中添加 数据库反应器acdbHostApplicationServices()->workingDatabase()->addReactor(pDRec);acutPrintf(_T("\n反应器已经添加!"));
    }void removeReactor()
    {if (pDRec){// 在当前活动数据库中删除 数据库反应器acdbHostApplicationServices()->workingDatabase()->removeReactor(pDRec);// 释放内存delete pDRec;// 重置指针pDRec = NULL;}acutPrintf(_T("\n数据库反应器已经删除!"));
    }
    

    遇到问题:拉伸操作,CAD也会调用反应器删除、修改函数

三、编辑反应器

3.1 反应器创建

  • 向导创建
    在这里插入图片描述
    在这里插入图片描述

3.2 类文件修改

  • CEditorreactor.h

    class CEditorreactor : public AcEditorReactor {...
    public:...virtual void commandWillStart(const ACHAR* cmdStr);virtual void commandEnded(const ACHAR* cmdStr);
    } ;
    
  • CEditorreactor.cpp

    #include "StdAfx.h"
    #include "CEditorreactor.h"
    // 添加一个全局变量
    CEditorreactor *pERec = NULL;
    ...	
    // 重写命令执行前操作
    void CEditorreactor::commandWillStart(const ACHAR* cmdStr)
    {acutPrintf(_T("\n命令【%s】开始执行"), cmdStr);
    }// 命令执行后操作
    void CEditorreactor::commandEnded(const ACHAR* cmdStr)
    {acutPrintf(_T("\n命令【%s】执行完毕"), cmdStr);
    }
    

3.3 注册卸载反应器

  • Commands.h
    #include "stdafx.h"void AddCommands();
    void AttacthEditor();
    void RemoveEditor();
    
  • Commands.cpp
    #include "stdafx.h"
    #include "Commands.h"
    #include "Editor.h"
    #include "CEditorreactor.h"extern CEditorreactor *pERec;void AddCommands()
    {	Editor::AddCommand(L"c-addReactor", ACRX_CMD_MODAL, AttacthEditor);Editor::AddCommand(L"c-removeReactor", ACRX_CMD_MODAL, RemoveEditor);
    }void AttacthEditor()
    {if (pERec == NULL){pERec = new CEditorreactor();	}// 添加编辑反应器方法pERec->Attach();
    }void RemoveEditor()
    {if (pERec){	// 卸载编辑反应器方法pERec->Detach();// 释放CEditorreactor对象内存delete pERec;// 重置指针pERec = NULL;}
    }
    

四、配置文件管理器反应器

4.1 反应器创建

  • 向导创建
    在这里插入图片描述
    在这里插入图片描述

4.2 类文件修改

  • CProfileManReactor.h

    class CProfileManReactor : public AcApProfileManagerReactor {...	
    public:...	virtual void currentProfileWillChange(const ACHAR *newProfile);virtual void currentProfileChanged(const ACHAR *newProfile);
    } ;
    
  • CProfileManReactor.cpp

    ...
    void CProfileManReactor::currentProfileWillChange(const ACHAR *newProfile)
    {acutPrintf(_T("\n/*******当前配置文件将要改变:%s*******/"), newProfile);
    }void CProfileManReactor::currentProfileChanged(const ACHAR *newProfile)
    {acutPrintf(_T("\n/*******当前配置文件已经被改变:%s*******/"), newProfile);
    }
    

4.3 测试文件

  • 注:包含配置文件操作、添加删除反应器语句
  • Commands.h
    #include "stdafx.h"void AddCommands();
    void ProfileManReactor();
    
  • Commands.cpp
    #include "stdafx.h"
    #include "Commands.h"
    #include "Editor.h"
    #include "CProfileManReactor.h"void AddCommands()
    {	Editor::AddCommand(L"c-addReactor", ACRX_CMD_MODAL, ProfileManReactor);
    }// 配置文件管理器 及 反应器
    void ProfileManReactor()
    {	// 新建 配置文件管理器反应器 对象CProfileManReactor *pProfileReactor = new CProfileManReactor();// acProfileManagerPtr:通过此函数进入CAD配置文件管理器// addReactor:添加反应器来接收 配置文件管理器 通知acProfileManagerPtr()->addReactor(pProfileReactor);/******	 以下为配置文件操作	******/// 获得配置文件在 注册表 中的注册路径 字符串(注意释放)ACHAR *pstrKey;// 参数:返回路径字符串,传入配置文件名(null为第一个)acProfileManagerPtr()->ProfileRegistryKey(pstrKey, NULL);if (pstrKey != NULL){acutPrintf(_T("\n配置文件的注册关键字为: %s"), pstrKey);acutDelString(pstrKey);}// ProfileListNames函数:接收 配置文件名称 字符串列表(查看函数声明,即可知道参数类型)// nProfiles:为函数 返回 配置文件 个数AcApProfileNameArray arrNameList;int nProfiles = acProfileManagerPtr()->ProfileListNames(arrNameList);acutPrintf(_T("\n当前用户配置文件的个数为:%d"), nProfiles);// 遍历列表方法for (int i = 0; i < arrNameList.length(); i++)acutPrintf(_T("\n配置文件名称为: %s"), arrNameList.at(i));// 从已有配置文件拷贝创建新的:新文件名、拷贝源文件名、新文件注释文字acProfileManagerPtr()->ProfileCopy(_T("TestProfile"), _T("<<未命名配置>>"), _T("注释1"));// 恢复默认设置:此名称下的配置文件会被重设为系统默认值acProfileManagerPtr()->ProfileReset(_T("TestProfile"));// 应用为当前配置:配置文件名acProfileManagerPtr()->ProfileSetCurrent(_T("TestProfile"));// 通过acedSetVar修改全局变量(此时修改的是TestProfile配置文件的)struct resbuf rbCursorSize;rbCursorSize.restype = RTSHORT;rbCursorSize.resval.rint = 100;// 修改鼠标十字光标的百分比(可以在CAD命令行输入CURSORSIZE看下效果)acedSetVar(_T("CURSORSIZE"), &rbCursorSize);// 重命名配置文件:新名、原名、新文件注释文字acProfileManagerPtr()->ProfileRename(_T("TestProfile2"), _T("TestProfile"), _T("注释2"));// 导出配置文件(.arg格式):待导出配置文件名、导出文件路径(REGEDIT4 格式)acProfileManagerPtr()->ProfileExport(_T("TestProfile2"), _T("C:/TestProfile2.arg"));/* 导入配置文件(.arg格式):新建配置文件名,导入文件路径(REGEDIT4 格式)、新文件注释文字、是否读入路径信息*/acProfileManagerPtr()->ProfileImport(_T("TestProfile3"),_T("C:/TestProfile2.arg"),_T("复制的配置文件"), Adesk::kTrue);/******	 配置文件操作结束  ******/// 删除反应器acProfileManagerPtr()->removeReactor(pProfileReactor);
    }
    

    注意:除非为非当前正在应用配置, ProfileImport默认覆盖同名配置文件

4.4 效果

  • 图示
    在这里插入图片描述
    在这里插入图片描述

五、上下文反应器

5.1 反应器创建

  • 向导创建
    在这里插入图片描述
    在这里插入图片描述

5.2 类文件修改

  • CInputContextReactor.h
    ...
    class CInputContextReactor : public AcEdInputContextReactor {
    ...
    public:...// 开始静止状态virtual void beginQuiescentState();// 结束静止状态virtual void endQuiescentState();
    } ;
    
  • CInputContextReactor.cpp
    ...	
    // 定义全局变量
    class CInputContextReactor;
    CInputContextReactor *pIRec = NULL; ...
    // 开始静止状态
    void CInputContextReactor::beginQuiescentState() 
    {acutPrintf(_T("\n开始静止状态!"));
    }
    // 结束静止状态
    void CInputContextReactor::endQuiescentState()
    {acutPrintf(_T("\n结束静止状态!"));
    }
    

5.3 注册卸载反应器

  • Commands.h
    #include "stdafx.h"void AddCommands();
    void addReactor();
    void removeReactor();
    
  • Commands.cpp
    #include "stdafx.h"
    #include "Commands.h"
    #include "Editor.h"
    #include "Database.h"
    #include "CInputContextReactor.h"extern CInputContextReactor *pIRec;void AddCommands()
    {	Editor::AddCommand(L"c-addReactor", ACRX_CMD_MODAL, addReactor);Editor::AddCommand(L"c-removeReactor", ACRX_CMD_MODAL, removeReactor);
    }void addReactor()
    {	if (pIRec == NULL){pIRec = new CInputContextReactor();}curDoc()->inputPointManager()->addInputContextReactor(pIRec);acutPrintf(_T("\n上下文反应器已经添加!"));
    }void removeReactor()
    {if (pIRec){curDoc()->inputPointManager()->removeInputContextReactor(pIRec);delete pIRec;pIRec = NULL;}acutPrintf(_T("\n上下文反应器已经删除!"));
    }
    

5.4 效果

  • 图示
    在这里插入图片描述
  • 改写示意(基类AcEdInputContextReactor方法)
    在这里插入图片描述

传送门 返回 列表

http://www.xdnf.cn/news/11476.html

相关文章:

  • JAVA开发环境配置(保姆式教程)
  • 代码的两种命名方法:驼峰命名、匈牙利命名(优缺点)
  • ADB安装及使用详解(非常详细)从零基础入门到精通,看完这一篇就够了_adb是什么
  • 关于qt缺少xcb问题终极解决办法
  • android 使用SQLite数据库详解
  • HIS系统门急诊医保实时结算接口测试
  • 倍投计算机器在线,2021看图开特马50研究计算倍投【欢迎你】
  • css设置滚动条样式
  • 网络管理与维护基本知识
  • android x86怎么样,Android x86 4.4安装体验(转载)
  • nii与nii.gz格式的关系
  • DWZ简介以及使用
  • csdn是什么
  • Android中GridView解析
  • perl下载与安装教程【工具使用】
  • perl 5.10.0安装包下载
  • Spring AOP全面详解(超级详细)
  • 网络负载平衡(NLB)详解!
  • 虚拟机-安装与使用(详细教程)
  • 智能dns调研及bind9搭建
  • FlashFXP 4.0注册码key 及教程
  • MFC内存映射文件
  • 软件工程专业值得考的8个证书
  • 使用C#判断字符串中是否包含中文字符
  • 【目标检测】58、目标检测中的正负样本分配策略总结
  • GaussDB数据类型转换介绍
  • pornstars java,Pornstar - QQ音乐-千万正版音乐海量无损曲库新歌热歌天天畅听的高品质音乐平台!...
  • 分享25个适合上班族的副业路子
  • Round Robin 算法
  • 常用的错误码介绍