天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 59|回复: 0

ObjectARX2015 + vs2012创建和编辑对象时的动态拖动技术

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
[code]1. 说明

        本篇介绍:1. 创建一个圆弧长度的标注,在标注过程中可以选择标注文本的位置;
                          2. 模拟了 MOVE 命令,不过仅能移动文字( AcDbText 类)对象。
2. 思路
        对于 AutoCAD 内建图形对象,要在创建或编辑中实现动态拖动的效果,只能考虑使用
acedGrRead 函数。该函数能够跟踪鼠标的移动:
//创建或编辑中实现动态拖动的效果
int acedGrRead(
    int track,   //track 指定了该函数的控制位
    int * type,  //type 参数返回输入设备及其种类
struct resbuf * result);  //result 参数被设置为从用户获得的参数。


         acedGrRead 函数的使用结构:

//acedGrRead 函数的使用结构:
int track = 1, type; // 控制位和输入设备类型
struct resbuf result; // 保存鼠标拖动时的动态坐标
while (track > 0)
{
    acedGrRead(track, &type, &result); // 追踪光标移动
    ptText[X] = result.resval.rpoint[X]; // 获得用户输入点的位置
    ptText[Y] = result.resval.rpoint[Y];

    // 使用获得的坐标
    {
        ……
    }
    if (type == 3) // 如果用户按下了鼠标左键,跳出循环
    {
        track = 0;
    }
}

        (1) 提示用户选择一个实体使用 acedEntSel 函数,该函数能够获得所选择实体的 ads_name;
        (2) 然后使用 acdbGetObjectId 函数可以将 ads_name 转化为 AcDbObjectId;
        (3) 进而通过 acdbOpenAcDbEntity 函数获得对象的指针,访问其各种特性;
        (4) 获取圆弧的圆心、起点和终点都有直接调用的函数,但是却无法直接获得圆弧的中点;
        (5) AcDbCurve 类的 getDistAtPoint 函数用于获得曲线上某一点到起点的距离
        (6) getPointAtDist 函数用于获得曲线上距离起点一定长度的点
        (7) 因此可以用(5)(6)方法获得圆弧的中点:使用 getDistAtPoint 函数获得圆弧的长度;使用 getPointAtDist 函数根据长度获得圆弧的中点
        (8) 当用户在图形窗口中移动鼠标时,acedGrRead 函数会获得当前光标位置的坐标,使用
acdbOpenAcDbEntity 函数获得指向新创建的标注对象的指针
        (9) 修改标注文本的位置之后,记得关闭该对象。
3. 步骤
(1) 创建一个圆弧长度的标注,在标注过程中可以选择标注文本的位置

添加AddDimensionArc函数

    //添加圆弧尺寸标注
    static void AddDimensionArc();//添加圆弧尺寸标注
//添加圆弧尺寸标注
void CCreateEnt::AddDimensionArc()
{
    // 提示用户选择圆弧
    ads_name en;
    ads_point pt;
    if (acedEntSel(_T("选择所要标注的圆弧:"), en, pt) != RTNORM)
        return;

    // 获得选择对象的指针
    AcDbObjectId arcId;
    Acad::ErrorStatus es = acdbGetObjectId(arcId, en);
    if (es != Acad::eOk)
        return;
    AcDbEntity *pEnt;
    es = acdbOpenAcDbEntity(pEnt, arcId, AcDb::kForRead);

    // 判断选择的对象是否是圆弧
    if (!pEnt->isKindOf(AcDbArc::desc()))
    {
        pEnt->close();
        return;
    }
    AcDbArc *pArc = AcDbArc::cast(pEnt);

    // 获得圆弧的特征点位置
    AcGePoint3d ptCenter, ptStart, ptEnd, ptMiddle;
    ptCenter = pArc->center();
    es = pArc->getStartPoint(ptStart);
    es = pArc->getEndPoint(ptEnd);
    double length;
    es = pArc->getDistAtPoint(ptEnd, length);
    es = pArc->getPointAtDist(length / 2, ptMiddle);
    pEnt->close();

    // 创建三点角度标注
    CString strLength;
    strLength.Format(_T("%.2f"), length);
    AcDbObjectId dimId;
    dimId = CCreateEnt::CreateDim3PtAngular(ptCenter, ptStart, ptEnd, ptMiddle, strLength);

    // 拖动鼠标改变标注文字的位置
    AcGePoint3d ptText;
    int track = 1, type; //track=1
    struct resbuf result; // 保存鼠标拖动时的动态坐标
    while (track > 0)
    {
        acedGrRead(track, &type, &result); // 追踪光标移动
        ptText[X] = result.resval.rpoint[X]; //获得用户输入点的位置
        ptText[Y] = result.resval.rpoint[Y];

        // 设置拖动位置为标注文本的插入点
        acdbOpenAcDbEntity(pEnt, dimId, AcDb::kForWrite);
        if (pEnt->isKindOf(AcDb3PointAngularDimension::desc()))
        {
            AcDb3PointAngularDimension *pDim;
            pDim = AcDb3PointAngularDimension::cast(pEnt);

            if (pDim != NULL)
            {
                pDim->setTextPosition(ptText);
            }
        }
        pEnt->close();

        if (type == 3) // 如果用户按下了鼠标左键,跳出循环
        {
            track = 0;
        }
    }
}

