一,
(1)使用的ObjectARX向导创建新工程用户交互
(2)编译,如果出现以下错误:
错误C2338:/ RTCc拒绝符合代码,因此C ++标准库不支持它。删除此编译器选项,或定义_ALLOW_RTCc_IN_STL以确认您已收到此警告。
解决方法:
(3)新建一个常见的过滤器:右键 – “添加筛选器
(4)在普通文件夹中新建相互作用文件夹
(5)在交互文件夹中新建一个CGetInputUtil,用于获取用户的输入
(6)此时,将的.cpp文件拖入到筛选器中即可
打开项目的文件夹,发现头文件和源文件都在同一层级上,所以拖入到筛选器文件夹中不影响它的层级关系,筛选器文件夹只是给开发者起到一种分类作用
(7)在其中新建一个成员函数GetPointReturnCode,指定基点的情况下提示用户拾取一个点,代码实现:
int CGetInputUtil::GetPointReturnCode(const AcGePoint3d &basePoint, const TCHAR* prompt, AcGePoint3d &point)
{
//将基点转换为UCS坐标
AcGePoint3d ucsBasePoint = CConvertUtil::WcsToUcsPoint(basePoint);
int nReturn = acedGetPoint(asDblArray(ucsBasePoint), prompt, asDblArray(point));
if (nReturn == RTNORM)
{
//acedGetPoint得到UCS坐标,转换为WCS
point = CConvertUtil::UcsToWcsPoint(point);
}
return nReturn;
}
(8)其中的CConvertUtil类:
在CConvertUtil类中添加成员函数:AcGePoint3d WcsToUcsPoint(const AcGePoint3d&point); 实现代码:
AcGePoint3d CConvertUtil::WcsToUcsPoint( const AcGePoint3d &point )
{
// 转换成世界坐标
AcGePoint3d pt;
struct resbuf rbFrom, rbTo;
rbFrom.restype = RTSHORT;
rbFrom.resval.rint = 0; // from WCS
rbTo.restype = RTSHORT;
rbTo.resval.rint = 1; // to UCS
acedTrans(asDblArray(point), &rbFrom, &rbTo, Adesk::kFalse, asDblArray(pt));
return pt;
}
注意,是静态静成员函数:
static AcGePoint3d WcsToUcsPoint(const AcGePoint3d &point);
(9)在GetInputUtil.cpp中添加头文件
#include "ConvertUtil.h"
(10)在CConvertUtil类中添加静态成员函数UcsToWcsPoint(const AcGePoint3d&point)
UcsToWcsPoint函数声明:
static AcGePoint3d UcsToWcsPoint(const AcGePoint3d &point);
UcsToWcsPoint函数实现:
AcGePoint3d CConvertUtil::UcsToWcsPoint(const AcGePoint3d &point)
{
// 转换成世界坐标
AcGePoint3d pt;
struct resbuf rbFrom, rbTo;
rbFrom.restype = RTSHORT;
rbFrom.resval.rint = 1; // from UCS
rbTo.restype = RTSHORT;
rbTo.resval.rint = 0; // to WCS
acedTrans(asDblArray(point), &rbFrom, &rbTo, Adesk::kFalse, asDblArray(pt));
return pt;
}
(11)关于acedGetPoint函数:用于获取用户输入的一个点。
int acedGetPoint(
const ads_point pt,
const ACHAR * prompt,
ads_point result
);
二,在CGetInputUtil类中新建一个函数用GetPoint,返回值为布尔
(1)用GetPoint函数声明
static bool GetPoint(const AcGePoint3d &basePoint,
const TCHAR* prompt, AcGePoint3d &point);
(2)用GetPoint函数实现
bool CGetInputUtil::GetPoint(const AcGePoint3d &basePoint,
const TCHAR* prompt, AcGePoint3d &point)
{
return (GetPointReturnCode(basePoint, prompt, point) == RTNORM);
}
三,在CGetInputUtil类中添加一个函数GetPointReturnCode,在不提供基点的情况下提示用户拾取一个点:
(1)实现的代码:
int CGetInputUtil::GetPointReturnCode(const TCHAR* prompt, AcGePoint3d &point)
{
int nReturn = acedGetPoint(NULL, prompt, asDblArray(point));
if (nReturn == RTNORM)
{
point = CConvertUtil::UcsToWcsPoint(point);
}
return nReturn;
}
(2)asDblArray函数:
这个内联函数返回VEC作为两个双精度的数组。
四,添加一个简化返回值的封装函数用GetPoint
实现代码:
bool CGetInputUtil::GetPoint(const TCHAR* prompt, AcGePoint3d &point)
{
return (GetPointReturnCode(prompt, point) == RTNORM);
}
五,新建一个命令AddPolyBasic
(1)实现代码
static void AAAMyGroupAddPolyBasic() {
// Put your command code here
int index = 2; //当前输入点的次数
AcGePoint3d ptStart;
if (!CGetInputUtil::GetPoint(TEXT("\\n输入第一点:"), ptStart))
{
return;
}
AcGePoint3d ptPrevious, ptCurrent;//前一个参考点,当前拾取点
ptPrevious = ptStart;
AcDbObjectId polyId; //多段线ID
while (CGetInputUtil::GetPoint(ptPrevious, TEXT("\\n输入下一点:"), ptCurrent))
{
if (index == 2) //输入了第二个点,将多段线添加到模型空间
{
polyId = CPolylineUtil::Add(CConvertUtil::ToPoint2d(ptPrevious), CConvertUtil::ToPoint2d(ptCurrent));
}
else if (index > 2) //输入了更多的顶点,就向多段线添加一个顶点
{
AcDbPolyline *pPoly = NULL;
if (acdbOpenObject(pPolyId, AcDb::kForWrite) == Acad::eOk)
{
pPoly->addVertexAt(index - 1, CConvertUtil::ToPoint2d(ptCurrent));
pPoly->close();
}
}
ptPrevious = ptCurrent;
index++;
}
}
(2)添加一个类CPolylineUtil,
(3)添加2个成员函数
函数声明:
// 创建优化多段线
static AcDbObjectId Add(const AcGePoint2dArray &points, double width = 0);
static AcDbObjectId Add(const AcGePoint2d &ptStart, const AcGePoint2d &ptEnd,
double width = 0);
函数实现:
AcDbObjectId CPolylineUtil::Add(const AcGePoint2dArray &points, double width)
{
int numVertices = points.length();
AcDbPolyline *pPoly = new AcDbPolyline(numVertices);
for (int i = 0; i < numVertices; i++)
{
pPoly->addVertexAt(i, points.at(i), 0, width, width);
}
AcDbObjectId polyId;
polyId = CDwgDatabaseUtil::PostToModelSpace(pPoly);
return polyId;
}
AcDbObjectId CPolylineUtil::Add(const AcGePoint2d &ptStart, const AcGePoint2d &ptEnd, double width)
{
AcGePoint2dArray points;
points.append(ptStart);
points.append(ptEnd);
return Add(points, width);
}
(4)创建类CDwgDatabaseUtil,添加成员函数PostToModelSpace
实现代码:
static void AAAMyGroupAddPolyBasic() {
// Put your command code here
int index = 2; //当前输入点的次数
AcGePoint3d ptStart;
if (!CGetInputUtil::GetPoint(TEXT("\\n输入第一点:"), ptStart))
{
return;
}
AcGePoint3d ptPrevious, ptCurrent;//前一个参考点,当前拾取点
ptPrevious = ptStart;
AcDbObjectId polyId; //多段线ID
while (CGetInputUtil::GetPoint(ptPrevious, TEXT("\\n输入下一点:"), ptCurrent))
{
if (index == 2) //输入了第二个点,将多段线添加到模型空间
{
polyId = CPolylineUtil::Add(CConvertUtil::ToPoint2d(ptPrevious), CConvertUtil::ToPoint2d(ptCurrent));
}
else if (index > 2) //输入了更多的顶点,就向多段线添加一个顶点
{
AcDbPolyline *pPoly = NULL;
if (acdbOpenObject(pPoly,polyId, AcDb::kForWrite) == Acad::eOk)
{
pPoly->addVertexAt(index - 1, CConvertUtil::ToPoint2d(ptCurrent));
pPoly->close();
}
}
ptPrevious = ptCurrent;
index++;
}
}
(5)在PolylineUtil.cpp中添加头文件
#include "DwgDatabaseUtil.h"
(6)在类CConvertUtil中添加成员函数ToPoint2d
AcGePoint2d CConvertUtil::ToPoint2d( const AcGePoint3d &point3d )
{
return AcGePoint2d(point3d.x, point3d.y);
}
需要注意的是,我们整个项目中所添加的函数都是静态成员函数,在函数声明中添加静态
(7)在acrxEntryPoint.cpp中添加头文件
#include "GetInputUtil.h"
#include "PolylineUtil.h"
#include "ConvertUtil.h"
(8)此时不妨加载程序,在AutoCAD的中输入命令AddPolyBasic
可以正确运行,并绘制多段线。
六、注册新命令GetPointKeyword,用于实现在acedGetPoint函数中使用关键字的基本方法
(1)实现代码:
static void AAAMyGroupGetPointKeyword() {
// Put your command code here
int rc; //返回值
TCHAR kword[20]; //关键字
AcGePoint3d pt;
acedInitGet(RSG_NONULL, TEXT("K W"));
rc = CGetInputUtil::GetPointReturnCode(TEXT("\\n输入一个点或[keyword1/keyword2]:"), pt);
switch (rc)
{
case RTKWORD://输入了关键字
if (acedGetInput(kword) != RTNORM)
{
return;
}
if (_tcscmp(kword, TEXT("K")) == 0)
{
acutPrintf(TEXT("\\n选择的关键字是keyword1"));
}
else if (_tcscmp(kword, TEXT("W")) == 0)
{
acutPrintf(TEXT("\\n选择的关键字是keyWord2!"));
}
break;
case RTNORM:
acutPrintf(TEXT("\\n输入点的坐标是(%.2f,%.2f,%.2f)"),
pt.x, pt.y, pt.z);
break;
default:
break;
}
}
(2)acedInitGet(RSG_NONULL, TEXT("K W"))函数:
初始化下一个对用户输入函数的调用所使用的选项,如acedGetXxx()、acedDragGen()、acedEntSel()、acedNEntSelP()或acedNEntSel()。
参数RSG_NONULL:控制位,支持或禁用某些输入值和输入样式。RSG_NONULL表示不允许空输入
参数TEXT("K W"):用户输入函数接受的可选的关键字列表;
(3)_tcscmp(kword, TEXT("K")):
如果两个字符串是相同的则返回零。
七、在acrxEntryPoint.cpp文件的static void AAAMyGroupAddPolyBasic()命令函数前面创建一个函数GetWidth,
用于获取用户输入的线宽。(若你的编译器为VC6,则是在UserInteractionCommands.app文件中添加)
实现代码:
static ads_real GetWidth()
{
ads_real width = 0;
if (acedGetReal(TEXT("\\n输入线宽:"), &width) == RTNORM)
{
return width;
}
else
{
return 0;
}
}
八、GetWidth函数后面添加一个函数GetColorIndex,用于提示输入颜色索引值。注意添加static。
static int GetColorIndex()
{
int colorIndex = 0;
if (acedGetInt(TEXT("\\n输入颜色索引值(0~256):"), &colorIndex) != RTNORM)
{
return 0;
}
//处理颜色索引值无效的情况
while (colorIndex < 0 || colorIndex > 256)
{
acedPrompt(TEXT("\\n输入了无效的颜色索引值."));
if (acedGetInt(TEXT("\\n输入颜色索引值(0-256):"), &colorIndex) != RTNORM)
{
return 0;
}
}
return colorIndex;
}
九、注册一个新命令AddPoly,提示用户输入多段线的节点、线宽和颜色,完成多段线的创建。
实现代码为:
static void AAAMyGroupAddPoly() {
// Put your command code here
int colorIndex = 0; //颜色索引值
ads_real width = 0; //多段线的线宽
int index = 2; //当前输入点的次数
//提示用户输入起点
AcGePoint3d ptStart; //起点
if (!CGetInputUtil::GetPoint(TEXT("\\n输入第一点:"), ptStart))
{
return;
}
AcGePoint3d ptPrevious, ptCurrent;//前一个参考点,当前拾取点
ptPrevious = ptStart;
AcDbObjectId polyId;//多段线的Id
//输入第二点
acedInitGet(NULL, TEXT("W C O"));
int rc = CGetInputUtil::GetPointReturnCode(ptPrevious,
TEXT("\\n输入下一点[宽度(W)/颜色(C)]<完成(O)>:"), ptCurrent);
while (rc == RTNORM || rc == RTKWORD)
{
if (rc == RTKWORD) //如果用户输入了关键字
{
TCHAR kword[20];
if (acedGetInput(kword) != RTNORM)
return;
if (_tcscmp(kword, TEXT("W")) == 0)
{
width = GetWidth();
}
else if (_tcscmp(kword, TEXT("C")) == 0)
{
colorIndex = GetColorIndex();
}
else if (_tcscmp(kword, TEXT("O")) == 0)
{
return;
}
else
{
acutPrintf(TEXT("\\n无效的关键字."));
}
}
else if (rc == RTNORM)//用户输入了点
{
if (index == 2)
{
//创建多段线
polyId = CPolylineUtil::Add(CConvertUtil::ToPoint2d(ptPrevious), CConvertUtil::ToPoint2d(ptCurrent));
AcDbPolyline *pPoly = NULL;
if(acdbOpenObject(pPoly,polyId,AcDb::kForWrite) == Acad::eOk)
{
//修改多段线的颜色和线宽
pPoly->setConstantWidth(width);
pPoly->setColorIndex(colorIndex);
pPoly->close();
}
}
else if (index > 2)
{
//修改多段线,添加最后一个顶点
AcDbPolyline *pPoly = NULL;
if (acdbOpenObject(pPoly, polyId, AcDb::kForWrite) == Acad::eOk)
{
pPoly->addVertexAt(index - 1, CConvertUtil::ToPoint2d(ptCurrent));
//修改多段线的颜色和线宽
pPoly->setConstantWidth(width);
pPoly->setColorIndex(colorIndex);
pPoly->close();
}
}
ptPrevious = ptCurrent;
index++;
}
//提示用户输入新的节点
acedInitGet(NULL, TEXT("W C O"));
rc = CGetInputUtil::GetPointReturnCode(ptPrevious, TEXT("\\n输入下一点[宽度(W)/颜色(C)]<完成(O)>"), ptCurrent);
}
}
十、效果:
输入命令addpoly:
注意:宽度的关键字W 和 颜色关键字C 需要区分大小写
十一、项目UserIntereaction 的完整代码分享(开发环境:ObjectARX2018 + AutoCAD2018)
链接:https://pan.baidu.com/s/1qvbeEDP0-eMQb7vf4TncKQ 密码:osg6
参考资料:
《AutoCAD ObjectARX(VC)开发基础与实例教程》
暂无评论内容