objectArx --- ADS篇

一、基本概念

1.1 基本定义

  • ADS:autocad design system 简称,早期CAD面向过程编程系统,现在整合入objectarx中
  • 功能:对CAD全局参数编辑,提供与用户交互函数,头文件:adslib.h、adsdlg.h,默认已加入

1.2 关键类型

  • 类型定义

    类型名特性
    对象id
    AcDbObjectId
    在一个CAD进程中管理多个CAD文件,所有打开的数据库对象在内存中都有唯一的id,每个对象在每次加载后id值都不同,此对象是以下各类型的中介
    实体名
    ads_name
    为ADS存储实体对象的临时变量,关闭文件即丢失,此对象通常用来接收用户选择实体选择集
    句柄
    AcDbHandle
    数据库文件dwg真实标记实体的数据类型,每次打开文件,同一实体,句柄不变
  • 转换关系
    在这里插入图片描述

二、数据类型

2.1 ads数据类型

  • 包含:浮点型、整型、字符串、点、实体名
  • 代码
    // 整形
    int num = 5;
    // 打印写法:跟C语言printf一样
    acutPrintf(_T("%d\n"), num);
    
    // 浮点型:typedef double   ads_real;
    ads_real r1=3.14;
    acutPrintf(_T("%0.3f\n"), r1);
    
    // 字符串型:以下二者可相互转换
    ACHAR * str = _T("兼容性最好\n");
    CString cstr = _T("此类为mfc项目默认字符串,函数更友好\n");
    acutPrintf(str);
    acutPrintf(cstr);
    
    // 点:typedef ads_real ads_point[3];
    ads_point pt1, pt2;
    // 三个坐标不可留空
    pt1[X] = pt1[Y] = pt1[Z] = 1.0;
    // 点覆盖式赋值:用pt1赋值pt2
    ads_point_set(pt1, pt2);
    acutPrintf(_T("%0.3f\n"),pt2[X]);
    
    // 实体名(由鼠标选择赋值),通常由其获得对象id
    // typedef int64_t ads_name[2];
    ads_name en, en1;
    // 将en0深拷贝给en1
    ads_name_set(en0, en1);
    

2.2 类型转换

2.2.1 浮点数 与 字符串

  • 代码示例
    ads_real rel = 1.23456789;
    ACHAR str[12];
    // 浮点数转字符串:浮点数、转换模式、小数位数、待接收字符串
    // 转换正常ret为RTNORM,否则见第3.1节
    int ret = acdbRToS(rel, 1, 3, str);
    acutPrintf(str);
    
    // 字符串转浮点数:字符串、转换模式、浮点数(注意取地址符)
    ACHAR str_a[12]= _T("9.87654");
    // ret用于存储结果类型码(本篇3.1) 判断是否正常转换:RTNORM为正常
    // 转换正常ret为RTNORM,否则见第3.1节
    ret = acdbDisToF(str_a,1,&rel);
    acutPrintf(_T("\n%f"),rel);
    

    转换模式:

    • 1科学记数法:结果为1.235E+00
    • 2十进制:结果为1.235
    • 3工程、4建筑:略
    • 5分数:结果为1 1/4

2.2.2 角值 转换

  • 弧度 转 字符串(由控制符 控制 转换格式)
    // 函数acdbAngToS参数:弧度值、控制符、精度、字符串指针
    // 转换正常ret为RTNORM,否则见第3.1节
    
    ACHAR str[12];
    // 0弧度转角度
    int ret = acdbAngToS(MathUtil::PI() / 4, 0, 4, str);
    // 返回:45.0000,0都省略了
    acutPrintf(_T("\n%s"),str);
    
    // 1弧度转角度
    ret = acdbAngToS(MathUtil::PI()/4, 1, 4, str);
    // 返回:45d0'0"
    acutPrintf(_T("\n%s"), str);
    
    // 2弧度转工程
    ret =acdbAngToS(MathUtil::PI() / 4, 2, 4, str);
    // 返回:50g
    acutPrintf(_T("\n%s"), str);
    
    // 3弧度(ads_real)转弧度(字符串)(带r标识)
    ret =acdbAngToS(MathUtil::PI() / 4, 3, 4, str);
    // 返回:0.7854r
    acutPrintf(_T("\n%s"), str);
    
  • 角 转 浮点数
    // 函数acdbAngToF参数:字符串(弧度/角度值)、控制符、浮点数
    // 转换正常ret为RTNORM,否则见第3.1节
    
    ads_real rel;
    // 0:百分角度 转弧度
    int ret = acdbAngToF(_T("45"), 0, &rel);
    acutPrintf(_T("\n%.4f"),rel);
    
    // 1:度分秒角度 转弧度
    ret = acdbAngToF(_T("45d0'0\""), 1, &rel);
    acutPrintf(_T("\n%.4f"), rel);
    
    // 2:工程 转弧度
    ret = acdbAngToF(_T("50g"), 2, &rel);
    acutPrintf(_T("\n%.4f"), rel);
    
    // 3:弧度(带r标识) 转弧度(不含r标识)
    ret = acdbAngToF(_T("0.7854r"), 3, &rel);
    acutPrintf(_T("\n%.4f"), rel);
    

    关系:acdbAngTo与acdbAngToS为互补函数

