• 基于C/C++的UG二次开发流程


    基于C/C++的UG二次开发流程

    1 环境搭建

    UG/Open API(UG 开放应用程序接口),也称 User Function(用户函数,简称 UF)。

    UF 的编程可以采用标准 C 或 C++两种方式作为开发语言(这里我们使用C++)。

    针对程序运行的环境不同,UF 程序又分为外部 UF内部 UF 两种形式。

    外部 UF 程序是可执行程序(*.EXE)。优点是不必启动 UG,属于后台运行,缺点是不能实现用户的交互操作。一般多用于 Part 文件大量创建、存取和管理或控制出图,而不适用于用户交互性的几何建模和修改。

    内部 UF 是以**动态链接库(*.DLL)**的形式创建并编译的。UG 调用内部 UF 的方式有两种,一种是启动 UG 后,点击菜单:【文件】→【执行】→【NX 打开】,从中选择需要执行的 DLL 文件(程序入口点:ufusr),另一种则是从用户创建的菜单中(Menu Script)调出用户定制的界面(UI Styler)来运行(程序入口点:ufsta)。内部 UF在用户的交互、屏幕选取等的复杂操作上具有优势。

    下文中我们主要介绍内部UF程序的开发。

    1.1 新建工程

    启动VS2022,由于是内部UF的开发,新建动态链接库(DLL)项目。

    在这里插入图片描述

    1.2 项目属性设置

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    libufun.lib
    libugopenint.lib
    libvmathpp.lib
    libnxopencpp.lib
    libnxopenuicpp.lib
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.3 添加入口函数并生成dll文件

    新建项目后,VS2022会默认生成framework.h、pch.h、pch.cpp、dllmain.cpp文件。接下来我们只需要修改dllmain.cpp,修改后内容如下:

    // dllmain.cpp : 定义 DLL 应用程序的入口点。
    #include "pch.h"
    #include "uf.h"				// 包含常用 UF 函数的声明
    #include "uf_modl.h"		// 包含建模相关的 UF 函数声明
    #include "uf_ui.h"			// 包含界面操作相关的 UF 函数声明
    #include 
    
    #define UF_CALL(X) (report( __FILE__, __LINE__, #X, (X)))
    
    // 用于程序调试
    static int report(char* file, int line, char* call, int irc)
    {
    	if (irc)
    	{
    		char msg[133];
    		printf("%s, line %d: %s\n", file, line, call);
    		(UF_get_fail_message(irc, msg)) ?
    			printf("returned a %d\n", irc) :
    			printf("returned error %d: %s\n", irc, msg);
    	}
    	return(irc);
    }
    
    // 实际工作函数
    static void do_ugopen_api(void)
    {
    	/* 用户在此编写自己的 UF 程序 */
    	/* 下面示例为创建长方体 */
    	UF_FEATURE_SIGN sign = UF_NULLSIGN;
    	double block_orig[3] = { 0.0,0.0,0.0 }; // 原点
    	char* block_len[3] = { "1","2","3" };	// 三边长
    	tag_t blk_obj;
    	UF_CALL(UF_MODL_create_block1(sign, block_orig, block_len, &blk_obj)); // 调用UF_MODL_create_block1函数创建长方体
    }
    
    
    void ufusr(char* param, int* retcode, int paramLen)
    {
    	if (!UF_CALL(UF_initialize()))//获取二次开发许可 
    	{
    		do_ugopen_api();//实际工作函数 
    		UF_CALL(UF_terminate());//释放二次开发许可 
    	}
    	else
    	{
    		uc1601("获取开发许可失败,退出!", 1);//获取二次开发许可失败,提示用户 
    	}
    }
    
    // 卸载函数
    int ufusr_ask_unload(void)
    {
    	return (UF_UNLOAD_IMMEDIATELY);//完成操作后立即从内存中卸载
    }
    
    • 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
    • 50
    • 51
    • 52
    • 53
    • 54

    修改属性页,将符合模式改为,防止编译运行报错“const char *“ 类型的实参与 “char *“ 类型的形参不兼容

    参考文章:「VS」“const char *“ 类型的实参与 “char *“ 类型的形参不兼容
    在这里插入图片描述

    最后点击运行,即可得到内部UF的dll文件。

    在这里插入图片描述

    1.4 执行程序

    打开UG,新建一个part文件。Ctrl+U打开上一步生成的DLL文件(test.dll)。UG 会执行此动态库中的入口函数ufusr,在 UG 建模工作区中生成一个长方体。
    在这里插入图片描述

    1.5 ufsta入口

    在上面我们执行内部UF程序的方法是从ufusr入口进入(即Ctrl+U执行DLL文件),接下来我们介绍从ufsta入口进入的方法(即UI交互执行对应回调函数)。

    1.5.1 创建程序部署目录结构

    首先创建一个工作目录,其中分别再创建两个子目录“startup”和“application”。前者用来存放菜单文件(*.men)和动态库文件(*.dll),后者存放对话框文件(*.dlg)。
    在这里插入图片描述-

    1.5.2 创建菜单文件

    startup目录下创建一个菜单文件(test_ufsta.men),内容如下:

    VERSION 120
    EDIT UG_GATEWAY_MAIN_MENUBAR
    HIDE UG_HELP
    !一级菜单编辑,在帮助菜单后
    BEFORE UG_HELP
     CASCADE_BUTTON MENU_TestUfsta
     LABEL TestUfsta
    END_OF_BEFORE 
    !二级菜单编辑
    MENU MENU_TestUfsta 
     BUTTON BUTTON_TestUfsta 
     LABEL 测试ufsta 
     ACTIONS TestUfsta.dlg
    END_OF_MENU
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1.5.3 设置系统环境变量

    新建一个环境变量UGII_USER_DIR,将上面的程序工作目录作为值。

    在这里插入图片描述

    新建完成后,打开UG,点击菜单,即可得到我们想要的效果。
    如果出现中文乱码的问题,将men文件采用ANSI编码保存即可解决。
    在这里插入图片描述

    1.5.4 制作对话框

    UG中提供了UI Styler模块用于制作对话框UI,支持图形化操作,自动生成代码框架(类似于Qt Designer)。该模块的打开方式如下(需要先打开一个部件):

    在这里插入图片描述

    我们便可以得到一个最基础的对话框,左下角为预览效果,左上角为控件对象层级树,右边为控件对象属性。

    在这里插入图片描述

    点击界面上方工具栏中的按钮,即可在对话框中添加一个按钮。

    在这里插入图片描述

    接着我们将按钮的标签更改成一个我们想要名称,最后点击保存,选择使用的语言(这里选择C++),文件名为TestUfsta.dlg,保存到application目录下,

    在这里插入图片描述

    • xxx.dlg。对话框资源文件。

    • xxx.hxx。对此对话框编程使用的头文件。

    • xxx_template.c。对此对话框编程使用的代码框架。

    1.5.5 创建代码

    和ufusr入口一样,新建一个命名为TestUfsta的DLL工程,将上一步生成的xxx.h文件拷贝到工程目录下,再将xxx_template.c文件中的一个宏定义和两个静态变量,以及ufsta(UF 的入口点)、CHANGE_apply_cb(对话框上【apply】按钮的回调函数)、CHANGE_action_0_act_cb(对话框上用户定制的【创建长方体】按钮的回调函数)三个函数复制到TestUfsta.cpp中。修改后内容如下:

    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include  
    #include 
    #include 
    #include "TestUfsta.h"
    
    #define CHANGE_CB_COUNT ( 2 + 1 ) /* Add 1 for the terminator */
    #define UF_CALL(X) (report( __FILE__, __LINE__, #X, (X)))
    
    // 用于程序调试
    static int report(char* file, int line, char* call, int irc)
    {
        if (irc)
        {
            char msg[133];
            printf("%s, line %d: %s\n", file, line, call);
            (UF_get_fail_message(irc, msg)) ?
                printf("returned a %d\n", irc) :
                printf("returned error %d: %s\n", irc, msg);
        }
        return(irc);
    }
    
    // 实际工作函数
    static void do_ugopen_api(void)
    {
        /* 用户在此编写自己的 UF 程序 */
        /* 下面示例为创建长方体 */
        UF_FEATURE_SIGN sign = UF_NULLSIGN;
        double block_orig[3] = { 0.0,0.0,0.0 }; // 原点
        char* block_len[3] = { "1","2","3" };	// 三边长
        tag_t blk_obj;
        UF_CALL(UF_MODL_create_block1(sign, block_orig, block_len, &blk_obj)); // 调用UF_MODL_create_block1函数创建长方体
    }
    
    static UF_STYLER_callback_info_t CHANGE_cbs[CHANGE_CB_COUNT] =
    {
     {UF_STYLER_DIALOG_INDEX, UF_STYLER_APPLY_CB        , 0, CHANGE_apply_cb},
     {CHANGE_ACTION_0       , UF_STYLER_ACTIVATE_CB     , 0, CHANGE_action_0_act_cb},
     {UF_STYLER_NULL_OBJECT, UF_STYLER_NO_CB, 0, 0 }
    };
    
    static UF_MB_styler_actions_t actions[] = {
        { "TestUfsta.dlg",  NULL,   CHANGE_cbs,  UF_MB_STYLER_IS_NOT_TOP },
        { NULL,  NULL,  NULL,  0 } /* This is a NULL terminated list */
    };
    
    extern void ufsta(char* param, int* retcode, int rlen)
    {
        int  error_code;
    
        if ((UF_initialize()) != 0)
            return;
    
        if ((error_code = UF_MB_add_styler_actions(actions)) != 0)
        {
            char fail_message[133];
    
            UF_get_fail_message(error_code, fail_message);
            printf("%s\n", fail_message);
        }
    
        UF_terminate();
        return;
    }
    
    int CHANGE_apply_cb(int dialog_id,
        void* client_data,
        UF_STYLER_item_value_type_p_t callback_data)
    {
        /* Make sure User Function is available. */
        if (UF_initialize() != 0)
            return (UF_UI_CB_CONTINUE_DIALOG);
    
        /* ---- Enter your callback code here ----- */
    
        UF_terminate();
    
        /* Callback acknowledged, do not terminate dialog                 */
        /* A return value of UF_UI_CB_EXIT_DIALOG will not be accepted    */
        /* for this callback type.  You must respond to your apply button.*/
        return (UF_UI_CB_CONTINUE_DIALOG);
    
    }
    
    int CHANGE_action_0_act_cb(int dialog_id,
        void* client_data,
        UF_STYLER_item_value_type_p_t callback_data)
    {
        /* Make sure User Function is available. */
        if (UF_initialize() != 0)
            return (UF_UI_CB_CONTINUE_DIALOG);
    
        /* ---- Enter your callback code here ----- */
        do_ugopen_api();
    
        UF_terminate();
    
        /* Callback acknowledged, do not terminate dialog */
        return (UF_UI_CB_CONTINUE_DIALOG);
    
        /* or Callback acknowledged, terminate dialog.    */
        /* return ( UF_UI_CB_EXIT_DIALOG );               */
    
    }
    
    • 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
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110

    运行生成DLL。

    对于VS2022,新建DLL工程后会默认生成和使用pch.h作为预编译头文件,为了不必要的麻烦,我们将工程属性设置为不使用预编译头文件,即可删除pch相关的文件。
    在这里插入图片描述

    1.5.6 部署和执行

    将所生成的DLL文件拷贝到startup目录下,打开UG即可成功运行。

    在这里插入图片描述

  • 相关阅读:
    B+树的定义以及查找
    常见的数值转换函数
    Problem A: 检查数中重复的数字
    Bindiff安装以及使用
    2023年腾讯云双11活动云服务器价格表
    Docker学习(3)—— 将容器转化为新的镜像,并将新镜像发布到阿里云公共仓库或私有仓库
    猿创征文 | Docker实战:Linux环境安装Tomcat安装步骤
    带你入门HTML+CSS网页设计,编写网页代码的思路
    C++中关于树的一些定义
    《JAVA设计模式系列》解释器模式
  • 原文地址:https://blog.csdn.net/qq_39784672/article/details/134005927