1 说明
- AutoCAD中有一个非常实用的功能,当光标移动到一个实体上时,它会显示一个动态的信息空间,光标离开这个实体,信息控件就会隐藏起来。这种显示方式非常便于用户获取图形中不容易得到的实体信息,如下图所示。
- 本文使用两个简单的例子来说明实现这个功能的方法,在这两个例子中将分别使用AcEdInputPointFilter和AcEdInputPointMonitor反应器来重载AutoCAD鼠标点处实体的提示信息。
- 环境配置:
AutoCAD2016 64位;
Vs2012;
ObjectARX2015 SDK。
2 思路
在ObjectARX中,这个效果是通过点输入处理机制来实现的,有以下两种实现方式。
2.1 使用AcEdInputPointFilter实现
使用AcEdInputPointFilter完成这个功能需要的基本流程包括:
- 创建一个从AcEdInputPointFilter类继承的子类,重写processInputPoint函数;
- 需要启动实体信息动态提示时,为当前文档添加输入点过滤器,处理的对象就是从AcEdInputPointFilter类继承的子类;
- 需要关闭实体动态提示时,为当前的文档删除输入点过滤器。
2.1.1 创建工程
在VS2012中创建一个名为FilterTest的工程,并添加一个名为CPointFilterSample的类。
2.1.2 改写CPointFilterSample类
将CPointFilterSample类改写为一个从AcEdInputPointFilter类继承的子类,并添加和重写成员函数。
头文件CPointFilterSample.h的内容为:
#pragma once
class CPointFilterSample : public AcEdInputPointFilter
{
public:
virtual Acad::ErrorStatus processInputPoint(
bool& changedPoint,
AcGePoint3d& newPoint,
bool& displayOsnapGlyph,
bool& changedTooltipStr,
ACHAR*& newTooltipString,
bool& retry,
AcGiViewportDraw* drawContext,
AcApDocument* document,
bool pointComputed,
int history,
const AcGePoint3d& lastPoint,
const AcGePoint3d& rawPoint,
const AcGePoint3d& grippedPoint,
const AcGePoint3d& cartesianSnappedPoint,
const AcGePoint3d& osnappedPoint,
AcDb::OsnapMask osnapMask,
const AcArray<AcDbCustomOsnapMode*>& customOsnapModes,
AcDb::OsnapMask osnapOverrides,
const AcArray<AcDbCustomOsnapMode*>& customOsnapOverrides,
const AcArray<AcDbObjectId>& pickedEntities,
const AcArray< AcDbObjectIdArray, AcArrayObjectCopyReallocator< AcDbObjectIdArray > >& nestedPickedEntities,
const AcArray<Adesk::GsMarker>& gsSelectionMark,
const AcArray<AcDbObjectId>& keyPointEntities,
const AcArray< AcDbObjectIdArray, AcArrayObjectCopyReallocator< AcDbObjectIdArray > >& nestedKeyPointEntities,
const AcArray<Adesk::GsMarker>& keyPointGsSelectionMark,
const AcArray<AcGeCurve3d*>& alignmentPaths,
const AcGePoint3d& computedPoint,
const ACHAR* tooltipString
);
public:
// 弧度转角度
static double RadianToAngle(double radian);
// 获得PI的值
static double PI();
};
源文件CPointFilterSample.cpp的内容为:
#include "stdafx.h"
#include "PointFilterSample.h"
Acad::ErrorStatus CPointFilterSample::processInputPoint(
bool& changedPoint,
AcGePoint3d& newPoint,
bool& displayOsnapGlyph,
bool& changedTooltipStr,
ACHAR*& newTooltipString,
bool& retry,
AcGiViewportDraw* drawContext,
AcApDocument* document,
bool pointComputed,
int history,
const AcGePoint3d& lastPoint,
const AcGePoint3d& rawPoint,
const AcGePoint3d& grippedPoint,
const AcGePoint3d& cartesianSnappedPoint,
const AcGePoint3d& osnappedPoint,
AcDb::OsnapMask osnapMask,
const AcArray<AcDbCustomOsnapMode*>& customOsnapModes,
AcDb::OsnapMask osnapOverrides,
const AcArray<AcDbCustomOsnapMode*>& customOsnapOverrides,
const AcArray<AcDbObjectId>& pickedEntities,
const AcArray< AcDbObjectIdArray, AcArrayObjectCopyReallocator< AcDbObjectIdArray > >& nestedPickedEntities,
const AcArray<Adesk::GsMarker>& gsSelectionMark,
const AcArray<AcDbObjectId>& keyPointEntities,
const AcArray< AcDbObjectIdArray, AcArrayObjectCopyReallocator< AcDbObjectIdArray > >& nestedKeyPointEntities,
const AcArray<Adesk::GsMarker>& keyPointGsSelectionMark,
const AcArray<AcGeCurve3d*>& alignmentPaths,
const AcGePoint3d& computedPoint,
const ACHAR* tooltipString
)
{
// 一定要注意检查缓冲区的大小,避免越界导致的Acad直接跳出
TCHAR mtooltipStr[1024], tempStr[1024];
mtooltipStr[0] = '\0';
Acad::ErrorStatus es;
AcDbEntity* pEnt;
AcDbObjectId highlightId = AcDbObjectId::kNull;
if (pointComputed)
{
// 分析光标所覆盖的实体
if (pickedEntities.length() > 0)
{
for (int i = 0; i < pickedEntities.length(); ++i)
{
// 避免显示更多的实体(根据需要确定是否需要)
if (i > 0)
{
break;
}
if (Acad::eOk != (acdbOpenAcDbEntity(pEnt, pickedEntities[i], AcDb::kForRead)))
{
continue;
}
if (pEnt->isKindOf(AcDbLine::desc()))
{
// 实体类型信息
if (_tcslen(mtooltipStr) > 0)
{
_tcscpy(mtooltipStr, TEXT("直线:"));
}
else
{
_tcscpy(mtooltipStr, TEXT("\n直线:"));
}
// 实体详细信息
AcDbLine* pLine = AcDbLine::cast(pEnt);
double length = pLine->startPoint().distanceTo(pLine->endPoint());
AcGeVector3d vec = pLine->endPoint