2.2 结果缓冲区

  • 功能:CAD中数据种类多样,需要有一个进行数据临时交换与存储的媒介

2.2.1 定义

  • 源文件声明
    // 结果缓冲区节点为结构体
    struct resbuf {            
    		// 用于构造单链表,未设置则为NULL                                  
            struct resbuf *rbnext; 
            // 用于定义ads_u_val 的类型
            short restype;
            // 联合体:用于存储具体值
            union ads_u_val resval;
    };
    
    // 联合体ads_u_val的定义
    union ads_u_val {
    	// 浮点型:常用
        ads_real rreal;
        // 点:常用
        ads_real rpoint[3];
        // 短整型:常用
        short rint;
        // 字符串:常用
        ACHAR *rstring;
    	// 剩下不常用略,可以转到结果缓冲区查看
    }; 
    

2.2.2 结果类型码

  • 类型码列表
    #define RTNONE    5000 /* 无结果 */
    #define RTREAL    5001 /* 浮点型 */
    #define RTPOINT   5002 /* 2D点 */
    #define RTSHORT   5003 /* 短整型 */
    #define RTANG     5004 /* 角度 */
    #define RTSTR     5005 /* 字符串 */
    #define RTENAME   5006 /* 实体名 */
    #define RTPICKS   5007 /* 选择集 */
    #define RTORINT   5008 /* 方向*/
    #define RT3DPOINT 5009 /* 3D点 */
    #define RTLONG    5010 /* 长整型 */
    #define RTVOID    5014 /* 空白符号 */
    #define RTLB      5016 /* 列表开始 */
    #define RTLE      5017 /* 列表结束 */
    #define RTDOTE    5018 /* 点对 */
    #define RTNIL     5019 /* 零*/
    #define RTDXF0    5020 /* DXF码,仅供ads_buildlist使用 */
    #define RTRESBUF  5023 /* 结果缓冲区 */
    

    用于指定结果缓冲区节点的值类型

  • 组码:特殊的类型码,≤1071的类型码有特殊含义,传送门

2.2.3 简单使用

  • 结果缓冲区链表
    void  test()
    {	// 自制结果缓冲区的迭代器,提取链表每个节点
    	resbuf* rb_iter;
    	resbuf* cmdlist;
    	ads_point pt1 = { 1,1,1 };
    	int num = 3;
    	// 函数:构建结果缓冲区链表
    	cmdlist = acutBuildList(RTSTR,	_T("test"), 
    							RTPOINT,pt1, 
    							RTSHORT,num, 
    							RTNONE);
    	// 拷贝 链表 首节点 的 指针 给 迭代器
    	rb_iter = cmdlist;
    	// rb_iter的指针不为空
    	while (rb_iter != NULL)
    	{
    		acutPrintf(_T("结果类型码:%d\n"), rb_iter->restype);
    		switch (rb_iter->restype)
    		{
    		case RTSTR:
    			acutPrintf(_T("值为:%s\n"), rb_iter->resval.rstring);
    			break;
    		case RTPOINT:
    			acutPrintf(_T("值为:%f\n"), rb_iter->resval.rpoint[X]);
    			break;
    		case RTSHORT:
    			acutPrintf(_T("值为:%d\n"), rb_iter->resval.rint);
    			break;
    		}
    		rb_iter = rb_iter->rbnext;
    	}
    	acutPrintf(_T("执行完毕\n"));
    	// 手动释放结果缓冲区
    	acutRelRb(rb_iter);
    	acutRelRb(cmdlist);
    }
    
  • 效果
    在这里插入图片描述

