跳到主要内容

二次开发

二次开发

Lua开发

Lua开发界面

SFB支持内嵌Lua开发环境,支持Lua编程、运行、单步调试、变量查看。支持Lua XXX版本。

Lua与SFB场景的交互原理:通过内置信号量函数实现。

  1. 界面介绍

点击【菜单栏】-【信号】-【Lua脚本】按钮,打开Lua脚本管理窗口。

  1. 功能栏:功能栏包含操作、调试两项
  2. 工作区:显示多个Lua脚本的目录
  3. 编辑区:对已打开的脚本文件进行编辑
  4. 日志输出:显示运行输出日志
  5. 操作功能

脚本的文件基础操作功能如下:

  1. 调试功能

脚本文件程序的调试功能如下:

SFBLua接口说明

SFB实现的Lua自定义接口说明:

  1. void print(string content)

功能:打印输出

参数:content,字符串,即要输出的字符内容;

返回:无

  1. void timedelay(int ms)

功能:延时等待

参数:ms,整数,时间长度,单位毫秒;

返回:无

  1. bool readbool(int index)

功能:读开关量

参数:index,整数,索引值,不应该大于开关量的最大值8191;

返回:开关量的值;

  1. bool writebool(int index, bool value)

功能:写开关量

参数:index,整数,索引值,不应该大于开关量的最大值8191;

value, 布尔,待写入的值;

返回:写入的值

  1. int readint(int index)

功能:读数字量

参数:index,整数,索引值,不应该大于数字量的最大值8191;

返回:数字量的值;

  1. int writeint(int index, int value)

功能:写数字量

参数:index,整数,索引值,不应该大于数字量的最大值8191;

value, 整数,待写入的值;

返回:写入的值

  1. float readfloat(int index)

功能:读浮点量

参数:index,整数,索引值,不应该大于浮点量的最大值8191;

返回:浮点量的值;

  1. float writefloat(int index, float value)

功能:写浮点量

参数:index,整数,索引值,不应该大于浮点量的最大值8191;

value, 浮点数,待写入的值;

返回:写入的值

  1. TcpListener listenPortInit(int port, bool stopSame)

功能:TCP端口监听初始化

参数:port,整数,端口号,端口号不允许重复以及与系统端口冲突,否则会异常;

stopSame, 布尔,是否先停止与输入端口相同的监听再创建新的端口监听;

返回:已经创建的端口监听对象;

  1. void listenPortStart(TcpListener lis)

功能:启动TCP端口监听

参数:lis,TCP端口监听对象;

返回:无

  1. TcpClient listenConnect(TcpListener lis)

功能:侦听客户端连接,此接口会等待直到有客户端连接才返回;

参数:lis,TCP端口监听对象;

返回:连接到此监听的TCP端口的客户端;

  1. void listenPortStop(TcpListener lis)

功能:停止TCP端口监听

参数:lis,TCP端口监听对象;

返回:无

Python开发

SFB支持Pythoh插件环境,支持Pythoh编程、运行、单步调试、变量查看。支持Pythoh XXX版本。

Pythoh与SFB场景的交互原理:通过内置信号量函数实现。

  1. 界面介绍

点击【菜单栏】-【应用】-【Python】按钮,打开Python脚本处理器窗口。

  1. 功能栏:功能栏包含运行时管理、项目管理、依赖管理及运行状态管理
  2. 工作区:以树状结构显示多个Python项目的目录结构及项目运行状态
  3. 编辑区:对已打开的文件进行编辑
  4. 日志输出:显示插件输出的日志及通过内置日志输出函数打印内容
  5. 运行时管理

  1. 点击“运行时”按钮打开运行时管理窗口

  1. 通过下拉选项,选择已安装的运行时版本

  1. 也可通过输入版本号,点击安装来下载未安装版本的运行时,等待安装完成
  2. 项目管理

  1. 点击新建项目,在弹出窗口输入项目名称,创建一个新的Python工程目录

  1. 选择要添加新文件夹的项目或文件夹,点击新建文件夹,在弹出窗口输入文件夹名称,创建一个新的文件夹

  1. 选择要添加新文件的项目或文件夹,点击新建文件,在弹出窗口输入文件名称并选择文件类型,创建一个新的文件

  1. 在树形结构中,选中某一个节点,点击删除或在右键菜单中选择删除,可删除该项目/文件夹/文件

  1. 选择一个Python项目,点击依赖管理,打开模块管理窗口

  1. 在模块输入框输入模块名称,如:panda,如果要指定模块版本,在版本输入框输入版本号,留空则安装最新版本

  1. 在列表中选中已安装的模块,点击卸载则删除该模块
  2. 运行状态管理

  1. 选中想要运行或停止的Python项目,点击运行当前或停止当前来控制项目状态
  2. 点击运行所有,则会所有勾选使能的项目
  3. 点击停止所有,则会停止所有已运行的项目
  4. SFB进入运行状态时,所有勾选使能的项目也会随之运行;SFB退出运行状态时,所有项目也会随之停止