(2) 模拟了 MOVE 命令,不过仅能移动文字(AcDbText 类)对象

添加 MoveText 函数

    //移动文字
    static void MoveText(); //移动文字
//移动文字
void CCreateEnt::MoveText()
{
    ads_name entName;
    ads_point ptPick, ptBase;
    if (acedEntSel(_T("\n选择所要移动的文字:"), entName, ptPick) != RTNORM)
    {
        return;
    }

    AcDbObjectId txtId;
    AcDbText *pText = NULL;
    AcDbEntity *pEnt = NULL;
    Acad::ErrorStatus es = acdbGetObjectId(txtId, entName);
    if (es != Acad::eOk)
    {
        return;
    }

    AcGePoint3d ptInsertOld(0, 0, 0);
    acdbOpenObject(pEnt, txtId, AcDb::kForWrite);
    if (pEnt->isKindOf(AcDbText::desc()))
    {
        pText = AcDbText::cast(pEnt);

        if (pText != NULL)
        {
            ptInsertOld = pText->position();
        }
    }
    pEnt->close();

    if (acedGetPoint(NULL, _T("\n选择基点:"), ptBase) != RTNORM)
    {
        return;
    }
    acedPrompt(_T("\n选择第二点:"));

    AcGePoint3d ptInsertNew(0, 0, 0);
    AcGePoint3d ptPick3d = asPnt3d(ptBase);

    // 鼠标拖动部分
    int track = 1, type; //track=1
    struct resbuf result; // 保存鼠标拖动时的动态坐标
    while (track > 0)
    {
        acedGrRead(track, &type, &result); // 追踪光标移动
        ptInsertNew[X] = result.resval.rpoint[X] - ptPick3d[X] +
            ptInsertOld[X];
        ptInsertNew[Y] = result.resval.rpoint[Y] - ptPick3d[Y] +
            ptInsertOld[Y];

        // 设置拖动位置为直线的终点坐标
        acdbOpenObject(pEnt, txtId, AcDb::kForWrite);
        if (pEnt->isKindOf(AcDbText::desc()))
        {
            pText = AcDbText::cast(pEnt);

            if (pText != NULL)
            {
                pText->setPosition(ptInsertNew);
            }
        }
        pEnt->close();

        if (type == 3) // 如果用户按下了鼠标左键
        {
            track = 0;
        }
    }
}

(3) 在acrxEntryPoint.cpp中

ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyAddDimensionArc, MyAddDimensionArc, ACRX_CMD_MODAL, NULL) //创建对齐标注
    //当前项目中注册一个命令 AddDimensionArc moveText
    static void MidasMyGroupMyAddDimensionArc()
    {
        //添加圆弧标注,并可自定位文字位置
        CCreateEnt::AddDimensionArc();
        //移动文字
        CCreateEnt::MoveText();
    }

原文链接:https://blog.csdn.net/qq_42981953/article/details/121853874[/code]

 

 

 

 

ObjectARX2015 + vs2012创建和编辑对象时的动态拖动技术
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 11:32 , Processed in 0.127083 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表