XControl
这一节将详细介绍 XControl 的制作方法。为了便于讲解,将以 “界面设计实例” 中提到的棋盘为主要例子,介绍如何制作一个 XControl 控件。在讲解 XControl 的某些特殊功能时,也会介绍一些其它的例子。
设计
XControl 的主要特点是可以把它的界面元素与相关的代码封装在一起,从而便于发布和重用这些界面组件。但是 XControl 也有不足之处,它的开发难 度较大。此外,不合理的 XControl 可能导致程序出现更严重的问题,比如导致程序界面死锁等。所以,在开发 XControl 之前,一定要精心设计它的结构和行为,以避免出现错误。
在开发一个新的界面组件之前,首先要考虑一下以何种方式实现这个组件。
如果一个界面组件极为特殊,且只可能用在某个特定的程序中,那也许就没有必要将其制作成单独的控件了。可以把这个界面组件做成一个独立的子界面 VI,然后通过子面板控件调用这个界面。
如果这个组件需要被多次使用,那么就应该考虑把它做成可重用的独立控件。如果这个控件不包含任何特殊行为,比如一个新型按钮,仅其外观与一般的按钮不同,其它行为都与传统的按钮一模一样。这样的控件适合制作成用户自定义控件。
如果新的组件需要重用,其行为与已有的其它控件又有较大差别,那么就要考虑使用 XControl 了。比如:需要制作一个新按钮,它比传统按钮多一个状态;制作带有动画效果的控件;制作使用中国本土度量单位的数值类控件;制作一个专用于绘制某种特殊曲线的图片控件等。它们都比较适合使用 XControl 来开发。
前面提到的黑白棋的控件,它既有特殊界面,又有特殊行为,又可以应用于不同软件中,它就非常适合做成 XControl。
首先要具体设计这个 XControl 所需的界面和行为。
它的界面部分可以直接利用界面设计实例一节中设计好的界面。在前文提到的几个设计方案中,使用图片下拉列表数组控件的解决方案,编程代码最简单。所以,在设计 XControl 时就采用这个界面方案。
XControl 在程序框图上的接线端的输入输出数据应该是应用程序中最经常需要与 XControl 交互的数据。本例中,应用程序最常使用的数据是棋盘的布局信息。因此,这个 XControl 的输入输出数据应当是一个表示棋盘上棋子的布局的 8×8 的整型数组。
黑白棋控件的属性应当包括:当前该下什么颜色的子、可落子的位置、盘面上每种颜色的子数、上次落子的位置等。
它的方法应当包括:落下一个棋子的方法。这个方法需要包含以下具体的操作:在新位置放置一个棋子;翻转被吃掉的棋子;更新数据和所有属性的值。
还有,当用户在交互界面上摆放下一个子之后,需要发送一个事件通知应用程序。
创建
在项目浏览器上,点击鼠标右键,选择 "新建 ->XControl",就可以创建一个新的 XControl:

XControl 在结构上是一种特殊的库。它包含一些特定的功能 VI,和一些可选的属性、方法 VI 及其它相关文件。在新建的 XControl 上已经包含了 4 个必须的功能 VI(控件):"数据"(Data)、"状态"(State)、"外观"(Façade)、以及 "初始化"(Init)。XControl 还有两个可选的功能 VI:"反初始化" 和 "转换状态以保存"。
数据功能控件:用来定义 XControl 的数据类型;
状态功能控件:定义除数据功能之外所有 XControl 内部使用到的数据;
外观功能 VI:XControl 中最主要的功能 VI,用以实现 XControl 的界面和界面上的行为;
初始化功能 VI:设置 XControl 的初始状态;
反初始化功能 VI:负责清理工作,从内存中删除 XControl 时,释放所有分配给该 XControl 的资源;
转换状态以保存功能 VI:用于把 XControl 内部的某些数据保存在使用它的 VI 中。
反初始化功能 VI 和转换状态以保存功能 VI 在新创建的 XControl 中不存在。如果需要使用到它们,可以在项目浏览窗口的 XControl 上点击鼠标右键,选 "新建 -> 功能",为 XControl 添加一个功能 VI。
XControl 被保存在一个.xctl 文件中。它与 LabVIEW 库文件十分相似,可以把它看作是一种特殊的 LabVIEW 库文件。它的属性设置与 LabVIEW 库的设置也一模一样:

先把这个新创建出来的 XControl 存盘。XControl 功能 VI 的文件名并不一定与其功能名相同。比如,在这个演示中,为了方便更多人使用,可以选择使用英文名称来保存 XControl:

需要注意:XControl 的功能 VI 由 LabVIEW 系统调用,并具有预设的输入输出接口。我们在编写 XControl 的时候一定不要改变它们的输入输出控件,以及接线端的布局。我们也不可以直接在其它的 VI 中直接调用这些功能 VI。XControl 开发者需要做的只是填充功能 VI 所需的程序代码。功能 VI 之间的数据无法直接传递,也不应该使用全局变量,只可以通过由功能控件定义的“数据”和“状态”来传递。