插件开发应用

SFB插件介绍

  1. SFB 插件简介

插件是遵循一定规范的应用程序接口编写出来的程序,只能在程序规定的系统平台下,不能脱离指定的平台单独运行。我们常见的插件有 WEB 浏览器插件,如 Flash 插件、Office插件、Visual Studio 插件、Eclipse 插件。

SFB 插件是遵循 SFB 插件开发规范,编写的应用程序,插件只能运行在 SFB 平台下。

  1. MEF 框架简介

MEF(Managed Extensibility Framework)是微软为大型应用程序(比如 Visual Studio)提供的一个功能扩展框架,通过一个混合层提升了灵活性、维护性和可测试性。

SFB 基于 MEF 插件框架,为第三方开发者提供插件扩展服务,在不改变 SFB 程序的情况下,扩展 SFB 功能。

  1. 开发前准备

SFB 插件开发,首先要获取 SFB 插件开发必备的动态库,该动态库位于 SFB 安装目录的“PluginDLL”目录。如果需要了解 SFB 的安装,请参考《SFB 使用说明书》软件安装章节。

SFB 插件开发,目前仅支持 C#语言,.net Framwerow 4.6.2 开发环境。强烈建议采用安装 Visual studo 2017,同时包含.net Framwerow 4.6.2 组件方式安装插件开发环境。

插件开发

MEF 基础知识

SFB 插件开发,需掌握基础 C#开发知识外,还需对 MEF 开发框架的基本原理有所了解,至少应掌握导入(Import)、导出(Export)、组合容器(CompositionContainer)的基本概念和2简单使用。

  1. MEF 基本原理

MEF 的工作原理是对部件(Part)的需求(Import)和供应(Export)。 每当应用对某部件(Part)有需求(Import)时,MEF 组合引擎(CompositionContainer)将在我们指定的位置(Catalog)查找遵循共同的契约(Contract)的供应(Export),并自动创建这些部件的实例。

  1. MEF 基本概念

⚫ Part(部件): Part 是一个可以在应用程序中进行导入或导出操作的对象(可以是

类、方法、属性)

⚫ Catalog(仓库): 协助从程序集或目录中发现有效的部件的对象;

⚫ Contract(契约): 导入和导出的部件之间的一些约定(接口或预先定义的数据类型,如字符),部件通过这些约定进行通信;

⚫ Import 特性(导入): 声明导入部件的需求;

⚫ ImportMany 特性: 支持导入多个部件的导入声明;

⚫ Export (导出): Import 声明导入部件需求,Export 则声明实现这些需求。

⚫ Compose(组合): 将匹配的导入与导出组合在一起。

更详细的 MEF 知识,请参考

https://docs.microsoft.com/en-us/dotnet/framework/mef/

扩展 SFB 工具栏

SFB 插件,通常是以 SFB 工具栏功能按钮的形式,展示给用户。SFB 允许第三方在【应用】工具栏分页下,添加工具栏分组和工具栏按钮。其中,工具栏按钮,必须包含在工具栏分组之中。

通过下面的示例,在 SFB 工具栏【应用】分页中,添加【我的扩展】工具栏分组和【我的按钮】功能按钮;点击【我的按钮】功能按钮,显示消息提示框。

SFB 工具栏

  1. 扩展工具栏分组

⚫ 首先,在 Visual Studio 中,创建一个新的控制台应用程序项目,此处注意:实现接口的程序集必须以“Plugin.”开头,如“Plugin.Tool.dll”

新建工程

⚫ 从 SFB 安装根目录中,拷贝“PluginDLL”文件夹至工程目录下

⚫ 引用 SFB 插件开发动态库

在控制台项目中,添加对“PluginDLL”文件夹中,SFB.PluginContract.dll 和

