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; } }
用户选择一个实体,获取其属性,创建文本标注,当用户在图形窗口中移动鼠标时,修改标注文本的位置
以下代码可以在acedGrRead时响应ESC和回车键
int ret =acedGrRead(1, &type, &result); // 追踪光标移动 if (type == 5) // 如果用户移动了鼠标 { } else if (type == 3) // 如果用户按下了鼠标左键,说明已选定圆的大小 { break; } else { int a = 10; } if(RTCAN == ret || RTNORM==ret)//增加对ESC和回车的响应 { acutPrintf(_T("\n您退出了命令!")); }
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)
//加到选择集 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; }
ObjectARX2015 + vs2012创建和编辑对象时的动态拖动技术
提示:看之前的博客(1)(4)和(12),那里已经分析了创建一个图形对象的基本过程,在之前的基础上本节开始就要将着眼点放在创建实体的参数上。
(1)ObjectARX2015 + vs2012创建直线_qq_42981953的博客-CSDN博客
(4)ObjectARX2015 + vs2012扩展绘制直线的功能为绘制实体_qq_42981953的博客-CSDN博客
(12)ObjectARX2015 + vs2012创建尺寸标注_qq_42981953的博客-CSDN博客
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(); //移动文字
文章评论