|
[code]1. 说明
ObjectARX 中提供了多个提示用户输入的全局函数,包括 acedGetString 、 acedGetPoint 、
acedGetInt 、 acedGetKword 和 acedGetReal 等。这些方法本身的使用很简单,仅在小结部分提
供参考的使用代码,本节所要讨论的主要问题是 acedGetPoint 函数和关键字的结合应用,例
如在 AutoCAD 中执行 PLINE 命令时,能够得到如下的命令提示:
本篇的实例将要模拟 AutoCAD 中动态创建多段线的效果,并且允许用户通过命令行的关键字来改变多段线的某些特性。
2. 思路
(1) 动态创建多段线
动态创建多段线,最基本的要求是用户在图形窗口中按顺序拾取多个顶点,每次拾取一
点都会将其添加到多段线的末尾,最终按下 Enter 键或者 Esc 键完成多段线的创建。
(1)拾取第一点;
(2)拾取第二点,创建多段线;
(3)如果用户没有按下 Enter 键或者 Esc 键,拾取下一点,并将拾取的点添加到多段线的末尾;
(4)如果用户按下 Enter 键或者 Esc 键,退出程序执行,完成多段线的创建,否则反复执行(3)
// 添加创建多段线
//(1)拾取第一点;
//(2)拾取第二点,创建多段线;
//(3)如果用户没有按下 Enter 键或者 Esc 键,拾取下一点,并将拾取的点添加到多段线的末尾;
//(4)如果用户按下 Enter 键或者 Esc 键,退出程序执行,完成多段线的创建,否则反复执行步骤(3)
void CUserInteraction::AddPolyBasic()
{
int index = 2; // 当前输入点的次数
ads_point ptStart; // 起点
if (acedGetPoint(NULL, _T("\n输入第一点:"), ptStart) != RTNORM)
return;
ads_point ptPrevious, ptCurrent; // 前一个参考点,当前拾取的点
acdbPointSet(ptStart, ptPrevious);
AcDbObjectId polyId; // 多段线的ID
while (acedGetPoint(ptPrevious, _T("\n输入下一点:"), ptCurrent) == RTNORM)
{
if (index == 2)
{
// 创建多段线
AcDbPolyline *pPoly = new AcDbPolyline(2);
AcGePoint2d ptGe1, ptGe2; // 两个节点
ptGe1[X] = ptPrevious[X];
ptGe1[Y] = ptPrevious[Y];
ptGe2[X] = ptCurrent[X];
ptGe2[Y] = ptCurrent[Y];
pPoly->addVertexAt(0, ptGe1);
pPoly->addVertexAt(1, ptGe2);
// 添加到模型空间
CCreateEnt m_createEnt;
polyId = m_createEnt.PostToModelSpace(pPoly);
}
else if (index > 2)
{
// 修改多段线,添加最后一个顶点
AcDbPolyline *pPoly;
acdbOpenObject(pPoly, polyId, AcDb::kForWrite);
AcGePoint2d ptGe; // 增加的节点
ptGe[X] = ptCurrent[X];
ptGe[Y] = ptCurrent[Y];
pPoly->addVertexAt(index - 1, ptGe);
pPoly->close();
}
index++;
acdbPointSet(ptCurrent, ptPrevious);
}
}
(2) 在acedGetPoint函数中使用关键字
要在 acedGetPoint 函数中使用关键字,必须在使用 acedGetPoint 函数之前定义关键字,并且使用 acedInitGet 函数来设置关键字,并紧跟这一句调用 acedGetPoint 函数。下面的代码演示了在 acedGetPoint 函数中使用关键字的方法:
要获得 acedGetPoint 函数执行过程中用户输入的关键字,可以通过该函数的返回值来判断用户是否输入了关键字,如果返回值是 RTKWORD 就通过 acedGetInput 函数获得输入关键字的内容。
之所以两个关键字的大写字母不都是第一个,分别为 Keyword1 和 keyWord2 ,是为了让用户可以用不同的大写字母(K 和 W )来代表这两个关键字。
void CUserInteraction::GetPoint()
{
int rc; // 返回值
TCHAR kword[20]; // 关键字
ads_point pt;
acedInitGet(RSG_NONULL, _T("Keyword1 keyWord2"));
rc = acedGetPoint(NULL, _T("输入一个点或[Keyword1/keyWord2]:"), pt);
switch (rc)
{
case RTKWORD: // 输入了关键字
if (acedGetInput(kword) != RTNORM)
return;
if (_tcscmp(kword, _T("Keyword1")) == 0)
acedAlert(_T("选择的关键字是Keyword1!"));
else if (_tcscmp(kword, _T("keyWord2")) == 0)
acedAlert(_T("选择的关键字是keyWord2!"));
break;
case RTNORM:
acutPrintf(_T("输入点的坐标是(%.2f, %.2f, %.2f)"), pt[X], pt[Y], pt[Z]);
} // switch
}
3 步骤
(1)
acedGetString:获取用户输入的字符串
acedGetPoint:获取用户输入的点
acedGetInt:获取用户输入的整型
acedGetKword:获取用户输入的关键字
acedGetReal:获取用户输入的实数
acedGetDist:获取用户输入的距离值
acedGetCorner:获取用户输入的角点
acedGetAngle:获取用户输入的角度
acedGetFileD:打开文件选择对话框获取用户输入的文件名
static void AddPolyDynamic();
static ads_real GetWidth();
static int GetColorIndex();
使用了 acdbPointSet 宏将一个 ads_point 变量的值复制到另一个 ads_point 变量中
#define acdbPointSet(from, to) (*(to)= *(from), (to)[1]=(from)[1], (to)[2]=(from)[2])
void CUserInteraction::AddPolyDynamic()
{
int colorIndex = 0; // 颜色索引值
ads_real width = 0; // 多段线的线宽
int index = 2; // 当前输入点的次数
ads_point ptStart; // 起点
// 提示用户输入起点
if (acedGetPoint(NULL, _T("\n输入第一点: "), ptStart) != RTNORM)
return;
ads_point ptPrevious, ptCurrent; // 前一个参考点,当前拾取的点
acdbPointSet(ptStart, ptPrevious);
AcDbObjectId polyId; // 多段线的ID
// 输入第二点
acedInitGet(NULL, _T("W C O"));
int rc = acedGetPoint(ptPrevious, _T("\n输入下一点 [宽度(W)/颜色(C)]<完成(O)>: "), ptCurrent);
while (rc == RTNORM || rc == RTKWORD)
{
if (rc == RTKWORD) // 如果用户输入了关键字
{
TCHAR kword[20];
if (acedGetInput(kword) != RTNORM)
return;
if (_tcscmp(kword, _T("W")) == 0)
{
width = GetWidth();
}
else if (_tcscmp(kword, _T("C")) == 0)
{
colorIndex = GetColorIndex();
}
else if (_tcscmp(kword, _T("O")) == 0)
{
return;
}
else
{
acutPrintf(_T("\n无效的关键字,重新输入:"));
}
}
else if (rc == RTNORM) // 用户输入了点
{
if (index == 2)
{
// 创建多段线
AcDbPolyline *pPoly = new AcDbPolyline(2);
AcGePoint2d ptGe1, ptGe2; // 两个节点
ptGe1[X] = ptPrevious[X];
ptGe1[Y] = ptPrevious[Y];
ptGe2[X] = ptCurrent[X];
ptGe2[Y] = ptCurrent[Y];
pPoly->addVertexAt(0, ptGe1);
pPoly->addVertexAt(1, ptGe2);
// 修改多段线的颜色和线宽
pPoly->setConstantWidth(width);
pPoly->setColorIndex(colorIndex);
// 添加到模型空间
CCreateEnt m_createEnt;
polyId = m_createEnt.PostToModelSpace(pPoly);
}
else if (index > 2)
{
// 修改多段线,添加最后一个顶点
AcDbPolyline *pPoly;
acdbOpenObject(pPoly, polyId, AcDb::kForWrite);
AcGePoint2d ptGe; // 增加的节点
ptGe[X] = ptCurrent[X];
ptGe[Y] = ptCurrent[Y];
pPoly->addVertexAt(index - 1, ptGe);
// 修改多段线的颜色和线宽
pPoly->setConstantWidth(width);
pPoly->setColorIndex(colorIndex);
pPoly->close();
}
index++;
acdbPointSet(ptCurrent, ptPrevious);
}
// 提示用户输入新的节点
acedInitGet(NULL, _T("W C O"));
rc = acedGetPoint(ptPrevious, _T("\n输入下一点 [宽度(W)/颜色(C)]<完成(O)>:"), ptCurrent);
}
}
ads_real CUserInteraction::GetWidth()
{
ads_real width = 0;
if (acedGetReal(_T("\n输入线宽:"), &width) == RTNORM)
{
return width;
}
else
{
return 0;
}
}
int CUserInteraction::GetColorIndex()
{
int colorIndex = 0;
if (acedGetInt(_T("\n输入颜色索引值(0~256):"), &colorIndex) != RTNORM)
return 0;
// 处理颜色索引值无效的情况
while (colorIndex < 0 || colorIndex > 256)
{
acedPrompt(_T("\n输入了无效的颜色索引."));
if (acedGetInt(_T("\n输入颜色索引值(0~256):"), &colorIndex) != RTNORM)
return 0;
}
return colorIndex;
}
3. 在acrxEntryPoint.cpp中
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyAddPolyDynamic, MyAddPolyDynamic, ACRX_CMD_MODAL, NULL) //用户交互创建多段线
//当前项目中注册命令 AddPolyDynamic
static void MidasMyGroupMyAddPolyDynamic()
{
CUserInteraction::AddPolyDynamic();
}
效果展示
acedGetInt 函数暂停程序执行,等待用户输入一个整数。该函数定义为:
int acedGetInt(const char * prompt, int * result);
prompt 用于指定显示在命令窗口中的字符串,如果不需要使用可以指定 NULL 作为该参数的值。
acedGetReal 函数暂停程序执行,等待用户输入一个实数。
acedGetString 函数暂停程序执行,等待用户输入一个字符串,该函数定义为:
int acedGetString(int cronly, const char * prompt, char * result);
其中,参数 cronly 说明字符串能否包含空格,输入 0 表示不允许字符串中包含空格,
1 表示字符串可以包含空格。
acedGetDist 函数暂停程序执行,等待用户输入直线距离。
acedGetCorner 函数暂停程序执行,等待用户输入图形窗口的矩形框的对角点,一般和 acedGetPoint 函数配合使用。
acedGetAngle 函数暂停程序,等待用户输入一个相对于 ANGBASE 系统变量设置的当前值的角度。
acedInitGet、acedGetKword 和 acedGetInput 配合用于提示用户输入关键字,并根据用户
输入的关键字执行不同的操作。
acedGetFileD 函数使用标准的 AutoCAD 文件对话框提示用户输入一个文件名
// acedGetFileD 函数使用标准的 AutoCAD 文件对话框提示用户输入一个文件名,其定义为:
int acedGetFileD(
const char * title, //title 指定对话框的标题
const char * default, //default 指定默认的文件名称
const char * ext, //ext 指定默认的文件扩展名
int flags, //flags 参数用一个位值控制对话框的样式
struct resbuf * result); //result 参数包含了用户选择的文件名和路径
// 代码演示
void SelectFile()
{
const char* title = "选择图形文件";
const char* path = "C:\\";
struct resbuf *fileName;
fileName = acutNewRb(RTSTR);
if (acedGetFileD(title, path, "dwg;dxf", 0, fileName) == RTNORM)
{
acedAlert(fileName->resval.rstring);
}
acutRelRb(fileName);
}
[/code] |
|