SFB.PluginUtility.dll 两个动态库的引用

引用动态库

⚫ 引用 MEF 框架 System.ComponentModel.Composition 程序集的引用

MEF 程序集

项目引用

⚫ 新建 RibbonGroup 类,继承并实现 IRibbonGroupBox 接口在ibbonGroup 类,除了继承 IRibbonGroupBox,还声明了导出(Export)特征,并标记契约类型为 IRibbonGroupBox,因此该类成为 MEF 的部件(Part)。

实现 IRibbonGroupBox 契约的部件,将由于 MEF 组合至 SFB,SFB 读取相关信息,并创建工具栏分组。

⚫ 将工程修改为类库,并发布

由于 SFB 只搜索.DLL 扩展名的动态库,因此将项目修改为“类库”,编译生成动态库

⚫ 部署 SFB 扩展插件 PluginTool6

在 SFB 插件安装目录(安装目录下 Plugin 目录),新建“PluginTool”目录,然后将PluginTool 项目生成的动态库,拷贝至该目录

⚫ 运行 SFB,加载插件

运行 SFB 后,在 SFB“应用”工具栏分页中,已添加“我的扩展”工具栏分组

注意事项:

  • 工具栏分组的父级编码,即 ParentUUID,是由 SFB 定义的;必须与 SFB 定义的 UUID 保持一致。
  • SFB 只能从扩展名为.DLL 的动态库中,查找插件,因此插件必须是以.DLL 形式。
  • SFB 只查找位于安装目录下 Plugin 目录中的插件。
  1. 扩展工具栏按钮

SFB 通过工具栏分组,对 SFB 工具栏上的按钮进行分组管理;而工具栏按钮,是 SFB 与用户交互功能按钮。通过插件形式扩展的的工具栏按钮,必须依附于特定的工具栏分组。

在前一章节,我们已经具备了一个名为“MyPlugin”的工具栏按钮分组,在 SFB 工具栏上显示为“我的扩展”。通过下面的示例,我们在“我的扩展”按钮分组中,添加名为“MyButton”的按钮,在 SFB 工具栏上显示为“我的按钮”点击后显示一个 Windows 窗口。

扩展 SFB 工具栏分组时,接口中包含一个按钮集合 List<IRibbonButton > Buttons;SFB 会根据该集合中对按钮的描述,创建新的工具栏按钮添加到指定的工具栏分组中。

⚫ 定义实现 IRibbonButton 接口类

新建 PluginButton,实现 IRibbonButton;

⚫ 修改 RibbonGroup 类,生成按钮集合

⚫ 编译后,更新插件

更新插件,同时将两个 png 图片,保存在该插件安装目录下

⚫ 运行 SFB

注意事项:

  • 按钮关联的命令,采用了 SFB.PluginUtility 命名空间中定义的命令相关类PluginCommand;使用该类,必须引用 SFB.PluginUtility.DLL 程序集。可以为按钮指定其它实现 ICommand 接口的命令,SFB 并不强制要求使用 PluginCommand。
  • 按钮的图标,采用的是相对路径;路径格式为:插件安装根目录名称\图标名称.扩展名

SFB信号量读写

SFB 通过导出(Export)SFB.PluginContract 命名空间中的 ISFBDataAccess 契约,为插件开发者提供 SFB 信号量读写服务。插件开发者,如需读写 SFB 信号量,只需导入(Import)即可。

SFB 中实现导出(Exprot)ISFBDataAccess 契约的部件,位于IFB.PluginExtension.DLL动态库,因此必须将 SFB.PluginExtension.DLL 动态库包含在插件目录中。

下面通过修改前一章节的示例,演示如何读写 SFB 信号量。

⚫ 新建读写 SFB 信号类 SFBDataAccess,并导入 ISFBDataAccess 契约

⚫ SFBDataAccess 添加读写整型量接口 ReadIntValue,WritteIntValue

⚫ 组合实现了契约的部件

通过 import 特征,声明需要导入(Import)实现 ISFBDataAccess 契约的导出(Export);由于 SFB 在 SFB.PluginExtension.DLL 动态库中,实现了 ISFBDataAccess 契约的部件。因此,我们通过组合容器(CompositionContainer)导入该部件;组合过程,在构造函数中实现

⚫ 新建 Winform 窗口,接收用户输入,并显示输入

⚫ 添加读取与显示控件

控件类型

名称

用途

