本文主要是介绍ObjectARX如何监控实体双击事件(利用钩子函数或者反应器),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 1 实现方法1——钩子函数
- 1.1 钩子函数的作用
- 1.2 利用钩子函数监控双击事件
- 2 实现方法2——反应器
- 2.1 反应器的作用
- 2.2 利用编辑器反应器监控双击事件
在ObjectARX开发中,常常要监控鼠标的双击事件,比如,往一个实体中写了扩展数据,然后你希望用户双击这个实体的时候进行特殊处理。怎么办呢?
ObjectARX至少提供了两种方法:钩子函数和反应器。
1 实现方法1——钩子函数
1.1 钩子函数的作用
在ObjectARX中,可以在CAD的窗口消息循环中注册一个钩子函数。注册钩子函数的函数原型为:
BOOL acedRegisterFilterWinMsg( const AcedFilterWinMsgFn pfn);
其中,AcedFilterWinMsgFn 的类型为:
BOOL (* AcedFilterWinMsgFn)(MSG*);
acedRegisterFilterWinMsg中形参pfn指向的函数就是钩子函数,它可以更改传递进入的消息值。如果pfn返回FALSE,这个消息将继续传递给其他钩子函数和AutoCAD(假设其他钩子函数没有终止该消息的处理);如果返回TRUE,则消息不再传递。
在CAD的窗口消息循环中,所有窗口消息都会进入到钩子函数,你可以在钩子函数中对特定消息进行处理。
1.2 利用钩子函数监控双击事件
在加载arx时会调用OnLoadApp,在卸载时会调用OnUnloadApp。因此,我们可以在OnLoadApp注册钩子函数,在OnUnloadApp删掉注册的钩子函数,注册与反注册的代码如下:
void OnLoadApp()
{//..........省略//注册一个钩子函数//If the function returns TRUE, the message will not be passed to other hook functions or AutoCAD. The message is terminated. acedRegisterFilterWinMsg(FilterEntDBClick);
}void OnUnloadApp()
{//..........省略//remove the hook function.acedRemoveFilterWinMsg(FilterEntDBClick);
}
上述钩子函数具体实现为
bool FilterEntDBClick(MSG *pMsg)
{if (pMsg->message == WM_LBUTTONDBLCLK){ads_name ss;if (RTNORM != acedSSGet(_T("I"), NULL, NULL, NULL, ss))return false;ads_name ent;int32_t lLen;acedSSLength(ss, &lLen);acedSSName(ss, lLen-1, ent);acedSSFree(ss);AcDbObjectId idObj;if (Acad::eOk == acdbGetObjectId(idObj, ent)){AcDbEntity* pEnt = NULL;if (Acad::eOk == acdbOpenObject(pEnt, idObj)){CString sDxfName = pEnt->isA()->dxfName();acutPrintf(_T("\n\t当前双击实体的dxf名称:%s"), sDxfName);CString sClassName = pEnt->isA()->name();acutPrintf(_T("\n\t当前双击实体的类名称:%s"), sClassName);pEnt->close();}}}//消息继续传递return false;
}
当双击某个实体的时候,这个钩子函数会获取实体的对象类型、类名称等信息。关于这个函数还有几点说明:
1.对象的图元类型、类名称信息存在在AcRxClass类对象中,通过IsA()方法,获取对象的AcRxClass类对象。然后进一步获取对象类型、类名称等信息。
2.双击某个对象的时候,可能出现一种情况,就是已经选择了多个对象;所以,在钩子函数中,我们应当获取当前选择集的最后一个对象,这才是双击的对象,这是通过acedSSName方法来完成的。
最后效果如下:
2 实现方法2——反应器
2.1 反应器的作用
反应器实际上就是给ObjectARX提供了捕获AutoCAD特定事件的接口,例如,通过文档反应器捕获到创建新文档、打开图形文档、关闭图形文档的事件,通过数据库反应器捕获到添加新实体、修改实体、删除实体的事件,就可以针对这些事件做一些特定的处理。
AutoCAD提供了多种类型的反应器,供ObjectARX处理特定的事件,包括:
1. 编辑器反应器:AcEditorReactor
2. 文档反应器:AcApDocManagerReactor
3. 数据库反应器:AcDbDatabaseReactor
4. 对象反应器:AcDbObject
每个反应器的用法都有差异,监控实体双击事件,我们需要使用编辑器反应器。
2.2 利用编辑器反应器监控双击事件
以下反应器实例监控对象的双击事件,并且当对象是组中成员的时候,在命令行输出组的名称。
从AcEditorReactor派生出一个新类CDBClickReactor,头文件为:
#pragma onceclass CDBClickReactor : public AcEditorReactor
{
public:CDBClickReactor() {};~CDBClickReactor() {};virtual void beginDoubleClick(const AcGePoint3d& clickPoint);
};
该类的实现为:
#include "stdafx.h"
#include "CDBClickReactor.h"
#include <dbgroup.h>void CDBClickReactor::beginDoubleClick(const AcGePoint3d& clickPoint)
{//获取预选择集ads_name ss;if (RTNORM != acedSSGet(_T("I"), NULL, NULL, NULL, ss))return;ads_name ent;acedSSName(ss, 0, ent);acedSSFree(ss);AcDbObjectId objId;acdbGetObjectId(objId, ent);AcDbEntity* pEnt = NULL;if (Acad::eOk == acdbOpenObject(pEnt, objId)){const AcDbVoidPtrArray *pReactors;void *pSomething;AcDbObjectReactor *pObjReactor;AcDbObjectId persObjId;AcDbGroup *pGroup;pReactors = pEnt->reactors();if (pReactors != NULL && pReactors->length() > 0) {for (int i = 0; i < pReactors->length(); i++) {pSomething = pReactors->at(i);// Is it a persistent reactor?if (acdbIsPersistentReactor(pSomething)) {persObjId = acdbPersistentReactorObjectId(pSomething);// 如果是组,就打开,输出组名称if ((Acad::eOk == acdbOpenObject(pGroup, persObjId, AcDb::kForRead))){acutPrintf(_T("\n\t当前组的名称为:%s\n"), pGroup->name());pGroup->close();break;}}}}}
}
关于类的实现,着重说明以下几点:
1.用户双击对象以后,会进入到CDBClickReactor::beginDoubleClick,我们为了演示方便,针对用户双击组对象的情况,做了特殊处理,输出组的名称;其他情况没有特殊处理。
2.用户双击组时,实际上双击的是组中的某个成员实体,但是这个实体添加了一个永久反应器,这个永久反应器关联的对象才是组对象。上述例程用到的acdbPersistentReactorObjectId,返回的就是永久反应器关联的实体ID。
除了上述实现文件以外,需要声明全局变量
CDBClickReactor* g_ReactorDBClick = NULL;
在加载arx时,往CAD编辑器加载这个反应器
void OnLoadApp()
{//.........省略g_ReactorDBClick = new CDBClickReactor();acedEditor->addReactor(g_ReactorDBClick);
}
在卸载arx时,需要删掉这个反应器
void OnUnloadApp()
{//.........省略acedEditor->removeReactor(g_ReactorDBClick);delete g_ReactorDBClick;
}
实现效果如下:
以上,就是利用编辑器反应器监控对象双击的简单示例。
这篇关于ObjectARX如何监控实体双击事件(利用钩子函数或者反应器)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!