(30)ObjectARX2015 + vs2012用户交互

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); 
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值