NumericUpDown

numIntIndex

设置整型量索引

NumericUpDown

numIntValue

显示读取的整型量或设置写入的整型量

Button

btnReadInt

执行整型量读取动作

Button

btnWritteInt

执行整型量写入动作

⚫显示信号量读写窗口

通过前几步,已经实现了信号量的读写。为了通过点击按钮,显示信号量读写窗口。我们修改 12.3.2 章节中实现的 RibbonGroup 类

⚫ 编译并更新 SFB 插件

⚫ 运行,并测试 SFB 信号量读写

注意事项:

  • SFB 信号量读写需求,并不是通过静态引用 SFB.PluginExtension.DLL 动态库实现的,而是由组合容器导入符合契约的部件实现;代码中指定组合容器查找到的路径为插件所在路径,因此,即使没有引用 SFB.PluginExtension.DLL 动态库动态库,在部署插件时,插件部署目录必须存在 SFB.PluginExtension.DLL 动态库,否则组合容器查找不到合适的部件,导入会失败,导致读写功能无法实现。

响应SFB回调

SFB.PluginContract 程序集中的 ISFBAction 契约,定义了 SFB 回调契约。所有导出(Export)该契约的部件,都会被 SFB 导入,并在 SFB 执行期间,调用相应的契约接口。

我们通过在 SFB 打开工程时,获取工程所在路径为示例,演示如何应用 ISFBAction 契约。

⚫ 在 PluginTool 项目中,新增 SFBAction 类SFBAction 类,实现 ISFBAction,并声明为实现 ISFBAction 契约的导出;

⚫ LoadedProject 接口方法中,获取工程路径

⚫ 编译,并更新插件

⚫ 运行 SFB,每次打开 SFB 工程后,会提示当前工程路径

更多的 SFB 回调契约,请查看第 3 章 SFB 插件契约部分

SFB插件契约

IRibbonGroupBox

通过 IRibbonGroupBox 契约,实现对 SFB 工具栏的扩展

  1. 定义

命名空间 SFB.PluginContract

程序集:SFB.PluginContract.DLL

  1. UUID 属性

string UUID { get; }

工具栏分组全局唯一编码,相同 UUID 的插件会被分到同一个组中

  1. ParentUUID 属性

string ParentUUID { get; }

工具栏分组父级全局唯一编码,即工具栏分页全局唯一编码

  1. Index 属性

int Index { get; }

工具栏分组排序索引

  1. Header 属性

string Header { get; }

工具栏分组标题

  1. Buttons

List<IRibbonButton > Buttons { get; }

工具栏分组中的按钮集合;按钮实现 IRibbonButton 接口

ISFBDataAccess

通过 ISFBDataAccess 契约,实现对 SFB 信号量读写操作。

  1. 定义

命名空间 SFB.PluginContract

程序集:SFB.PluginContract.DLL

  1. GetBoolMemoryByIndex 方法

⚫ 定义

bool? GetBoolMemoryByIndex(int index);

读取 SFB 开关量指定索引位置的值

⚫ 参数

Index int

index 表示读取信号量地址16

⚫ 返回

bool?

读取失败,返回空值;

  1. SetBoolMemoryByIndex 方法

⚫ 定义

bool SetBoolMemoryByIndex(int index, bool value);

设置 SFB 开关量指定索引位置的值

⚫ 参数

Index int

index 表示读取信号量地址

Value bool

Value 表示新设置的值

⚫ 返回

bool

设置成功,返回 True,否则返回 False;

  1. GetIntMemoryByIndex 方法

⚫ 定义

bool GetIntMemoryByIndex(int index,out int value);

读取 SFB 数字量指定索引位置的值

⚫ 参数

Index int

index 表示读取信号量地址

Value int

Value 表示读取的值

⚫ 返回

bool

读取成功,返回 True,否则返回 False;

  1. SetIntMemoryByIndex 方法

⚫ 定义

bool SetIntMemoryByIndex(int index, int value);

设置 SFB 数字量指定索引位置的值

⚫ 参数

Index int

index 表示设置信号量地址

Value int

Value 表示新设置的值

⚫ 返回

bool

设置成功,返回 True,否则返回 False;

  1. GetFloatMemoryByIndex 方法

⚫ 定义

bool GetFloatMemoryByIndex(int index, out float value);

读取 SFB 浮点量指定索引位置的值

⚫ 参数

Index int

