ZW3D 二次开发-制作插件
一.前提要求
1.Windows 7 SP1 或 Windows 10 或 Windows 11(推荐 Windows 11)
2.Visual studio 2017-2022 (或 C/C++的任何其他集成开发环境)(推荐 Visual studio 2022)
3.ZW3D 2023 或以上版本(建议使用与 ZW3D 一致的 API 的版本)
4.Qt5.9.7(for Windows)
博主学习使用环境的是:
Windows 11 Version 24H2 + Visual studio 2022 + Qt5.9.7(for Windows)
二.安装 ZW3DTemplateVSIXProject 工程模板
zw3d 提供了 ZW3DTemplateVSIXProject.vsix 可以方便使用以建立工程,当然也可以手鲁。
【免费】中望3D二次开发工程模板文件资源-CSDN文库
ZW3DTemplateVSIXProject.vsix 支持 Visual studio 2017-2022。 双击该安装程序会自动检测本地的 Visual Studio 平台(适配2017、 2019、 2022 版本),双击后根据提示安装向导模板.
注:安装 Visual studio 2022 过程自行百度.
三.建立 ZW3D 测试插件工程 (Zw3dTest)
1.根据您的 Visual Studio 版本选择对应的模板直接创建开发工程.因为博主用的是Visual studio 2022,所以选择 ZW3D API Template Project for VS2022.
2.创建好的工程资源管理器
main:
#include "..\inc\Zw3dTestPr.h"// Dynamic library entry function, called when the dll is loaded
// The function name must be dll name + "Init"
int Zw3dTestInit(){RegisterCustomCommand();RegisterTemplateCommand();RegisterFormCommand();return 0;}// Dynamic library entry function, called when the dll is unloaded
// The function name must be dll name + "Exit"
int Zw3dTestExit(){UnloadCustomCommand();UnloadTemplateCommand();UnloadFormCommand();return 0;}
TemplateCommand:
#include "zwapi_cmd_paramdefine_param.h"
#include "zwapi_cmd_paramdefine_tpl.h"
#include "..\inc\Zw3dTestPr.h"#define Field_Entity 1static int TemplateCmd(int idData);
static void TemplateCmdInit(int idData);
static int TemplateCmdInitA(int idData);
static void TemplateCmdEcho(int idData, void* ohEcho);
static void TemplateCmdTerm(void);
static int TemplateCmdCb(char* form, int idField, int item);int RegisterTemplateCommand(void)
/*
DESCRIPTION:Register callback function of template command.
*/{/* Start the command by entering command string "!TemplateCmd" */cvxCmdFunc("TemplateCmd", (void*)TemplateCmd, VX_CODE_GENERAL);cvxCmdCallback("TemplateCmdInit", (void*)TemplateCmdInit);cvxCmdCallback("TemplateCmdInitA", (void*)TemplateCmdInitA);cvxCmdCallback("TemplateCmdEcho", (void*)TemplateCmdEcho);cvxCmdCallback("TemplateCmdTerm", (void*)TemplateCmdTerm);cvxCmdCallback("TemplateCmdCb", (void*)TemplateCmdCb);return 0;}int UnloadTemplateCommand(void)
/*
DESCRIPTION:Unload callback function of template command.
*/{cvxCmdFuncUnload("TemplateCmd");cvxCmdFuncUnload("TemplateCmdInit");cvxCmdFuncUnload("TemplateCmdInitA");cvxCmdFuncUnload("TemplateCmdEcho");cvxCmdFuncUnload("TemplateCmdTerm");cvxCmdFuncUnload("TemplateCmdCb");return 0;}int TemplateCmd
(int idData /* I: index of data container */
)
/*
DESCRIPTION:Execution function of command. the function is called when the command
is clicked on the OK or APPLY button.
*/{// TODO: Do somethingcvxMsgDisp("TemplateCmd");/* Inquire data of data container */int nEnts = 0, * idEnts = 0;cvxDataGetEnts(idData, Field_Entity, &nEnts, &idEnts);cvxMemFree((void**)&idEnts);return 0;}void TemplateCmdInit
(int idData /* I: index of data container */
)
/*
DESCRIPTION:Initialize callback function of command. the function is called when the command
is initialized. In this callback function, you can initialize the data of command,
but the command form has not yet been created at this time, so should not initialize
the command form in this callback function.
*/{// TODO: Do somethingcvxMsgDisp("TemplateCmdInit");}int TemplateCmdInitA
(int idData /* I: index of data container */
)
/*
DESCRIPTION:Init-after callback function of command. the function is called when the command
is initialized. In this callback function, you can initialize the command form.
*/{// TODO: Do somethingcvxMsgDisp("TemplateCmdInitA");return 0;}void TemplateCmdEcho
(int idData, /* I: index of data container */void* ohEcho /* I: handle of preview object */
)
/*
DESCRIPTION:Preview callback function of command, the function is called when the parameters
of command change.
*/{cvxEchoStart();// TODO: Do somethingcvxMsgDisp("TemplateCmdEcho");cvxEchoEnd();}void TemplateCmdTerm(void)
/*
DESCRIPTION:Terminate callback function of command form, the function is called when the command
is clicked on the CANCEL button to exit.
*/{// TODO: Do somethingcvxMsgDisp("TemplateCmdTerm");}int TemplateCmdCb
(char* formName, /* I: form name */int idField, /* I: index of command parameter field */int idData /* I: index of data container */
)
/*
DESCRIPTION:Callback function of command parameter field, the function is called when value
of the specify parameter field changes.
*/{// TODO: Do somethingcvxMsgDisp("TemplateCmdCb");return 0;}
CustomCommand:
#include "..\inc\Zw3dTestPr.h"static int Zw3dTest(void);
static int PrintString(char* string);int RegisterCustomCommand(void)
/*
DESCRIPTION:Register custom command.
*/{/* Start the command by entering command string "~Zw3dTest" */cvxCmdFunc("Zw3dTest", (void*)Zw3dTest, VX_CODE_GENERAL);/* Start the command by entering command string "~PrintString(Hello ZW3D API)" */cvxCmdFunc("PrintString", (void*)PrintString, VX_CODE_GENERAL);return 0;}int UnloadCustomCommand(void)
/*
DESCRIPTION:Unload custom command.
*/{cvxCmdFuncUnload("Zw3dTest");cvxCmdFuncUnload("PrintString");return 0;}int Zw3dTest(void)
/*
DESCRIPTION:Custom command.
*/{// TODO: Do somethingcvxMsgDisp("调用 Zw3dTest 函数成功");return 0;}int PrintString
(char* string /* I: input string */
)
/*
DESCRIPTION:Custom command.
*/{// TODO: Do somethingcvxMsgDisp(string);return 0;}
FormCommand:
#include "zwapi_ui_form.h"
#include "zwapi_ui_tablewidget.h"
#include "zwapi_ui_treeview.h"
#include "..\inc\Zw3dTestPr.h"const char gFormName[] = "FormCmd";
const int gTableWidgetField = 101;
const int gTreeViewField = 102;static int ShowForm(void);
static int FormCmd(int idIn, int* idOut);
static int FormCmdCb(char* form, int idField, int item);
static int TableWidgetCb(char* form, int idField, int idItem);
static int TreeViewCb(char* form, int idField, int idItem);int RegisterFormCommand()
/*
DESCRIPTION:Register callback function of form command.
*/{/* Show form by entering command string "~ShowForm" */cvxCmdFunc("ShowForm", (void*)ShowForm, VX_CODE_GENERAL);/* Register callback function of form */cvxFormFunc(const_cast<char*>(gFormName), (void*)FormCmd, VX_CODE_GENERAL);cvxCmdCallback("FormCmdCb", (void*)FormCmdCb);return 0;}int UnloadFormCommand()
/*
DESCRIPTION:Unload callback function of form command.
*/{cvxCmdFuncUnload("ShowForm");cvxCmdFuncUnload("FormCmd");cvxCmdFuncUnload("FormCmdCb");return 0;}int ShowForm(void)
/*
DESCRIPTION:Custom command to show form.
*/{/* Create form if it has not already been created */int formState = cvxFormState(const_cast<char*>(gFormName));if (formState == 0 && cvxFormCreate(const_cast<char*>(gFormName), 0))return 1;/* Show form */cvxFormShow(const_cast<char*>(gFormName));return 0;}int FormCmd
(int idIn, /* I: index of data container */int* idOut /* O: index of data container */
)
/*
DESCRIPTION:Execution function of command form.
*/{switch (idIn){case VX_FORM_INIT:{// TODO: Do somethingcvxMsgDisp("Initialize form");}break;case VX_FORM_CANCEL:{// TODO: Do somethingcvxMsgDisp("Exit form");}break;case VX_FORM_RESET:{// TODO: Do somethingcvxMsgDisp("Reset form");}break;case VX_FORM_APPLY:{// TODO: Do somethingcvxMsgDisp("Apply form");}break;case VX_FORM_OKAY:{// TODO: Do somethingcvxMsgDisp("Exit form");}break;case VX_FORM_DEFAULT:{// TODO: Do somethingcvxMsgDisp("Default settings");}break;default:break;}return 0;}int FormCmdCb
(char* form, /* I: form name */int idField, /* I: index of field */int idItem /* I: index of item */
)
/*
DESCRIPTION:Callback function of command form.
*/{switch (idField){case gTableWidgetField:{/* Table widget control event handling */TableWidgetCb(form, idField, idItem);}break;case gTreeViewField:{/* Tree view control event handling */TreeViewCb(form, idField, idItem);}break;default: break;}return 0;}int TableWidgetCb
(char* form, /* I: form name */int idField, /* I: index of field */int idItem /* I: index of item */
)
/*
DESCRIPTION:Table widget control event handling function.
*/{svxTableAt at = {};svxTableCallBackParam vsData = {};char szText[128] = "\0";cvxTableCallBackParamGet(form, idField, &vsData);/* if press ctrl, shift or alt key, do nothing */if (vsData.key.modifier != 0)goto F_END;switch (vsData.evt){case VX_LEFT_CLICK:{// TODO: Do somethingcvxMsgDisp("Left-click");}break;case VX_RIGHT_CLICK:{// TODO: Do somethingcvxMsgDisp("Right-click");}break;case VX_LEFT_DOUBLE_CLICK:{// TODO: Do somethingcvxMsgDisp("Left-double-click");}break;case VX_KEY_UP_DOWN:{// TODO: Do somethingcvxMsgDisp("Key up and down");}break;case VX_HOT_KEY:{// TODO: Do somethingcvxMsgDisp("Hot-key");}break;case VX_SORT:{// TODO: Do somethingcvxMsgDisp("Sort");}break;case VX_DATA_CHANGED:{// TODO: Do somethingcvxMsgDisp("Data changed");}break;case VX_CELL_BUTTON_CLICKED:{// TODO: Do somethingcvxMsgDisp("Button in table cell clicked");}break;case VX_MOUSE_MOVE:{// TODO: Do somethingcvxMsgDisp("Mouse move");}break;case VX_CELL_CLOSE_EDITOR:{// TODO: Do somethingcvxMsgDisp("Table cell close editor");}break;default: break;}F_END:cvxTableCallBackParamFree(&vsData);return 0;}int TreeViewCb
(char* form, /* I: form name */int idField, /* I: index of field */int idItem /* I: index of item */
)
/*
DESCRIPTION:Tree view control event handling function.
*/{char szText[256] = "\0";svxTreeCbParam treeCbData;if (cvxTreeGetCbParam(form, idField, idItem, &treeCbData)) return 0;evxTreeHitPos hitPos = treeCbData.uvxu.svxhit.pos;if (treeCbData.mode == VX_HOVER)return 0;switch (treeCbData.mode){case VX_LEFT_DOWN:{// TODO: Do somethingcvxMsgDisp("Left-click down");}break;case VX_LEFT_UP:{// TODO: Do somethingcvxMsgDisp("Left-click up");}break;case VX_MIDDLE_DOWN: {// TODO: Do somethingcvxMsgDisp("Middle-click down");}break;case VX_MIDDLE_UP:{// TODO: Do somethingcvxMsgDisp("Middle-click up");}break;case VX_RIGHT_DOWN: {// TODO: Do somethingcvxMsgDisp("Right-click down");}break;case VX_RIGHT_UP:{// TODO: Do somethingcvxMsgDisp("Right-click up");}break;case VX_BOX_SELECTION_DONE:{// TODO: Do somethingcvxMsgDisp("Box selection over");}break;case VX_LABEL_CHANGED:{// TODO: Do somethingcvxMsgDisp("Label changed");}break;case VX_EDITOR_CLOSED:{// TODO: Do somethingcvxMsgDisp("Item editor closed");}break;case VX_DBL_LEFT:{// TODO: Do somethingcvxMsgDisp("Left-double-click");}break;case VX_DROP:{// TODO: Do somethingcvxMsgDisp("Drop after dragging");}break;case VX_KEY_PRESS: {// TODO: Do somethingcvxMsgDisp("Key press");}break;case VX_HOVER: {// TODO: Do somethingcvxMsgDisp("Normal hover");}break;case VX_HOVER_TIMEOUT: {// TODO: Do somethingcvxMsgDisp("Hovered timeout");}break;case VX_ENTER: {// TODO: Do somethingcvxMsgDisp("Enter");}break;case VX_LEAVE: {// TODO: Do somethingcvxMsgDisp("Leave");}break;default: break;}return 0;}
注:代码下节再展开讲,这节只是讲流程.
3.查看并修改属性
3.1平台使用 v143
3.2 C/C++ →常规→附加包含目录,可以使用变量 $(ZW3D_DIR)或写绝对路径.
$(ZW3D_DIR)api\inc 或 D:\Program Files\ZWSOFT\ZW3D 2025\api\inc
3.3 链接器→常规→附加库目录,可以使用变量 $(ZW3D_DIR)或写绝对路径.
$(ZW3D_DIR) 或 D:\Program Files\ZWSOFT\ZW3D 2025
3.4 链接器→输入→附加依赖项和模块定义文件.
3.5 要编译资源,请将以下的命令行添加至: 生成事件→后期生成事件→命令行.添加事件命令
IF EXIST "$(ZW3D_DIR)zrc.exe" "$(ZW3D_DIR)zrc.exe" "$(SolutionDir)." -o "$(TargetDir)$(ProjectName).zrc"
注:没有资源可不添加此事件命令.
3.5 配置好工程数据后,生成工程dll.
四.测试 ZW3D 测试插件工程 (Zw3dTest)
1.加载插件有3种方式.
第一种方式。
直接使用 ZW3D 的应用程序管理器来加载这个 DLL 文件,输出对话框的信息将显示命令成功还是失败。
第二种方式。
复制 Zw3dTest.dll 至用户目录下的"apilibs"文件夹, 然后启动 ZW3D。ZW3D 会自动加载"apilibs"文件夹下的插件程序.
"%appdata% \ZWSOFT\ZW3D\ZW3D 2025\custom\apilibs"
第三种方式。
您需要在开启 ZW3D 前在注册表"HKEY_CURRENT_USER\Software\ZWSOFT\ZW3D"中添加资源信息, 如 29.00(2025)版本的 ZW3D 对应插件注册表在"ZW3D29.00\en_US\Plugin_x64"中,您需要创建一个新的项,并且为其添加如下的内容,其中 Application 为 dll 文件名称, Description为插件描述, Load 为插件加载标记,填写 7 即可, Location 为 dll 所在文件夹, Resource 为创建模板命令时需要添加的 zrc 文件完整路径。
2.测试调用命令.
五:结束语
以上步骤是ZW3D最初步的入门,后面开发还有制作菜单、工具条、、函数调用、插件界面等等。希望大大家有所帮助。