2.2.4 链表命令

  • 函数用法
    // 必须包含头文件
    #include "acedCmdNF.h"
    
    // 模拟人工输入命令:隐式构建结果缓冲区链表
    acedCommandS(RTSTR, _T("circle"), 
    			 RTSTR, _T("0,0"), 
    			 RTSTR, _T("300"), 
    			 RTNONE);
    

三、用户交互

3.1 函数返回码

  • 功能:用于标识函数执行情况
  • 常用返回码列表(重要)
    #define RTNORM    5100 /* 正常 */
    
    #define RTERROR          (-5001) // 其他错误
    #define RTCAN            (-5002) // 用户按Ctl-C或ECS
    #define RTREJ            (-5003) // AutoCAD拒绝的请求--无效
    #define RTFAIL           (-5004) // 连接失败 -- Lisp脚本可能崩溃了
    #define RTKWORD          (-5005) // 来自 getxxx() 的关键字
    #define RTINPUTTRUNCATED (-5008) // 输入不完全适合缓冲区
    

3.2 常用

  • 弹出警告框:acedAlert(_T("弹出警告框"));
    在这里插入图片描述
  • 命令行打印:acutPrintf(_T("跟C语言printf函数一样\n"));
  • 捕捉离光标最近的中点、端点、中心点(最好关掉对象捕捉)
    acedOsnap(pt, _T("midp,endp,center"), pt1);,pt是传入的点,pt1是返回的点
  • 遍历全图实体(包括隐藏实体)
    ads_name en0, en1;
    
    // 遍历全图:首参数为null,则获取第一个元素的ads_name
    if (acdbEntNext(NULL, en0) != RTNORM)
    	return;
    // acdbEntNext遍历链表,以首参数为参照,获取第二个参数ads_name
    do
    {	// 从ads_name获取对象id
    	AcDbObjectId id;
    	acdbGetObjectId(id, en0);
    	// ld 长整型
    	acutPrintf(_T("\n对象id为:%ld"), id);
    	// acedUsrBrk()用于判断用户是否按下esc键
    	if (acedUsrBrk())
    		return;
    	// 将en0深拷贝给en1
    	ads_name_set(en0, en1);
    // en1变为参考点,en0值被覆盖,从而获取下一个链表节点的ads_name
    } while (acdbEntNext(en1, en0) == RTNORM);
    

3.3 acedGetXXX函数

3.3.1 常规

  • 获取整型:acedGetInt

    // 获取整型:提示字符串、变量地址(看函数头文件)
    int num;
    if (acedGetInt(_T("\n请输入整数:"), &num) == RTNORM)
    	acutPrintf(_T("\n整数为:%d"),num);
    
  • 获取浮点数:acedGetReal

    // 获取浮点数:提示字符串、变量地址
    ads_real num_real;
    if (acedGetReal(_T("\n请输入浮点数:"), &num_real) == RTNORM)
    	acutPrintf(_T("\n浮点数为:%0.3f"), num_real);
    
  • 获取字符串:acedGetString

    // 获得字符串:是否允许空格(1允许)、提示字符串、字符串指针、字符串变量长度(包括结尾\0)
    // 如果超出长度ret返回RTINPUTTRUNCATED,超出的字符串丢弃,正常返回RTNORM
    ACHAR str[6];
    int ret = acedGetString(0, _T("\n请输入字符串:"), str, 6);
    if ( ret == RTNORM)
    	acutPrintf(_T("\n字符串为:%s"), str);
    else
    {
    	acutPrintf(_T("\n结果返回码为:%d"), ret);
    }
    
    // 字符串正则匹配函数:待校验字符串指针、匹配规则
    if (acutWcMatch(str, _T("ro*b"))==RTNORM) {
    	acedAlert(_T("此字符串匹配了定义的正则表达式"));
    }
    
  • 获取点坐标:acedGetPoint

    // 获取点坐标:是否允许空格(1允许)、提示字符串、点变量
    ads_point pt;
    if (acedGetPoint(0, _T("\n请选取点:"), pt) == RTNORM)
     	acutPrintf(_T("\n点为:%f,%f"), pt[X],pt[Y]);
     	
    // 极坐标法获得点坐标:基点ads_point、弧度ads_real,极半径ads_real,返回点ads_point
    acutPolar(pt,ang, 100.0, pt3);
    
  • 获取夹角弧度:acedGetAngle

    // 获取与三点钟方向夹角弧度:基准点(若为NULL则在屏幕上点)、提示字符串、接收弧度值
    ads_point pt_ang = { 0,0,0 };
    ads_real ang;
    if (acedGetAngle(pt_ang, _T("\n请角度点:"), &ang) == RTNORM)
    	acutPrintf(_T("\n角弧度为:%f"), ang);
    	
    // 方法2:直接计算pt与pt1线段与x轴正向夹角弧度
    ads_real ang = acutAngle(pt, pt1);
    

    在这里插入图片描述

    方框内角度:非弧度,会跟着十字光标动态变化

  • 获取两点间距离:acedGetDist

    // 返回屏幕上两点间距离:基准点(若为NULL则在屏幕上点)、提示字符串,
    ads_real distance;
    if (acedGetDist(NULL, _T("\n请选择点:"), &distance) == RTNORM)
    	acutPrintf(_T("\n距离为:%f"), distance);
    

