在工程图中插入二维码可以方便机器扫描读取,易于将图纸与MES、ERP等系统结合。添加二维码一般可以考虑以下方式:
在工程图中插入图片等OLE内容。可以在Creo中导入外部程序生成的诸如jpg、png等图片格式的二维码文件。经测试,插入OLE内容暂时不仅未提供Toolkit接口,并且录制宏发现插入图片的操作也无法通过宏的方式实现,所以该方法只能由设计人员手动添加,无法进行二次开发。 
在工程图中插入dxf。可以在Creo中导入外部程序生成的dxf格式的二维码文件。经测试,导入的dxf文件会转换为草绘对象,而且Toolkit提供了Pro2dImportAppend函数用于导入dxf文件,所以该方法不仅可以手动操作,也适合于二次开发。但该方法导入dxf后添加了一系列草绘图元,当需要修改时难以确定那些草绘时导入的dxf文件转换得到导致难以对二维码相关的草绘删除修改,故该方法仅适用于一次性导入二维码的操作。 
生成包含二维码信息的符号。可以在绘图中添加一个符号,在符号中绘制对应的二维码图案,之后插入该符号。该方法手工操作较复杂,主要需要手动绘制对应的二维码符号,但易于插入修改及替换,而Toolkit也提供了绘制符号的方式。 
 
本文主要采用第三种方法在绘图中添加二维码。
1.添加二维码的基本流程 如上分析,通过添加符号的方式为工程图添加二维码主要包含以下几个步骤:
遍历工程图所有符号实例,删除之前添加的二维码符号实例; 
遍历工程图所有符号定义,删除之前添加的二维码符号定义; 
对输入进行转码,生成二维码信息; 
创建新的符号定义,根据二维码信息对该符号定义进行修改,生成包含二维码信息的符号定义; 
根据实际,生成符号定义的实例并将其摆放到正确的位置。 
 
2. 遍历并删除符号定义 Toolkit提供了ProDrawingDtlsymdefsCollect函数收集绘图所包含的所有符号对象定义。获取所有符号定义后对即可其遍历,使用ProDtlsymdefdataNameGet函数获取符号的名称,通过名称进行比对,如果名称与我们定义的二维码符号名称一致则调用ProDtlsymdefDelete删除符号定义。遍历并删除符号定义示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 CString DtlsymdefName (ProDtlsymdef *p_sym_def)   {  ProDtlsymdefdata data;   ProError status;   ProName name;   if  (p_sym_def == NULL  || p_sym_def->type != PRO_SYMBOL_DEFINITION)     return  "" ;   status = ProDtlsymdefDataGet (p_sym_def, &data);   status = ProDtlsymdefdataNameGet (data, name);   return  CString (name); } void  DeletePreQrCodeDef ()  {  ProError status;   ProDrawing drawing;   ProDtlsymdef *p_symdefs;   int  size;   CString SymName;   if  (CurrentMdlType () != PRO_DRAWING)     return ;   status = ProMdlCurrentGet ((ProMdl *)&drawing);   status = ProDrawingDtlsymdefsCollect (drawing, &p_symdefs);   status = ProArraySizeGet ((ProArray)p_symdefs, &size);   for  (int  i = 0 ; i < size; i++)   {     if  (DtlsymdefName (&p_symdefs[i]) == QRCODESYMNAME)     {       status = ProDtlsymdefDelete (&p_symdefs[i]);     }   }   status = ProArrayFree ((ProArray *)&p_symdefs); } 
 
经测试,如果直接删除符号定义,则符号定义生成的对象实例也同时一并删除,故无需进行删除符号实例的操作。
3.字符串转二维码[1]  生成QRCODE的数据我们直接使用了Github.com上MFCQRcode项目提供的LibQRCode库 。使用该库只需添加LibQRCode.lib以及对应头文件qrencode.h的引用,为常规的库文件引用操作,在此不在赘述。根据工程介绍,生成二维码并访问其信息的示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 if  (pQRC = QRcode_encodeString (message, 0 , QR_ECLEVEL_L, QR_MODE_8, 1 ))   {     pSourceData = pQRC->data;     unWidth = pQRC->width;     for  (y = 0 ; y < unWidth; y++)     {       for  (x = 0 ; x < unWidth; x++)       {         if  (*pSourceData & 1 )         {                    }         pSourceData++;       }     }     QRcode_free (pQRC);   } 
 
4.创建二维码符号定义 4.1 创建符号定义 创建一个新的符号定义可以用ProDtlsymdefdataAlloc、ProDtlsymdefCreate等实现,使用ProDtlsymdefdataAttachAdd等函数可以设置其插入方式为自由摆放,ProDtlsymdefdataPathSet设置其名称等。操作相对简单,直接给出创建符号定义对应的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 void  QRcodeSymdefCreate (ProDrawing drawing, CString name, CString message, ProVector position)  {  ProError status;   ProDtlsyminstdata sdata;   ProDtlattach attach;   ProDtlsyminst syminst;   status = ProDtlsymdefdataAlloc (drawing, &sdata);   symdefname = name.AllocSysString ();   status = ProDtlsymdefdataPathSet (sdata, symdefname);   SysFreeString (symdefname);   status = ProDtlsymdefdataHeighttypeSet (sdata, PRODTLSYMDEFHGHTTYPE_FIXED);   status = ProDtlsymdefattachAlloc (PROSYMDEFATTACHTYPE_FREE, 0 , 0.0 , origin, &attach);   status = ProDtlsymdefdataAttachAdd (sdata, attach);   status = ProDtlsymdefattachFree (attach);   status = ProDtlsymdefCreate (drawing, sdata, &symdef);   status = ProDtlsymdefdataFree (sdata);    } 
 
