|
[摘 要] 通过在基于Windows NT平台的ugII(V16.0)中建立对话框、设置和读取对话框中各对象值、激活对话框和执行代码的编写,介绍了开发UGII内部应用程序的基本步骤,并指出了用UG/Open API编程时的注意点。 $ }, s. J) W& }/ G# u: }6 f
[关 键 词] UGII;内部应用程序;二次开发;( C: V9 h3 @+ |* q4 I+ ~" Q5 E
中图分类号: TP391.7 文献标识码:A
6 Z) b" M" s2 @9 U) h; i UGII作为机械领域的高档三维CAD/CAM/CAE软件,因其所具备的工程实用能力和良好的售后服务、技术支持,在国内正拥有越来越多的用户。在为企业提供服务的过程中发现,企业在使用该软件一段时间后,都会提出二次开发的要求,希望通过进一步的开发使UGII能更好地适应本企业的要求,从而进一步提高设计效率,减少使用UGII过程中技术人员的重复操作。所以本文就如何在以Windows NT为操作系统的微机工作站上进行基于VC++6.0的UGII(V16.0)二次开发进行介绍。 / {2 S; n4 g" P" q
UGII的二次开发程序有二种执行方式,可以是在UGII内部运行的程序和在UGII外部运行的程序,内部程序和外部程序开发方法基本相同,只是程序入口和某些API函数不一样,考虑到用户一般都希望所开发的程序能在UGII环境下运行,所以这里主要介绍UGII内部应用程序的开发方法[1-2]。对UGII内部应用程序的开发主要分为四个部分:⑴ 环境变量的设置;⑵对话框的建立与激活;⑶对话框对象数据设置和读取;⑷ 执行代码的编写。 : T, @5 C7 h( F3 l" C+ W# z5 }' p
3 K6 T- ]8 R9 _" z9 N/ P4 x1 W
1 环境变量的设置
. N3 N2 t' J' \% T; x8 {' J6 b6 l& `* U1.1 首先确保已购买了相应的UGⅡ二次开发许可证和执行许可证。 + r2 m F/ G" N0 B* ]# c" W
设定UGII启动时所读取的用户文件目录有两种方法:⑴可通过在UG_env.dat中指定UGⅡ_USER_DIR或UGⅡ_SITE_DIR或UGⅡ_VENDOR_DIR,如c:\UGS160\UGⅡ\my_development;⑵可以在操作系统的环境变量中指定,如UGⅡ_VENDOR_DIR=:\UGS160\UGⅡ\my_development。在该目录下建立startup和application子目录以放置用户菜单、对话框和动态连接库; 9 V; U4 \9 T m5 g
1.3 设置VC++6.0环境
1 b3 A7 i- \$ ^& e8 Q9 _⑴ 建立一个空的DLL文件 & s1 N" A4 V- G( W
File→new→Projects→Win32 Dynamic-Link Library→输入Project Name→An empty DLL Project→OK; . h" B; q, f: w- ]- F) b! B
⑵ 设置编译和连接选项
3 t. \8 k ~ Q+ m- rProject→Settings→C/C++→Category:Code Generation;Use run-time library:Mutli threaded DLL;
* g0 T/ h8 r( P& \7 s8 K4 KProject→Settings→Link→Object/library modules增加UG的二个库文件:libufun.lib、libugopenint.lib;
/ D7 G5 }: u1 N$ r) I$ n⑶ 设置Include路径和库文件路径
# N1 T# m1 h0 \2 N& A9 s) S. t/ b5 Y* C; {# D
Tools→Options→Directories→Show directories for→Include files:c:\UGS160\UGⅡ\ugopen;% @1 w! o+ i) Z! p& Q' H
( s' F! l5 U1 [) |; q7 `; O8 U, E4 @
Tools→Options→Show directories for→Library files:c:\UGS160\ugopen; ! B% y/ ]) c- s) O* S
\ T, l9 A+ {0 h9 Z% N2 对话框的建立与激活
, W* a" A" F+ |5 [4 ?
/ w: Y% ~8 ]' ?6 H 二次开发中的一个重要部分就是建立对话框,并在对话框与程序之间进行参数的传递,由于UG/Open UIStyler所创建的对话框与UGⅡ系统本身的对话框风格一致,所以一般用它来创建对话框。! p6 d3 V, T# j }
( `8 u2 W. w! ?& O
2.1 对话框的建立
. i0 J! P8 Q- l& F) v' k" ?1 l( D 启动UGⅡ→Application→激活User interface Styler,建立对话框。$ x5 ?$ D' U+ m5 |9 [6 ^
- Z4 C, R+ V8 }! U2 C6 j 在保存对话框时,UGII自动生成三个文件: 7 V) N3 v+ @* {$ ]
Variable.h:含有指向对话框每个对象的ID。
7 F: j; u ], ?. k G8 KVariable _template.c:包含了用MenuScript或UG/Open API集成对话框到内部应用程序的框架;
# _# f9 q& V/ ~& c% H( q4 n9 L$ xVariable dlg:是菜单脚本所规定的动作与API中激活UF_MB_add_styler_actions 的桥梁。 2 L, r! `; i; y7 z D" y1 ]$ Y
将对话框头文件和模板文件加入到project中,添加所需要的执行代码进行编译,并将所生成的DLL和 MENU文件存放到startup目录下,将*.dlg文件存放到application目录下。 . h( t9 n5 p8 |& |6 A% z
2 E2 A, \0 [4 ?( k& h# g
2.2 对话框的激活
* W! V1 Q3 s0 F6 X8 j2 B0 d- O 对于内部应用程序而言,对话框可通过三种方式被激活,其调用方式和入口函数如下: Z1 b8 U% D2 p
& Y8 j V' z& X5 |8 }4 h0 K(1)由菜单调用: void ufsta (char param, int *retcode, int rlen){ 函数体? } ) O8 W7 V/ O% U s8 k
(2)从其它Callback函数调用: int 函数名( int *response ) { 函数体? } 9 A) P8 E. @1 v* ^. P3 x/ w2 ?% Y/ m
(3)从UG的File→Execute UG/Open →User Function调用该dll文件,激活对话框: 1 |" n7 q9 ^ {1 a& A3 l
void 函数名 (char *param, int *retcode, int rlen) { 函数体 }
- L' `" n( q [5 j3 W' H$ f6 `, M9 N, d 对第1种方式系统使用int UF_MB_add_styler_actions (UF_MB_styler_actions_p_t actions )显示对话框;对于第2、3种方式时,系统调用intUF_STYLER_create_dialog (char*dialog_file, UF_STYLER_callback_info_t * cbs, int number_of_cbs, void * client_data,int * response )建立对话框;
6 }" [+ _0 l9 K, i5 d, y p @, o- |3 Z5 m
三种不同的调用方式所产生的结果也稍有不同。第1、2种方式,UGII启动时与对话框相关的DLL、menu文件就被同时载入,*.dlg文件则在使用时才被载入;第3种方式,DLL文件和*.dlg在系统调用DLL文件时被载入,所以对话框激活时的各对象初值会有所不同,这在编程时应加以注意。
+ F# q5 |% E" g7 T- @8 E 如果用来建立该对话框的函数名是自已给定的(上述的第2、3种方式),则应在相应的头文件中加以申明。对于从菜单调用的应编写菜单文件,以men为后缀存放到startup目录下面。例: # ^, \/ y! D5 U B# {( S' a( s
VERSION 120 , E$ a: L5 I' \ p1 Z3 y
EDIT UG_GATEWAY_MAIN_MENUBAR //编辑UGII主菜单条
$ f4 @5 L9 b0 B, ]& E- w
5 z, d" X, k2 b% yAFTER UG_TOOLBOX //给定增加菜单的位置,可根据情况规定
" c2 B; |. v" ~CASCADE_BUTTON CUSTOM //给出下拉菜单
9 V& C# t; O+ qLABEL CUSTOM? //给出下拉菜单标签名
4 j% w. c0 m: p+ s- pEND_OF_AFTER
4 T; Y+ E2 z6 G/ U9 EMENU CUSTOM //给出菜单项标签
" S6 v0 c. L$ ~- U8 J& tBUTTON C_PICTURE_BTN //在下拉菜单中增加菜单项 9 ^/ c" q2 s9 }5 B* m$ F, u1 H
LABEL Variable Transfer //给出菜单项名称
2 M' G8 t5 v) j4 |ACTIONS Variable.dlg //规定选中菜单项时所执行的动作 ' X- V, H* c0 Q/ y7 S8 r# ]
END_OF_MENU 3 l6 j' u3 N0 k3 [7 C' |
图1 UGII中插入的菜单6 \: B J* C. N8 f, a3 k
: H/ Q S. ^: T9 ^2 n' ~3 对话框对象的数据设置和读取
4 p8 f) o G1 n" [. ]9 f4 A
) _! I* G8 q0 ?' t9 J; V. A; Y 了解对话框中对象(Object)的数据结构可以清楚地实现对话框中对象与程序间数据的传递。在UG中所有对话框中的对象(Object)都具有相同的数据结构:
2 N, E3 T9 }" u8 z9 `0 ntypedef struct UF_STYLER_item_value_type_s { . K' I+ D" V, [
int reason;
+ X5 H5 r( ?* q: Q* dchar *item_id;//指出与API程序当前关联的对象名称
) ^* k. n4 r' rint subitem_index; ' ^4 X" O$ r. Q0 A2 C/ w
int count;& `& \( Q" N' F' q) k# F) X
int item_attr; //指出与API程序当前关联的对象属性 ) U* R" q3 v9 C+ @" X1 x p5 K
int indicator; W o8 |3 ?# s- q( r- I- v, I5 p
union{char *string; char *strings; int integer; int *integers;
, s" X& ~: ^- h9 s( R& V5 hdouble real;? double *reals;? UF_UI_selection_p_t *selection; @! _ h( h9 ?& U3 h
} value;
/ r8 A) W9 e# K} UF_STYLER_item_value_type_t, *UF_STYLER_item_value_type_p_t;
/ c$ V* y7 R8 W6 K! p! U U 其中item_id和 item_attr最为重要的,每次对对象的操作都必须首先指定它。下例介绍了如何设定图1对话框中对象Option:
9 z% F% f( J3 x5 yUF_STYLER_item_value_type_t data; //建立一个对象 \6 J: r. U5 [* M8 I: ^/ [5 z
data.item_id= DIALOG_OPTION_1? ; //指定该对象的ID(可以在头文件中查到) 8 I Q. C4 m3 H5 ^7 B
data.item_attr = UF_STYLER_SUBITEM_VALUES; //指定该对象的属性 * O, R* \9 T; z) h, R
data.count=number_of_exps; //指定加入的表达式数目 " I9 D9 t) f2 _/ f( }; `5 U9 a" i" d' r
data.value.strings = point; //传递表达式字符串指针数组的地址给该对象 ) ^: v6 \& }$ G: H
UF_STYLER_set_value(dialog_id,&data); //对该对象按上述要求进行设定。
) y$ u8 K: F, F& n0 V3 B% q 同样,读取对象的值时只需按要求设定好ID和ATTR等各项后,使用UF_STYLER_ask_value(dialog_id,&data)可读取该对象的值,如果一次希望读取多个对象的值,则用 int UF_STYLER_ask_values (int dialog_id, int num_values, UF_STYLER_item_value_type_p_t values, int * count )。当然不同Object所要设定的项和读取结果不一样,具体可查阅UIObject Reference。
8 }5 P [3 j) ~4 ~8 ]* N4 执行代码的编写4 x1 J4 e5 m: v/ f9 T
+ z s$ x. |4 ^7 v4 E* {2 O
在实现与对话框的交互后,就涉及到程序对所获取数据的处理,这主要通过调用UG/Open API中的函数实现,取决于用户对API函数的熟练程度。UGII要求二次开发程序的每个函数执行部分都放在UF_initialize()和UF_terminate()之间,例如对用菜单来激活对话框的入口函数: & o9 }$ G. D8 t2 t7 z8 }
void ufsta (char *param, int *retcode, int rlen){( N. s2 k- m W: k9 v! _
variable declarations; ) f8 v# I4 X. ~9 S; V
if((UF_initialize())!=0) // 初始化UG/Open API环境和分配一个UG/Open API执行许可 5 ~# V6 a6 T( s h8 S
return;
. J3 h9 Z# d0 N, W6 W# k$ L) JFunction body * ]) U! I8 Y0 m" C o
UF_terminate();//释放UG/Open API执行许可 " U& d6 Z/ f3 B1 x' t! r/ D! Q. s
Return? ; $ r$ i j7 y9 [, y+ e( E
}% U e9 t4 ]+ L* X
: B! ]& {+ K4 f& l) w# _' @
对话框和UG/Open API中需要用到大量的指针,所以在编写代码时对不用的资源应特别注意通过相应的函数及时释放,否则当对话框增多或操作步骤较多时,极易造成系统的不稳定。
* Q4 _. Y1 { N, l. D/ N5 结 论
9 d2 ]+ j' s3 J8 R1 G3 \ UGII软件本身提供了良好的二次开发功能,为用户进行适合特定要求的二次开发提供了丰富的工具。包括从编辑菜单、建立对话框到抽取或给定部件中对象、特征、装配信息的函数,只要充分运用UGII的现有功能,完全可以实现用户的各种特定要求。 |
|