3.3.2 acedInitGet

  • 功能一:循环检测用户非法输入

  • 关键字代码:

    // 过滤用户非法输入,输入符合要求才能通过,可esc退出
    acedInitGet(RSG_NONEG + RSG_NOZERO + RSG_NONULL, NULL);
    int num;
    if (acedGetInt(_T("\n请输入整数:"), &num) == RTNORM)
    	acutPrintf(_T("\n整数为:%d"),num);
    

    控制位开关:

    • 非负:RSG_NONEG ,非零 RSG_NOZERO,非空RSG_NONULL
    • 开启橡皮筋或虚矩形追踪RSG_DASH
    • 去掉Z坐标:RSG_2D,仅用于acedGetDist
      特点:仅对紧跟着的那个acedGetXXX函数起效

    在这里插入图片描述


  • 功能二:关键字选项控制

    // 禁止输入空,并明确关键字为以下四个(空格分隔)
    acedInitGet(RSG_NONULL, _T("1 2 3 4"));
    ACHAR kw[5];
    // 这是控制关键字显示:见下面效果图
    acedGetKword(_T("\n选择一个关键字[ONE(1)/TWO(2)/THREE(3)]:"), kw);
    switch (tc)
    {
    case RTCAN:
    	acutPrintf(_T("\n你取消了输入"));
    	break;
    case RTNORM:
    	if (_tcscmp(kw, _T("1")) == 0)
    	{	// 可以通过关键字跳转其他程序处理后续
    		acutPrintf(_T("\n你选择了1"));
    		break;
    	}
    	else if (_tcscmp(kw, _T("2")) == 0)
    	{
    		acutPrintf(_T("\n你选择了2"));
    		break;
    	}
    	else if (_tcscmp(kw, _T("3")) == 0)
    	{
    		acutPrintf(_T("\n你选择了3"));
    		break;
    	}
    default:
    	break;
    }
    acutPrintf(_T("\n程序结束"));
    
  • 效果
    在这里插入图片描述

3.3.3 选择实体

  • 功能:获取实体ads_name和选择点
  • 代码示例
    // 获取与三点钟方向夹角弧度:基准点(若为NULL则在屏幕上点)、提示字符串、接收弧度值
    ads_point pt;
    ads_name en;
    if (acedEntSel(NULL, en, pt) == RTNORM)
    	acutPrintf(_T("点选处为:%f,%f"), pt[X], pt[Y]);
    
  • 常用函数
    ads_name en1, en2;
    ads_point pt1, pt2;
    
    acedEntSel(NULL, en1, pt1);
    acedEntSel(NULL, en2, pt2);
    
    // 判断ads_name是否相等
    if (acdbNameEqual(en1, en2))
    	acutPrintf(_T("\n选择了同一个实体"));
    else
    	acutPrintf(_T("\n选择了两个实体"));
    	
    // 清空ads_name值
    acdbNameClear(en2);
    // 判断ads_name是否为空,为空则为true
    if (acdbNameNil(en2))
    	acutPrintf(_T("\n清除成功"));
    	
    // 用en2给en1赋值
    acdbNameSet(en1,en2);
    if (acdbNameEqual(en1, en2))
    	acutPrintf(_T("\n赋值成功"));
    
  • 效果
    在这里插入图片描述

