最近更新于 2024-12-19 08:36
前言
官方文档指定的开发方式是 BASIC,实际用什么语言可以自己选择。最终开发都是连接 PC-DMIS 的 COM 组件 INTEROP.PCDLRN.DLL,选择 Python 开发比较便利(三方库丰富,我也比较熟悉,而且相比于 C/C++ 等需要编译,Python 解释执行,用来写小工具非常适合)。
PC-DMIS 自带的 BASIC 编辑器非常难用,没有现代 IDE 的样子,我感觉甚至不如 Windows 的记事本。如果使用第三方 IDE 软件开发的话,我也不用 BASIC 了,我这里就选择了 Python。官方文档给的 BASIC 大概看一下还是知道在干嘛,毕竟关键字就那些,编程的操作逻辑都差不多,先用 Python 复现官方给的 BASIC 示例代码进行学习,后续查 API 文档就 OK 了。
另外想吐槽一下,PC-DMIS 本身的各种快捷键也独树一帜,只是不得不用,只能适应一下(虽然可以改,但是不用自己电脑的时候还是会不顺手,最好还是适应软件默认的)。如果搞过开发的,基本都熟悉调试运行用F5
(各种 IDE 默认都是这样),但 PC-DMIS 程序运行不是。更扯的是,撤销和反撤销也和 Windows 默认及各种软件不一致。
还有测量程序编辑部分和语言相关,我软件语言选择中文,编程也只能使用中文关键字。这就导致要频繁的中英文切换,经常要看语言状态栏确认当前语言,效率非常低下。既然要把关键字和语言关联,不如内部实现一个“输入法”,像搞中文编程的易语言,比如要输入“如果”,输入拼音首字母 rg 就可以候选出来,而不是要切换输入法再去输入。
这些都是其中一角,能吐槽的有一堆了。各种反直觉的设计,不知道是历史遗留,还是就喜欢标新立异?
PC-DMIS 2019 R2 对象库文档
官方提供的对象层次结构图(PC-DMIS 2019 R2)
连接 PC-DMIS
我这里的开发环境:
- Python 3.13.1
- pywin32 308(Python 模块)
pip install pywin32==308
一个简单的示例代码,获取 PC-DMIS 版本
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application') # 创建 COM 对象实例
print(app.VersionString)
以管理员身份运行终端,再手动执行 Python 命令执行,或者使用 IDE 的话,以管理员身份运行 IDE,再执行代码。总之一定要以管理员身份运行代码,否者代码执行后可能一直阻塞,不会继续往下执行(必须保证和运行 PC-DMIS 的权限一致,PC-DMIS 因为一些操作需要,建议就是以管理员身份运行)。
如果上面代码运行报错,类似
发生异常: com_error
(-2147221005, '无效的类字符串', None, None)
pywintypes.com_error: (-2147221005, '无效的类字符串', None, None)
During handling of the above exception, another exception occurred:
File "I:\work\development\PC-DMIS\test1.py", line 3, in <module>
app = win32.Dispatch('PCDLRN.Application')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pywintypes.com_error: (-2147221005, '无效的类字符串', None, None)
一个可能的问题方向是 PC-DMIS 软件安装的问题,我用的 2019 R2 破解版没问题,但是用的 2023.2 破解版就有问题。试一下打开注册表,按 Ctrl
+F
搜索PCDLRN.Application,正常是可以查到存在这个值,如果查不到这个值,就可能出现上面的错误,说明 INTEROP.PCDLRN.DLL 没有正常注册到系统。
自动请求管理员身份执行方案
参考:https://blog.iyatt.com/?p=18238
如果是把程序添加到 PC-DMIS 的外部命令执行倒没什么问题,由 PC-DMIS 来执行我们自己写的外部程序,权限都是一致的。
如果是作为独立工具直接执行的,PC-DMIS 是管理员身份执行,但是我们写的工具默认没有管理员执行,就会一直阻塞,在不知情的用户看来,就会以为我们的程序有问题。直接在程序上检查是否有管理员权限,没有就自动请求了,也不需要用户来关心要不要管理员身份运行。
使用 COM 组件中的常量
方式一(打包可执行文件建议)
如果需要打包成可执行文件拷贝到别的电脑上执行就建议这种方式,方式二是动态加载,换电脑执行没有找到导出的文件就会报错,需要同样执行这里的操作。
PC-DMIS 的 COM 组件中定义了一些枚举(常量),在开发中经常会用到,直接用枚举的值的话,代码可读性很差,这里就用 pywin32 的模块导出这些常量到文件,再放置到开发目录下。
查看 pywin32 安装路径
pip show pywin32
根据查到的路径拼接上 \win32com\client\makepy.py 就是要用到的模块路径
然后 PC-DMIS 的类型定义文件位于软件安装目录下的 Pcdlrn.tlb 文件中
执行代码导出
python 【makepy.py路径】 -d 【Pcdlrn.tlb文件路径】
可以看到提示 “Generating to C:\Users\pc01\AppData\Local\Temp\gen_py\3.13\10C96EB9-ED97-492D-BC67-700C7F18E394x0x14x2__init__.py”,这就是生成文件的路径,这里就把 10C96EB9-ED97-492D-BC67-700C7F18E394x0x14x2 文件夹复制到项目目录下,改名为 PCDLRN(可以自己取名,导入包的时候名字跟随就行)
后面就可以通过这个模块访问常量
import PCDLRN
from win32com.client import constants as wcc
print('通过 win32com 访问,没有语法提示')
print(wcc.SET_COMMENT)
print(wcc.COMMENT_TYPE)
print(wcc.COMMENT_FIELD)
print('直接访问')
print(PCDLRN.constants.SET_COMMENT)
print(PCDLRN.constants.COMMENT_TYPE)
print(PCDLRN.constants.COMMENT_FIELD)
方式二(代码通用)
方式一导出文件是手动移动到指定目录下使用,这种方式是导出文件后就不移动了,继续用 win32com 的机制,让它去动态加载,好在代码本身通用,坏在打包执行文件移动到没有导出文件的电脑上就找不到文件会报错,需要将导出文件一起复制过去,或者重新执行下面的操作。
# 导出
python [makepy.py路径] -d [tlb文件路径]
# 使用提示
python [makepy.py路径] -i [tlb文件路径]
会给你一段代码实现导入操作
from win32com.client import gencache
gencache.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
下面提供一段示例(后续也使用这种方式,相对较为规范)
import win32com.client.gencache as wcg
from win32com.client import constants as wcc
wcg.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
print(wcc.SET_COMMENT)
print(wcc.COMMENT_TYPE)
print(wcc.COMMENT_FIELD)
官方示例代码 Python 复现
示例 1
官方的示例是在 PC-DMIS 端让用户输入一个数,用一个变量存储这个数,接着执行 BASIC 去修改 PC-DMIS 中的这个变量,在 PC-DMIS 中查看这个结果。
下面是我复现的实现
PC-DMIS
C1 =注释/输入,否,全屏=否,
请输入一个整数
赋值/V1=INT(C1.INPUT)
注释/操作者,否,全屏=否,自动继续=否,
"用户输入值为:" + V1
注释/操作者,否,全屏=否,自动继续=否,
请执行 Python 代码后点确定
注释/操作者,否,全屏=否,自动继续=否,
"Python 修改后值为:" + V1
Python
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram # 获取当前 PC-DMIS 中激活状态的程序引用
v1obj = part.GetVariableValue('V1') # 获取 PC-DMIS 中变量 V1 对象
if v1obj.LongValue: # 如果成功获取 V1 变量
v1obj.LongValue += 1
part.SetVariableValue('V1', v1obj) # 将修改后的对象设置给 PC-DMIS 中的 V1 变量
print(f'自增后值为{v1obj.LongValue},请查看 PC-DMIS 端修改结果')
else:
print('V1 未定义')
运行 PC-DMIS 测量程序,输入一个整数
显示用户输入的值
弹框提醒的时候,去执行 Python 代码
Python 执行结束,显示修改后的值
回到 PC-DMIS 可以看到变量成功被修改
示例 2
用 Python 复现通过代码直接向 PC-DMIS 添加注释命令
Python
import win32com.client.gencache as wcg
from win32com.client import constants as wcc
import win32com.client as wc
wcg.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
noteContent = input('请输入要添加的注释内容:')
cmd = cmds.Add(wcc.SET_COMMENT, True) # 添加命令
cmd.PutText('操作者', wcc.COMMENT_TYPE, 0) # 设置注释类型
cmd.PutText(noteContent, wcc.COMMENT_FIELD, 1) # 添加注释内容
cmd.ReDraw # 刷新
初始命令状态
执行 Python 代码
Python 代码执行后,添加上了注释命令
示例 3(暂停)
这个示例代码使用 BASIC 重新实现了添加注释命令的窗口
下面我使用 Python 复现
读写数据
获取特征
Python
import win32com.client as wc
import win32com.client.gencache as wcg
from win32com.client import constants as wcc
wcg.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
# 遍历当前 PC-DMIS 程序中的命令
for i in range(1, cmds.count):
# 判断当前命令是否为特征
if cmds[i].IsFeature:
# 用于存储特征坐标
x, y, z = 0, 0, 0
# 创建引用变量
xRef = wc.VARIANT(wc.pythoncom.VT_BYREF | wc.pythoncom.VT_R8, x)
yRef = wc.VARIANT(wc.pythoncom.VT_BYREF | wc.pythoncom.VT_R8, y)
zRef = wc.VARIANT(wc.pythoncom.VT_BYREF | wc.pythoncom.VT_R8, z)
print(f"命令 {i:<2} - 特征 {cmds[i]}")
cmds[i].FeatureCommand.GetPoint(wcc.FPOINT_CENTROID, wcc.FDATA_THEO, xRef, yRef, zRef)
print(f'\t理论值 X: {xRef.value}, Y: {yRef.value}, Z: {zRef.value}')
cmds[i].FeatureCommand.GetPoint(wcc.FPOINT_CENTROID, wcc.FDATA_MEAS, xRef, yRef, zRef)
print(f'\t实际值 X: {xRef.value}, Y: {yRef.value}, Z: {zRef.value}')
cmds[i].FeatureCommand.GetPoint(wcc.FPOINT_CENTROID, wcc.FDATA_TARG, xRef, yRef, zRef)
print(f'\t目标值 X: {xRef.value}, Y: {yRef.value}, Z: {zRef.value}')
获取评价尺寸
Python
import win32com.client as wc
import win32com.client.gencache as wcg
from win32com.client import constants as wcc
wcg.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
# 精度
precision = 4
axisLetterWidth = 8
nominalWidth = 8
plusWidth = 8
minusWidth = 8
measuredWidth = 8
deviationWidth = 8
outTolWidth = 8
axisLetterString = '测量类型'
nominalString = '标称值'
plusString = '上偏差'
minusString = '下偏差'
measuredString = '测量值'
deviationString = '偏差值'
outTolString = '超差值'
# 遍历当前 PC-DMIS 程序中的命令
for i in range(1, cmds.count):
cmd = cmds[i]
# 判断当前命令是否为评价尺寸
if cmd.IsDimension:
dim = cmd.DimensionCommand
# 单位
units = cmd.GetFieldValue(wcc.UNIT_TYPE, 0)
# 特征
feat1 = dim.Feat1
feat2 = dim.Feat2
feat3 = dim.Feat3
# 测量类型(D 直径,M 距离)
axisLetter = cmd.DimensionCommand.AxisLetter
# 标称值
nominal = cmd.DimensionCommand.NOMINAL
nominal = round(nominal, precision)
# 上偏差
plus = cmd.DimensionCommand.Plus
plus = round(plus, precision)
if plus > 0:
plus = f'+{plus}'
# 下偏差
minus = cmd.DimensionCommand.Minus
minus = round(minus, precision)
if minus > 0:
minus = f'+{minus}'
# 实际值
measured = cmd.DimensionCommand.Measured
measured = round(measured, precision)
# 偏差值
deviation = cmd.DimensionCommand.Deviation
deviation = round(deviation, precision)
# 超差值
outTol = cmd.DimensionCommand.OutTol
outTol = round(outTol, precision)
if len(cmd.ID) != 0 and cmd.GetFieldValue(wcc.NOMINAL, 0) != False:
print(f'{i} {cmd.ID} {feat1} {feat2} {feat3},单位:{units}')
# 直接读取头部信息
dimHeading = cmd.GetFieldValue(wcc.DIM_HEADING, 0)
print(dimHeading)
print('-' * 100)
if len(axisLetter) != 0:
print(f'\t{axisLetterString:<{axisLetterWidth}}\t{nominalString:<{nominalWidth}}\t{plusString:<{plusWidth}}\t{minusString:<{minusWidth}}\t{measuredString:<{measuredWidth}}\t{deviationString:<{deviationWidth}}\t{outTolString:<{outTolWidth}}')
print(f'\t{axisLetter:<{axisLetterWidth}}\t{nominal:<{nominalWidth}}\t{plus:<{plusWidth}}\t{minus:<{minusWidth}}\t{measured:<{measuredWidth}}\t{deviation:<{deviationWidth}}\t{outTol:<{outTolWidth}}')
print('=' * 100)
获取形位公差
Python
import win32com.client as wc
import win32com.client.gencache as wcg
from win32com.client import constants as wcc
wcg.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
# 特征名对齐长度
featNameLen = 16
# 精度
precision = 4
# 遍历当前 PC-DMIS 程序中的命令
for i in range(0, cmds.count):
cmd = cmds[i]
# 判断当前命令是否为形位公差
if cmd.IsFCFCommand:
# 描述
description = cmd.GetFieldValue(wcc.DESCRIPTION, 0)
# 单位
unit = cmd.GetFieldValue(wcc.UNIT_TYPE, 0)
# 特征尺寸符号
size_symbol = cmd.GetFieldValue(wcc.SIZE_SYMBOL, 0)
if size_symbol == '直径':
size_symbol = 'Ø'
elif size_symbol == '半径':
size_symbol = 'R'
else:
size_symbol = ''
# 特征标称值
nominal = cmd.GetFieldValue(wcc.NOMINAL, 0)
# 特征上公差
fPlusTol = cmd.GetFieldValue(wcc.F_PLUS_TOL, 0)
if (float(fPlusTol) > 0):
fPlusTol = '+' + fPlusTol
# 特征下公差
fMinusTol = cmd.GetFieldValue(wcc.F_MINUS_TOL, 0)
if (float(fMinusTol) > 0):
fMinusTol = '+' + fMinusTol
# 形位公差类型
gdtSymbol = cmd.GetFieldValue(wcc.GDT_SYMBOL, 0)
# 形位公差形状
fcfTolZoneType = cmd.GetFieldValue(wcc.FCF_TOL_ZONE_TYPE, 0)
if fcfTolZoneType == '直径':
fcfTolZoneType = 'Ø'
else:
fcfTolZoneType = ''
# 形位公差
fcfTol = cmd.GetFieldValue(wcc.LINE2_TOL, 0)
# 跳动类型
fcfRunoutType = cmd.GetFieldValue(wcc.FCF_RUNOUT_TYPE, 0)
if not fcfRunoutType:
fcfRunoutType = ''
print(f'{i} 标识:{cmd.ID},单位:{unit},', end='')
if description:
if description == '1':
description = ''
else:
description = description + '×'
print(f'特征尺寸:{description}{size_symbol}{nominal}({fPlusTol}/{fMinusTol}),', end='')
print(f'形位公差:{gdtSymbol}|{fcfTolZoneType}{fcfTol} {fcfRunoutType}')
print('-' * 100)
# 部分形位公差同时评价了多个特征,需要遍历
print('\t特征' + ' ' * (featNameLen - 2) + '\t上公差\t测量值\t偏差值\t超差值' )
for j in range(1, cmd.GetDataTypeCount(wcc.LINE2_MEAS) + 1):
# 特征名称
featName = cmd.GetText(wcc.LINE2_FEATNAME, j)
# 标称值
nominal = cmd.GetFieldValue(wcc.LINE2_NOMINAL, j) # 也可以用 GetText 获取,只是默认会精确小数,得不到完整小数位
nominal = round(nominal, precision)
# 上公差
plusTol = cmd.GetFieldValue(wcc.LINE2_PLUSTOL, j)
# 测量值
meas = cmd.GetFieldValue(wcc.LINE2_MEAS, j)
meas = round(meas, precision)
# 偏差值
dev = cmd.GetFieldValue(wcc.LINE2_DEV, j)
dev = round(dev, precision)
# 超差值
outTol = cmd.GetFieldValue(wcc.LINE2_OUTTOL, j)
outTol = round(outTol, precision)
print(f'\t{featName:<{featNameLen}}\t{plusTol}\t{meas}\t{dev}\t{outTol}')
print('=' * 100)
修改评价尺寸
在上面“获取评价尺寸”的例子中,获取测量值是通过 Commands->Command->DimensionCommand 对象的属性获得的,而在“获取形位公差”的例子中,则是使用 GetFiledValue(也可以用 GetText)获取的。这是在 PC-DMIS 2019 R2 中对评价尺寸进行了封装,而没有对形位公差封装(之前在某处看到说,新版本也对形位公差提供了封装,似乎是 2020 版)。虽然对评价尺寸进行了封装,但可以不使用它,而是像获取形位公差那样直接访问(只是操作更繁琐),同样也可以借助 Commands->Command 下的 PutText 方法进行修改。
下面的例子就不再通过 DimensionCommand 对象的属性读取,而是改为使用 GetFieldValue 获取值,另外使用 PutText 对测量值修改
Python
import win32com.client as wc
import win32com.client.gencache as wcg
from win32com.client import constants as wcc
wcg.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
# 精度
precision = 4
axisLetterWidth = 8
nominalWidth = 8
plusWidth = 8
minusWidth = 8
measuredWidth = 8
deviationWidth = 8
outTolWidth = 8
axisLetterString = '测量类型'
nominalString = '标称值'
plusString = '上偏差'
minusString = '下偏差'
measuredString = '测量值'
deviationString = '偏差值'
outTolString = '超差值'
# 遍历当前 PC-DMIS 程序中的命令
for i in range(1, cmds.count):
cmd = cmds[i]
# 判断当前命令是否为评价尺寸
if cmd.IsDimension:
dim = cmd.DimensionCommand
# 单位
units = cmd.GetFieldValue(wcc.UNIT_TYPE, 0)
# 特征
feat1 = dim.Feat1
feat2 = dim.Feat2
feat3 = dim.Feat3
# 测量类型(D 直径,M 距离)
axisLetter = cmd.GetFieldValue(wcc.AXIS, 0)
if axisLetter != False:
axisLetter = str(axisLetter)
else:
axisLetter = ''
# 标称值
nominal = cmd.GetFieldValue(wcc.NOMINAL, 0)
nominal = float(nominal)
nominal = round(nominal, precision)
# 上偏差
plus = cmd.GetFieldValue(wcc.F_PLUS_TOL, 0)
plus = float(plus)
plus = round(plus, precision)
if plus > 0:
plus = f'+{plus}'
# 下偏差
minus = cmd.GetFieldValue(wcc.F_MINUS_TOL, 0)
minus = float(minus)
minus = round(minus, precision)
if minus > 0:
minus = f'+{minus}'
# 实际值
measured = cmd.GetFieldValue(wcc.DIM_MEASURED, 0)
measured = float(measured)
measured = round(measured, precision)
# 偏差值
deviation = cmd.GetFieldValue(wcc.DIM_DEVIATION, 0)
deviation = float(deviation)
deviation = round(deviation, precision)
# 超差值
outTol = cmd.GetFieldValue(wcc.DIM_OUTTOL, 0)
outTol = float(outTol)
outTol = round(outTol, precision)
if len(cmd.ID) != 0 and cmd.GetFieldValue(wcc.NOMINAL, 0) != False:
print(f'{i} {cmd.ID} {feat1} {feat2} {feat3},单位:{units}')
# 直接读取头部信息
dimHeading = cmd.GetFieldValue(wcc.DIM_HEADING, 0)
print(dimHeading)
print('-' * 100)
if len(axisLetter) != 0:
print(f'\t{axisLetterString:<{axisLetterWidth}}\t{nominalString:<{nominalWidth}}\t{plusString:<{plusWidth}}\t{minusString:<{minusWidth}}\t{measuredString:<{measuredWidth}}\t{deviationString:<{deviationWidth}}\t{outTolString:<{outTolWidth}}')
print(f'\t{axisLetter:<{axisLetterWidth}}\t{nominal:<{nominalWidth}}\t{plus:<{plusWidth}}\t{minus:<{minusWidth}}\t{measured:<{measuredWidth}}\t{deviation:<{deviationWidth}}\t{outTol:<{outTolWidth}}')
print('-' * 100)
# 对所有测量值增加 100
measured += 100
ret = cmd.PutText(measured, wcc.DIM_MEASURED, 0)
if ret:
print(f'修改成功,测量值修改为{measured}')
else:
print('修改失败')
print('=' * 100)
# 刷新报告
part.ReportWindow.RefreshReport
下面的报告是初始状态
执行代码对报告进行修改,所有测量值增加 100
刷新报告
PC-DMIS 的 COM 组件枚举常量使用帮助
PC-DMIS 的对象库文档就是个半截子,像在使用 GetText、GetFieldValue、PutText 的时候需要用到 ENUM_FIELD_TYPES 枚举,如果看文档就是下面的情况,Description 那列都是空着的,这一堆枚举成员只看名字也不一定知道是干啥的。
思路一
可以看到这些枚举成员实际都是映射一个数值的,那么就可以用附带测量数值的测量程序遍历匹配找到需要的枚举成员。
这里还是用上面的 PC-DMIS 测量程序,运行下面的 Python 代码
import win32com.client as wc
import win32com.client.gencache as wcg
from win32com.client import constants as wcc
wcg.EnsureModule('{10C96EB9-ED97-492D-BC67-700C7F18E394}', 0, 14, 2)
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
for i in range(1, cmds.Count):
cmd = cmds[i]
if cmd.DimensionCommand:
dim = cmd.DimensionCommand
id = dim.ID
if len(id) != 0 and cmd.GetFieldValue(wcc.NOMINAL, 0) != False:
print(f'{i} {id}')
下面有打印显示的命令索引就是评价尺寸(要获得形位公差的就判断是不是行为公差对象就行),从中任选一个,这里我就选第 207 个命令,对它进行枚举成员遍历
执行下面 Python 程序
import win32com.client as wc
app = wc.Dispatch('PCDLRN.Application')
part = app.ActivePartProgram
cmds = part.Commands
# 枚举最大遍历数值
enumMaxSize = 2000
# 使用的命令索引
cmdIdx = 207
for i in range(1, enumMaxSize):
val = cmds[cmdIdx].GetFieldValue(i, 0)
if val:
print(f'{i} {val}')
这个时候就对照检测报告看,48.000 这个值是标称值,其对应的枚举值是 166,然后查文档里的表,166 对应的枚举成员是 NOMINAL;
同样道理,报告上这个评价尺寸测量值是 48.017,这里对应的有 3 个枚举值:328、332、336,那么就去查表,这就知道这三个值分别对应DIM_MAX、DIM_MEASURED、DIM_MIN,即测量最大值,测量值(拟合结果),测量最小值。
思路二
PC-DMIS 的报告是使用模板插值的,查看模板就知道特定字段的名称了。
编辑标签模板,比如 Line2.lbl 模板文件
每个字段的名称一目了然
修改形位公差(可能无法实现)
我测试使用 PutText 修改,返回值是 True,但是在执行后再次读取测量值,结果不变,可能这个字段是只读的,无法修改。