index 表示读取信号量地址

Value float

Value 表示读取的值

⚫ 返回

bool

读取成功,返回 True,否则返回 False;

  1. SetFloatMemoryByIndex 方法

⚫ 定义

bool SetFloatMemoryByIndex(int index, float value);

设置 SFB 浮点量指定索引位置的值

⚫ 参数

Index int

index 表示设置信号量地址

Value float

Value 表示新设置的值

⚫ 返回

bool

设置成功,返回 True,否则返回 False;

ISFBAction

ISFBAction 契约,定义了 SFB 回调接口;实现 ISFBAction 契约的部件,SFB 在运行期间,会调用部件的

  1. 定义

命名空间 SFB.PluginContract19

程序集:SFB.PluginContract.DLL

  1. 方法

⚫ 定义

void Inition(string version);

SFB 初始化完成时调用方法

⚫ 参数

Version string

Version 表示 SFB 版本号

⚫ 返回

Void

  1. StateChanged

⚫ 定义

void StateChanged(bool isRunning);

SFB 运行状态改变时调用方法

⚫ 参数

isRunning bool

isRunning 表示 SFB 是否处于运行状态;True 表示运行状态;False 表示非运行状态

⚫ 返回

Void

  1. CreateProject

⚫ 定义

void CreateProject(string projectPath);20

SFB 创建新工程时调用方法

⚫ 参数

projectPath string

projectPath 表示 SFB 新建工程的目录路径

⚫ 返回

Void

  1. SavingProject

⚫ 定义

void SavingProject();

SFB 保存工程前调用的方法

⚫ 参数

⚫ 返回

Void

  1. SavedProject

⚫ 定义

void SavedProject();

SFB 保完成工程保存调用的方法

⚫ 参数

⚫ 返回

Void21

  1. LoadedProject

⚫ 定义

void LoadedProject(string projectPath);

SFB 工程加载完成时调用的方法

⚫ 参数

projectPath string

projectPath 表示 SFB 加载工程的目录路径

⚫ 返回

Void

  1. ClosedProject

⚫ 定义

void ClosedProject();

SFB 关闭工程时调用的方法

⚫ 参数

⚫ 返回

Void

  1. Closing

⚫ 定义

void Closing();

SFB 正在关闭时调用的方法

⚫ 参数

⚫ 返回

Void

  1. Closed

⚫ 定义

void Closed();

SFB 关闭前调用的方法

⚫ 参数

⚫ 返回

Void

SFB 插件开发约定

工具栏编码约定

SFB 插件开发规则约定,通过插件扩展的工具栏按钮分组,只能通过唯一识别码,添加到指定的工具栏分页上;识别码错误,将无法创建。

当前版本,SFB 仅开放应用分页;插件开发者可以在此分页上添加工具栏按钮分组。

工具栏元素

唯一识别码

【应用】分页

PluginInApplication

插件部置路径约定

⚫ SFB 插件路径位于 SFB 安装路径根目录下的 Plugin 目录

⚫ 所有的插件,应包含单独的安装文件夹;假设有 PluginTool 插件,则该插件所有动态库应部署在:SFB 安装路径根目录\Plugin\PluginTool 路径下

插件动态库版本号

SFB 插件开发规则约定,SFB 插件开发动态库的版本,通过 SFB.PluginContract 动态库,SFB.PluginContract 命名空间的PluginContractVersion 静态类的 Version 属性获取。

工具栏按钮接口

SFB 插件开发规则约定,所有添加至工具栏分组中的按钮,都必须实现 IRibbonButton接口,否则无法识别IRibbonButton 定义在 SFB.PluginContract 动态库,SFB.PluginContract 命名空间。

  1. UUID 属性

string UUID { get; }

全局唯一编码

  1. ParentUUID

string ParentUUID { get; }

父级全局唯一编码

  1. Index

int Index { get; }

按钮排序索引

  1. Header

string Header { get; }

按钮标题内容24

  1. IconUri 属性

string IconUri { get; }

按钮小图标路径; 该路径为相对于 SFB 插件部署路径的相对路径

  1. LargIconUri 属性

string LargIconUri { get; }

按钮大图标路径; 该路径为相对于 SFB 插件部署路径的相对路径

  1. ExcutComand 属性

ICommand ExcutComand { get; }

按钮绑定的命令

  1. ToolTip 属性

string ToolTip { get; }

按钮提示信息

API列表