请注意:本例假定您已使用默认安装选项安装了 X#,并且 X# 运行时已安装在 GAC 中。
如果没有安装,则无法运行该示例。请参阅本文档中的相关章节。
作为 XPorting VO 应用程序的第一个示例,我们以 VO Explorer 为例。
启动 VO Xporter 程序并将其指向 VO Explorer 示例:
在我的机器上,VO 安装在 C:\Cavo28SP3 文件夹中。当然,这在你的机器上可能有所不同。
我没有更改任何 xPort 选项。这些选项是
选项 |
描述 |
RemoveClassClause |
删除方法和 accesses/assigns 赋值的 “Class 子句”。这将在 CLASS ... END CLASS 块中对所有方法进行分组,然后就不再需要方法级的 CLASS 子句了 |
ChangeInitAxitToCtorDtor |
Init 和 Axit 是 VO 中的保留方法名。在 DotNet 中,这些名称经常被类使用。Vulcan 和 X# 引入了新的关键字 CONSTRUCTOR 和 DESTRUCTOR。该选项会自动重命名 Init 和 Axit 方法。示例 METHOD Init(oOwner) CLASS MyClass 会转换为 CONSTRUCTOR(oOwner) |
RemoveDeclareMethod |
如果在 VO 中使用强类型,则需要添加 DECLARE METHOD 语句和/或 DECLARE ACCESS 和 DECLARE ASSIGN。X# 编译器仍能识别这些语句,但不再需要它们 |
RemoveExportLocalClause |
该选项删除了 EXPORT LOCAL 子句,该子句可以包含在 VO 代码的方法声明中,但在 X# 中会被忽略。 |
AllClassesArePartial |
分部类是 Vulcan 和 X# 中的一种机制,它允许你将一个类分割到多个源文件中。如果你的类变得很大,或者你想将生成的代码与手写的代码分开(就像 Visual Studio 中的 Windows 窗体编辑器所做的那样),这可能会很方便。你可以选择让所有 Xporter 类都是分部的。我们禁用了这一功能,因为使用时会对性能造成(少量)影响。尤其是当你将类中的 Accesses 和 Assigns 分割到不同的文件中时。 |
AddMissingConstructors |
VO 允许您声明一个没有 Init 方法/构造函数的类。.Net中也允许这样做,但编译器会认为你的类有一个不带参数的构造函数。该选项将自动生成缺失的构造函数。请注意,如果启用了 /vo16 兼容选项,即使代码中没有指定构造函数,X# 编译器也支持生成缺失的构造函数。因此,这个 Xporter 选项已不再需要并被弃用。 |
IgnoreDuplicateDefines |
如果选择此项,重复定义将被忽略,不会写入输出文件。 |
Don’tGenerateEmptyFiles |
VO 应用程序中的每个模块都将成为 X# 中的源文件。该选项将抑制空源文件的生成 |
AdjustCallbackFunctions |
一些(高级)VO 代码包含回调函数,其中一个函数的地址会传递给另一个函数并被调用。Windows API 经常使用回调函数,例如用于枚举窗口或打印机。这种机制在 .Net 中不起作用。该选项将更改您的代码,并帮助您获得可行的解决方案。 |
ExportOnlyDefines |
通过该选项,您可以生成一个只包含所选 AEF 或文件中定义的 DLL。如果您以前曾使用 Vulcan Transporter 移植过代码,并希望删除包含定义的头文件,这可能会很有用。 |
Sort Entities by name |
这将根据名称对所有实体排序,函数和方法将在 CLASS... ENDCLASS 中排序。 |
Use XSharp Runtime |
选择此项(默认值)时,您的应用程序将根据 X# 运行时进行编译。否则,我们将使用 Vulcan 运行时(我们的产品中不包含该运行时) |
Copy Resources to Project folder |
选择该选项后,应用程序资源实体中使用的所有 BMP、ICO、CUR 等资源都将复制到项目中的资源子文件夹。 |
Replace Resource Defines with Values |
这可以控制将与菜单选项相关的数字标识符和表单上的控制标识符导出到外部资源文件的方式 |
Check For IVar and Property Conflicts |
在 Visual Objects 中,允许 ACCESS/ASSIGN 方法与同类的 IVar(通常是 INSTANCE vars)同名。在 .Net 中不允许这样做,因此如果启用该选项,Xporter 将检测到这一点,并在 IVar 名称前加上下划线(“_”)。 |
Ignore code inside #ifdef...#endif |
作为准备将 Visual Objects 代码移植到 X# 的一种方法,通常的做法是在源代码的 VO 版本中提供相同代码的 VO 版本和 X# 版本,并用 #ifdef __XSHARP__ ... #else ... #endif 预处理器指令。设置该选项后,Xporter 不会修改任何被这些指令包围的代码。 |
XPorter 将允许您为 Visual Studio 解决方案和项目文件选择目标文件夹和名称。
按 xPort 键后,您将看到以下文件夹
C:\XporterOutput\Examples\Explorer
C:\XporterOutput\Examples\Explorer\Explorer
C:\XporterOutput\Examples\Explorer\Explorer\Resources
C:\XporterOutput\Examples\Explorer\Explorer\Properties
第一个文件夹是所谓的 “解决方案” 文件夹
子文件夹包含项目及其文件。
如果您选择了多个 AEF 文件,那么每个 AEF 文件在 “解决方案” 文件夹下都有自己的子文件夹。
解决方案文件夹包含文件:
文件 |
内容 |
Explorer.sln |
VS 解决方案文件 |
Explorer.viproj |
XIDE 项目文件 |
Project 文件夹包含以下文件:
文件 |
内容 |
Customer Explorer.prg |
模块源代码 |
Data Servers.prg |
模块源代码 |
Explorer Shell.prg |
模块源代码 |
Explorer.viapp |
XIDE 应用程序文件 |
Explorer.xsproj |
VS 项目文件 |
Help About.HelpAboutDialog.rc |
VS 使用的表单资源 |
Help About.HelpAboutDialog.xsfrm |
VS 使用的表单 "二进制" |
Help About.prg |
模块源代码 |
Help About.rc |
XIDE 使用的表单资源 |
Icons.ICONONE.rc |
VS 使用的图标资源 |
Icons.ICONTWO.rc |
VS 使用的图标资源 |
Icons.prg |
模块源代码 |
Icons.rc |
XIDE 使用的图标资源 |
Menus.CustomerExplorerMenu.rc |
VS 使用的菜单资源 |
Menus.CustomerExplorerMenu.xsmnu |
菜单 "二进制" |
Menus.CustomerExplorerMenu_Accelerator.rc |
VS 使用的菜单加速器资源 |
Menus.EMPTYSHELLMENU.rc |
VS 使用的菜单资源 |
Menus.EMPTYSHELLMENU.xsmnu |
二进制菜单 |
Menus.EMPTYSHELLMENU_Accelerator.rc |
VS 使用的菜单加速器资源 |
Menus.OrdersListViewMenu.rc |
VS 使用的菜单资源 |
Menus.prg |
模块源代码 |
Menus.rc |
XIDE 的菜单资源 |
Start.prg |
模块源代码 |
为了编译和生成项目,我们在 Visual Studio 中打开文件 Explorer.SLN。在 Visual Studio 中,它看起来像
几个模块前面的箭头表示这些模块中有子项目。这些子项目包含表单、菜单和图标资源。
现在,让我们尝试在 Visual Studio 中生成解决方案。(菜单选项 “生成-生成解决方案")
这将编译应用程序,并在 c:\XporterOutput\Explorer\Debug 文件夹中生成一个可调试版本。你会看到该文件夹包含一个 EXE、PDB(调试符号)和 VO 运行时库的副本:
Explorer.exe
Explorer.pdb
SDK_Defines.dll
VOGUIClasses.dll
VORDDClasses.dll
VOSystemClasses.dll
VOWin32APILibrary.dll
XSharp.VO.dll
XSharp.RT.dll
XSharp.Core.dll
现在可以尝试运行应用程序了。这可以运行,但一旦我们选择 “文件/打开” 菜单选项,就会出现运行时错误。调整大小后,屏幕看起来类似下面这样:
错误信息很清楚:应用程序使用了 splitwindow 控件,而这需要 splitwindow 支持 DLL。
该 DLL 位于 VO 安装的 Redist 文件夹中。只需将 VO Redist 文件夹中的 “Cato3spl.dll ”文件和 MSVCRT.DLL 复制到输出文件夹,然后再试一次。
您也可以将 DLL 添加到项目中(添加现有项目,并指向 Redist 文件夹中的 DLL)。这将把它们复制到项目文件夹中。然后将这 2 个 DLL 的生成操作设置为 “无”,并将 “复制到输出目录 ”属性设置为 “保留最新内容”。现在,当您生成应用程序时,DLL 将被复制到正确的文件夹中。
之后,代码将像在 VO 中一样运行,无需更改代码!
让我们仔细看看 xPorter 都做了些什么:
•VO 中的每个模块都已成为 X# 项目中的 PRG 文件
•源代码已按类分组,并置于 CLASS ... END CLASS 结构中
•Init 方法已更名为 CONSTRUCTOR
•编译器宏(如“%CavoSamplesRootDir%\Explorer\”)已被字面值取代: “C:\cavo28SP3\Samples\Explorer\”
•资源已成为定义它们的源文件的 “子文件”。
•资源的位置也已更改 %CavoSamplesRootDir%\Explorer\TWO.ICO 已更改为 ICONTWO Icon C:\cavo28SP3\Samples\Explorer\TWO.ICO。
RESOURCE 关键字也已删除。
•表单和菜单的二进制文件尚未包含在此版本的 XPorter(Beta 11)中。这种情况将会改变。
•启动文件的变化最大。在 VO 中,有一个方法 App:Start()。但 App 类并没有在此应用程序中定义,而是 GUI 类的一部分。应用程序中也没有 Start 函数。VO 将调用 GUI 类中的 Start 函数,并将应用程序中的 App:Start() 方法与 GUI 类中 App 类的其余部分合并。
这在 .Net 中是不允许的。类不能分布在一个以上的程序集(.Net 对库、EXE 或 DLL 的称呼)中。
•因此,XPorter 创建了一个新类 (xApp),并将 Start 方法移到了这个 Xapp 类中。它还添加了一个 Start() 函数,用于实例化 App 类并调用 XApp 中的 Start 方法。在下面的示例中,您还可以看到添加了一个 TRY ... CATCH ... END TRY 结构,它可以捕获其他地方捕获不到的错误,并在 ErrorBox 对象中显示错误信息。这就是之前由于 CATO3SPL.DLL 丢失而显示的错误框。
•最后,“开始 ”函数被标记为一个属性(方括号中的单词)。在本例中,属性为 [STAThread],这意味着主函数(以及整个应用程序)需要以单线程模式运行。如果您的应用程序使用 OCX/ActiveX 控件等外部代码,这一点非常重要。
-
• 如果您仔细查看 Visual Studio 中的解决方案资源管理器,并点击树中的引用节点,就会发现示例中引用了 Vulcan 运行时和 VO 类库,以及 XPorter 附带的 SDK 定义库。
•如果打开项目属性,你会在常规页面上看到所选的方言是 “Visual Object”,在方言页面上设置了大多数 VO 选项,在生成页面上,平台目标是 x86(因为图形用户界面类设计为在 x86 模式下运行),并且抑制了一些警告。这些警告包括:
编号 |
含义 |
162 |
抑制关于无法访问代码的警告 |
618 |
抑制对使用过时函数(如 CollectForced)的警告 |
649 |
取消对未使用的 private 和/或 internal 字段的警告。 |
9025 |
消除关于缺少 Return 语句的警告 |
9032 |
消除关于 ASSIGN 方法和/或构造函数/析构函数中返回值的警告 |
9043 |
消除关于含糊代码的警告,如果两个程序集定义了同名函数,可能会出现这种情况。 |
在本例中,编译器只生成了 618 警告,因为 CustomerExplorer:Close() 方法调用了 CollectForced。注释掉这一行后,您就可以删除应用程序中所有 “抑制 ”的警告,这样编译时就不会出现任何警告了。
您可以在 XSharp 示例文件夹中找到 “Code before ”和 “Code after”。