3.4 选择集

  • 定义:实体的有名集合
  • 特性:
    • 非互斥性:一个实体可以包含在不同选择集中
    • 唯一性:多次选择一个实体,选择集中只包含一次
    • 易用性:可空,可手动框选添加实体进选择集

3.4.1 常用函数

  • 代码示例
    // 图上框选创建选择集
    ads_name  en1, en2, ss1;
    acedSSGet(NULL, NULL, NULL, NULL, ss1);
    
    // 获得选择集长度
    int len;
    acedSSLength(ss1, &len);
    acutPrintf(_T("\n初始选择集实体个数为%d"), len);
    
    // 获取 选择集 首元素 的ads_name赋值en:一般用在for循环里
    acedSSName(ss1,0,en1);
    // 判断实体是否在选择集里
    if(acedSSMemb(en1, ss1))
    	acutPrintf(_T("\n实体在选择集中"));
    
    // 获取实体en2
    acedEntSel(NULL, en2, NULL);
    // 将实体添加进现有选择集:第2、3参数均为选择集
    acedSSAdd(en2,ss1,ss1);
    acedSSLength(ss1, &len);
    acutPrintf(_T("\n新增后选择集实体个数为%d"), len);
    
    // 从选择集中删除实体,实体还在图中
    acedSSDel(en1, ss1);
    acedSSLength(ss1, &len);
    acutPrintf(_T("\n删除后选择集实体个数为%d"), len);
    
    // 释放选择集:选择集数量有上限,及时释放
    acedSSFree(ss1);
    acutPrintf(_T("\n程序结束"));
    
  • 效果
    在这里插入图片描述

3.4.2 acedSSGet函数详解

  • 常用
    写法注释
    acedSSGet(_T("A"), NULL, NULL, NULL, ss1);选择全部实体
    acedSSGet(_T("W"), pt1, pt2, NULL, ss1);矩形框选window:包住的、跟边线重合的实体
    acedSSGet(_T("C"), pt1, pt2, NULL, ss1);矩形叉选crossing:包住的、跟边线重合、相交的实体
  • 围区点列表
    点列表框选:acedSSGet(_T("WP"), pointlist, NULL, NULL, ss1);
    点列表叉选:acedSSGet(_T("CP"), pointlist, NULL, NULL, ss1);
    
    // 图上框选创建选择集
    ads_name  ss1;
    ads_point pt1 = { 0,0,0 }, 
    		  pt2 = { 100,100,0 }, 
    		  pt3 = { 100,0,0 }, 
    		  pt4 = { 0,100,0 };
    // 点列表构建
    resbuf * pointlist;
    pointlist = acutBuildList(RT3DPOINT, pt1, 
    						  RT3DPOINT, pt3, 
    						  RT3DPOINT, pt2, 
    						  RT3DPOINT, pt4, 
    						  RTNONE);	// 必须有这个,否则cad崩溃
    // CP可以换成WP或F(栏选:仅选择跟边线交叉的实体),
    // 点列首尾自动闭合,P为Polygon
    acedSSGet(_T("CP"), pointlist, NULL, NULL, ss1);
    // 显示选择集内实体个数
    int len;
    acedSSLength(ss1, &len);
    acutPrintf(_T("\n选择集内实体个数为%d"), len);
    // 释放选择集、释放结果缓冲区
    acedSSFree(ss1);
    acutRelRb(pointlist);
    acutPrintf(_T("程序结束"));
    
  • 过滤选择集
    • 常规过滤
      ads_name  ss1;
      resbuf * filter;
      // 构建筛选器:RTDXF0为实体类型组码、8为图层组码、结尾要有RTNONE
      filter = acutBuildList(RTDXF0, _T("CIRCLE"), 8, _T("0"), RTNONE);
      // X 开启筛选器,filter为筛选器缓冲区指针
      acedSSGet(_T("X"), NULL, NULL, filter, ss1);
      // 打印选择集内实体数
      int len;
      acedSSLength(ss1, &len);
      acutPrintf(_T("\n选择集内实体个数为%d"), len);
      
      acedSSFree(ss1);
      acutRelRb(filter);
      acutPrintf(_T("程序结束"));
      
    • 关系过滤 filter写法
      // -4:条件运算符,40:圆半径组码(必须是100.0有小数)
      filter = acutBuildList(RTDXF0, _T("CIRCLE"), 
      				       -4,     _T(">="), 
      					   40,     100.0, 
      					   RTNONE);
      
    • 条件过滤 filter写法
      // 为了好读,加了缩进:选取所有0层上的直线和所有半径为100的圆
      filter = acutBuildList(
      	// or内为或关系:内部有一个就选择
      	-4, _T("<OR"),
      		// and内为与关系,一个整体
      		-4, _T("<AND"), 
      			RTDXF0, _T("LINE"), 8, _T("0"), 
      		-4, _T("AND>"),
      		// and内为与关系,一个整体
      		-4, _T("<AND"), 
      			RTDXF0, _T("CIRCLE"), 40, 100.0, 
      		-4, _T("AND>"),
      
      	-4, _T("OR>"),
      
      	RTNONE);
      

