ObjectARX_acedGrRead/acedDragGen动态拖动

本文介绍了ObjectARX中acedGrRead和acedDragGen函数的使用方法,用于实现动态拖动效果。acedGrRead通过监听用户鼠标移动来获取坐标,用于更新对象位置。acedDragGen结合选择集、回调函数,允许用户选择实体并实时调整其属性,如文本标注的位置。示例代码展示了如何根据用户操作改变文本标注的坐标。
摘要由CSDN通过智能技术生成

转自:https://my.oschina.net/u/2930533/blog/1593775

acedGrRead函数的定义形式为:  

int acedGrRead(int track,int * type,struct resbuf * result);

第一个参数:track:控制位;第二个参数:type:返回输入设备及其种类;第三个参数:result:从用户获得

返回拖动的坐标:track为Bit 0(1):当用户移动鼠标或其它顶点设备时, type 设置为 5,result 设置为(X,Y)坐标。

返回所有的关键值:track为Bit 1(2) :包括函数和光标的所有代码。

控制光标的显示:Bit 2(4) :type为0,显示一般的十字丝;type为1,不显示光标或十字丝;type为2,显示选择实体的小方框。

不显示错误:Bit 3 (8) :当用户按下 Ctrl+C 快捷键的时候,控制台暂停消息。

具体用法如例:

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

用户选择一个实体,获取其属性,创建文本标注,当用户在图形窗口中移动鼠标时,修改标注文本的位置

void ZffCHAP2AddDimension()
{
    // 提示用户选择圆弧
    ads_name en;
    ads_point pt;
    if (acedEntSel("选择所要标注的圆弧:", en, pt) != RTNORM)
      return;

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

    AcDbEntity *pEnt = NULL;
    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 = 0.0;
    es = pArc->getDistAtPoint(ptEnd, length);//获得曲线上某一点到起点的距离
    es = pArc->getPointAtDist(length / 2, ptMiddle);//距离起点一定长度的点
    pEnt->close();

    // 创建三点角度标注
    CString strLength;
    strLength.Format("%.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 = NULl;
            pDim = AcDb3PointAngularDimension::cast(pEnt);
            if (pDim != NULL)
            {
                pDim->setTextPosition(ptText);
            }
        }
        pEnt->close();
        if (type == 3)  // 如果用户按下了鼠标左键
        {
            track = 0;
        }
    } 
}

根据用户的选择移动文字

void ZffCHAP2MoveText()
{
    ads_name entName;
    ads_point ptPick, ptBase;
    if (acedEntSel("\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, "\n选择基点:", ptBase) != RTNORM)
        return;

    acedPrompt("\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;
        }
    } 
}

 acedDragGen函数的定义形式为:

int acedDragGen (const ads_name selectName, const ACHAR *pmt, int cursor, int (*scnf) (ads_point pt, ads_matrix mt), ads_point point)

第一个参数:selectName:选择集名称;第二个参数:pmt:命令行提示语句;第三个参数:cursor:0;第四个参数:int (*scnf) (ads_point pt, ads_matrix mt):回调函数;第五个参数:point:当前鼠标位置的点

具体用法如例:

    //加到选择集
    ads_name selectName,singleName;
	bool bIsFirst = true;
	for (int i = 0;i < arrAllEntId.length(); ++i)
	{
		acdbGetAdsName(singleName, arrAllEntId[i] );

		if( bIsFirst )
		{
			acedSSAdd( singleName, NULL, selectName );
			bIsFirst = false;
		}
		else
			acedSSAdd( singleName, selectName, selectName );

		acedSSFree( singleName );
	}    

	// 用户拖动确定位置
	ads_point point;
	while(1)
	{
		int rc = acedDragGen(selectName,_T("\n左键确定位置:"),0,JigCallBack,point);
		if (rc != RTNORM)
		{
			acedSSFree(selectName);
			acutPrintf(_T("\n插入已取消!\n"));
			return FALSE;
		}

		AcGeMatrix3d matrix;
		AcGePoint3d ptBase(point[X], point[Y], point[Z]);//基点
		matrix(2,3) = 0; // Z方向不动
		AcDbObjectIdArray arrNEntId;
		CDrawEntityBlock mQkqly(NULL,ptBase);
		HHVerify(mQkqly.LockDoc());
		mQkqly.CopyEntitys(arrAllEntId, matrix, arrNEntId);//从原点拷贝一份到点击点

		//打成块		
		AcDbObjectId blockId;
		mQkqly.GetBlockRefrenceId(blockId);
		mQkqly.UnLockDoc();
		if (blockId.isNull() || !blockId.isValid())
			return FALSE;
	}
	acedSSFree(selectName);

回调函数:

__declspec(dllexport) int JigCallBack(ads_point pt,ads_matrix matrix)
{
	// 确定最终位置
	AcGeVector3d vector(pt[X]-origin[X],pt[Y]-origin[Y],0); // z方向不动
	AcGeMatrix3d mat = mat.setToTranslation(vector);

	for(int i = 0; i < 4; i++)
	{
		for(int j = 0; j < 4; j++) 
		{
			matrix[i][j] = mat(i,j); 
		} 
	}

	return RTNORM;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值