4.2 符号定义中绘制二维码 为便于描述,我们设定在符号中画一个1mm长,线宽1mm的线段作为二维码中的点。在符号中创建草绘与在绘图中创建草绘过程基本一致,只是在调用ProDtlentityCreate函数的参数中的第二个参数需指定为二维码的符号定义对象。创建草绘以及设定其属性在之前CREO Toolkit二次开发-草绘中心线 一文中已经进行了描述,在此不在赘述,直接给出源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 void  PrintQRCodeDot (ProDtlsymdef *symdef, ProVector start, ProColortype color)  {  ProError status;   ProDtlentity entity;   ProDtlentitydata edata;   ProCurvedata *curve;   ProColor entity_color;   ProVector end;   end[0 ] = start[0 ];   end[1 ] = start[1 ] + 1 ;   end[2 ] = start[2 ];   status = ProDtlentitydataAlloc (symdef->owner, &edata);   status = ProCurvedataAlloc (&curve);   status = ProLinedataInit (start, end, curve);   status = ProDtlentitydataCurveSet (edata, curve);   entity_color.method = PRO_COLOR_METHOD_TYPE;   entity_color.value.type = color;   status = ProDtlentitydataColorSet (edata, &entity_color);   status = ProDtlentitydataWidthSet (edata, 1.0 );   status = ProDtlentityCreate (symdef->owner, symdef, edata, &entity);   status = ProDtlentitydataFree (edata); } 
 
在第三节字符串转二维码中我们已获得了二维码信息矩阵,故只需根据该矩阵的信息在对应的位置调用PrintQRCodeDot绘制实心方块即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 void  QRcodeSymdefCreate (ProDrawing drawing, CString name, CString message, ProVector position)  {  ProError status;   ProDtlsymdefdata sdata;   ProVector origin = {0 , 0 , 0 }, start;   ProDtlsymdefattach attach;   ProDtlsymdef symdef;   wchar_t  *symdefname;   int  unWidth, x, y;   unsigned  char  *pSourceData;   QRcode *pQRC;   status = ProDtlsymdefdataAlloc (drawing, &sdata);   symdefname = name.AllocSysString ();   status = ProDtlsymdefdataPathSet (sdata, symdefname);   SysFreeString (symdefname);   status = ProDtlsymdefdataHeighttypeSet (sdata, PRODTLSYMDEFHGHTTYPE_FIXED);   status = ProDtlsymdefattachAlloc (PROSYMDEFATTACHTYPE_FREE, 0 , 0.0 , origin, &attach);   status = ProDtlsymdefdataAttachAdd (sdata, attach);   status = ProDtlsymdefattachFree (attach);   status = ProDtlsymdefCreate (drawing, sdata, &symdef);   status = ProDtlsymdefdataFree (sdata);   if  (pQRC = QRcode_encodeString (message, 0 , QR_ECLEVEL_L, QR_MODE_8, 1 ))   {     start[0 ] = 0.5 ;     start[1 ] = -0.5 ;     start[2 ] = 0.0 ;     pSourceData = pQRC->data;     unWidth = pQRC->width;     start[1 ] += unWidth;     for  (y = 0 ; y < unWidth; y++)     {       for  (x = 0 ; x < unWidth; x++)       {         if  (*pSourceData & 1 )         {           PrintQRCodeDot (&symdef, start, PRO_COLOR_LETTER);         }         start[0 ]++;         pSourceData++;       }       start[0 ] = 0.5 ;       start[1 ]--;     }     QRcode_free (pQRC);   }    } 
 
5.插入符号实例 插入符号也无非是设定相关参数并显示的操作,各函数调用也是基本的toolkit函数调用,注意内存的释放即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void  SymInstCreateFree (ProDrawing drawing, ProDtlsymdef *definition, ProVector position)  {  ProError status;   ProDtlsyminstdata sdata;   ProDtlattach attach;   ProDtlsyminst syminst;   status = ProDtlsyminstdataAlloc (drawing, &sdata);   status = ProDtlsyminstdataDefSet (sdata, definition);   status = ProDtlsyminstdataAttachtypeSet (sdata, PROSYMDEFATTACHTYPE_FREE);   status = ProDtlattachAlloc (PRO_DTLATTACHTYPE_FREE, NULL , position, NULL , &attach);   status = ProDtlsyminstdataAttachmentSet (sdata, attach);   status = ProDtlattachFree (attach);   status = ProDtlsyminstCreate (drawing, sdata, &syminst);   status = ProDtlsyminstdataFree (sdata);   status = ProDtlsyminstShow (&syminst); } 
 
插入二维码的实际演示效果如下图所示,读者也可以根据实际情况修改对应的文字、颜色及摆放位置:
     
    图 插入二维码示例
 
完整代码可在Github.com 下载。代码在VS2010,Creo 2.0 M060 X64下编译通过。
参考网址 [1] elicec/MFCQRcode. 2020-09-17[引用日期2020-09-17],https://github.com/elicec/MFCQRcode .