四、系统变量

  • 浮点型

    // 对结果缓冲区 浮点型 操作
    resbuf rb, rb1;
    // 获取系统变量:圆角半径
    acedGetVar(_T("FILLETRAD"), &rb);
    acutPrintf(_T("系统变量值为:%.3f"), rb.resval.rreal);
    
    // 给自定义结果缓冲区变量赋值,rb1.next默认为null
    rb1.restype = RTREAL;
    rb1.resval.rreal = 1.0;
    
    // 提取并操作系统变量值
    if (rb.resval.rreal < 1.0)
    	// 设置系统变量值:传入自定义结果缓冲区变量
    	if (acedSetVar(_T("FILLETRAD"), &rb1) != RTNORM)
    		return;
    
  • 整型

    // 对结果缓冲区 整型 操作
    resbuf rb2, rb3;
    acedGetVar(_T("CMDECHO"), &rb2);
    acutPrintf(_T("\n当前的CMECHO变量的值为%d."), rb2.resval.rint);
    // 给自定义结果缓冲区变量赋值,rb1.next默认为null
    rb3.restype = RTSHORT;
    rb3.resval.rint = 0;
    if (acedSetVar(_T("CMDECHO"), &rb3) == RTNORM)
    {
    	acutPrintf(_T("\n系统变量值CMDECHO,已修改,现在的值为%d"), rb3.resval.rint);
    }
    else
    	acutPrintf(_T("\n设置系统变量值失败!"));
    
  • 字符串型

    // 对结果缓冲区 字符串 操作
    resbuf rb4, rb5;
    // 获取系统变量:字体样式
    acedGetVar(_T("TEXTSTYLE"), &rb4);
    if (rb4.resval.rstring != NULL)
    {	// 打印当前字体样式、随后释放结果缓冲区
    	acutPrintf(_T("\n当前的文字样式是%s"), rb4.resval.rstring);
    	acdbFree(rb4.resval.rstring);
    	// 自定义结果缓冲区rb5,类型
    	rb5.restype = RTSTR;
    	// C语言的分配内存空间,判断分配成功
    	// 指针自身 = (指针类型*)malloc(sizeof(指针类型)*数据数量)
    	// mallo函数返回的实际是一个无类型指针,必须在其前面加上指针类型强制转换才可以使用
    	if ((rb5.resval.rstring = (ACHAR *)malloc(20)) != NULL)
    	{	// 给结果缓冲区赋值
    		_tcscpy(rb5.resval.rstring, _T("STANDARD"));
    		// 用自定义的设置结果缓冲区
    		acedSetVar(_T("TEXTSTYLE"), &rb5);
    		acutPrintf(_T("\n新修改的文字样式是:%s"), rb5.resval.rstring);
    		acdbFree(rb5.resval.rstring);
    	}
    	else
    		acedAlert(_T("内存不足!"));
    }
    
  • 点坐标

    // 对结果缓冲区点 坐标 操作
    resbuf rb6, rb7;
    ads_real lx, ly;
    // 获取系统变量:当前图形最大点、最小点
    acedGetVar(_T("EXTMAX"), &rb6);
    acedGetVar(_T("EXTMIN"), &rb7);
    // 结果缓冲区点提取
    lx = rb6.resval.rpoint[X] - rb7.resval.rpoint[X];
    ly = rb6.resval.rpoint[Y] - rb7.resval.rpoint[Y];
    acutPrintf(_T("\n当前图形的水平长度和垂直长度分别为<%.3f , %.3f>"), lx, ly); 
    
  • 总体效果
    在这里插入图片描述

传送门 返回 列表

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值