Show/Hide Toolbars

XSharp

 

VFPXporter 工具旨在通过 XSharp 帮助您将 Visual FoxPro (VFP) 应用程序迁移到 .NET,使用您已经熟悉的语言。

 

1.在导出过程中对代码的更改最小化

2.如果进行了任何更改,将原始代码保留为注释

3. 使用名为 XSharp.VFP.UI.Dll 的适配层/库,将 VFP 表单迁移到 Windows Forms

4. 将 VCX 库作为包含表单/控件的外部项目进行迁移

5. 创建真实的 Windows Forms 解决方案/项目,以便您可以在应用程序中使用任何现有的第三方 .NET 库

 

启动和设置

首先,打开设置对话框:

VFPExporter1

文件夹设置

VFPExporterSettings

默认 VFP 项目文件夹(Default VFP item Folder):VFPXPorter 将默认从该文件夹开始搜索要导出的元素。

默认输出文件夹(Default Output Folder):VFPXPorter 将在该文件夹中创建生成的导出内容。

默认导出资源文件夹(Default exporter resources Folder):VFPXPorter 将在该文件夹中查找额外的模板/库/工具等。

 

然后你可以:

重置设置为默认值(Reset Settings)。

打开存储 .json 设置文件的设置文件夹(Open Settings Folder), 例如用于备份。

 

导出设置

VFPExporterSettings2

检查或取消检查导出设置:通常默认值是最佳选择。

 

默认字段修饰符(Default Fields modifiers):导出类时,设置默认字段的可见性。

 

项目设置

VFPExporterSettings3

忽略导出错误( Ignore export Errors):允许在出现错误时继续导出过程。所有错误都会记录在目标文件夹中。

如果需要,您可以为导出元素的文件夹指定自己的名称。

每个类库在一个子文件夹中(Each ClassLibrary is in a SubFolder):如果您的应用程序使用库,最好将它们单独导出。  

清空目标文件夹(Empty the destination folder):每次导出元素时,目标文件夹都会被清空。

导出

项目

VFPExporterExport

输入项目(Input Project):搜索要导出的 .PJX 文件。

输出文件夹(Output Folder):指定 VFPXPorter 将生成文件写入的位置。

分析(Analyze):允许查看 VFPXPorter 在项目中检测到的内容。

导出(Export):导出项目。

打开(Open):打开包含生成文件的文件夹。

 

生成的文件夹应包含多个文件夹(如果已勾选设置,则每个库一个文件夹,一个用于检测到的 FreeTables,一个用于 XSharp 工具,...)。

 

您将找到一个与导出项目同名的文件,扩展名为 .SLN。这是 MS Visual Studio 解决方案文件,将组合所有导出的顶级项目(项目、库等)。

这是您应首先打开的文件。

VFPXPorter 工作原理

VFPXPorter 将读取您的项目及其元素。它会识别它们的类型并生成一些 X# 代码。

为了生成代码,它会查看 Data 文件夹。

在那里,我们可以找到几个 .JSON 文件,它们被用作转换规则:

这些规则的文档可在 GitHub 的 VFPXPorter repository 中找到

然后,它将使用一些模板来生成文件: 每种文件类型一个。您可以在 GitHub 上找到这些模板 : 模板

从 VFP 进行转换

常见问题

在将您的 VFP 图形用户界面代码转换为 X# 和 WinForms 时,我们会遇到一些常见问题,请参见以下列表。

事件和方法命名

将应用程序从 VFP 转换到 X# 和 WinForms 时,您必须牢记这两个 “世界” 对您的窗体使用不同的视角。
 

在 VFP 中,事件被路由到控件

因此,我们可以认为,例如,窗体上的每个按钮都有自己的类,该类继承自基类 CommandButton,并且是该特定类的实例: 因此,您可以重写该级别的事件和方法,这样就可以对发生的事情进行大量控制。

在 WinForms 中,事件会传递给控件的所有者: 表单

因此,使用方法是在事件处理程序和方法的前缀加上控件的名称。

如果 button1 引发了单击事件,那么处理程序的名称就是 button1_click。

如果是表单引发事件,由于表单是类,因此处理程序的名称将是 nameOfTheForm_Event。

您可以通过导出器设置更改该名称:

 

(以 FORM 名称作为事件方法的前缀Prefix Event methods with FORM name)

 

Start() 函数

生成的代码包含一个 Start() 函数,它是生成应用程序的启动对象。如果您在 VFP 代码中也使用了 Start() 函数,则必须在导出后对其进行重命名。

Init() 方法

在 VFP 中,创建对象时会调用 Init() 方法。

在 X# 中,调用类的 Constructor() (使用 MyClass{} 语法)不会自动调用 Init() 方法。

在导出过程中,InitType.prg 模板会模拟这一过程。

对于控件,在创建句柄时会调用 Init() 方法。这段代码由导出时使用的 InitType.prg 模板生成。

颜色

遗憾的是,这些都无法自动处理,因为这会破坏 Visual Studio 中的 Windows 窗体设计器。

使用 RGB 设置 BackColor 或 ForeColor,如 :

   this.Label1.ForeColor = RGB(255,0,0)

将被转换为:

   this.Label1.ForeColor = System.Drawing.Color.FromARGB( 255,0,0) )

BUT.... 如果您在 PRG 文件中使用名为 RGB() 的函数返回 System.Drawing.Color 颜色,那么它将成为您导出解决方案的一部分,并取代 XSharp Runtime 定义,这样就可以解决这个问题了!

 

无参数的方法调用

在 X# 中,“属性” 包含一个用等号设置/获取的 “值”,而 “方法” 包含调用时执行的代码。

这在 VFP 中是允许的,但在 X# 中您必须纠正这一点

   this.Refresh

应更正为:

   this.Refresh()

如果在设置中勾选 “将语句转换为调用(Convert Statement to Call)”,就可以在导出时纠正这些问题。

处理过的语句在 Statements.json 文件中。

 

表单属性封装

要使用 Visual Studio 中的 Windows 窗体设计器修改窗体,属性必须遵守 WinForm 的格式。因此,您可能需要在 PropRules.json 中添加一些属性,以便自动转换它们。

这就是 ShowInTaskBar 在规则中显示为 ShowInTaskbar 的原因(注意小写的 b)。

 

VFP2WinForms.json 规则解决了以下问题

父对象访问

Windows 窗体中已经定义了父属性,并将其强类型化为 System.Windows.Forms.Control 对象。为了避免麻烦并简化应用程序的移植,支持库中包含了一个名为 _Parent 的属性,它可以访问控件的父对象,但却是一个弱类型对象。

这将迫使 X# 进行后期绑定调用,并有助于解决移植代码的访问问题。

对 _Parent 的调用由 XPorter 自动生成。

在您的代码中调用一个对象的事件

在父对象中,您有时可能会在 VFP 代码中直接调用事件处理程序。

这可能会有问题,例如直接调用按钮的 Click 事件就会失败。

This.Parent.cmd_prec.Click

导出时,“This” 将转为父对象 ThisObject。

数组访问

在 X# 中,使用括号 [] 访问数组元素。

在 VFP 中,您可以使用括号 () 。

但在访问 .Net 类型数组时,这可能会造成问题。

因此,为了简化 VFP 应用程序的移植,在 XSharp.VFP.UI 控制层中,一些数组访问被转为方法调用,从而简化了使用 VFP 语法访问 .NET 控件的过程。

x = __screen.FormCount
__screen.Forms(x-1).Release() // 在这里,表单数组将被表单方法调用所取代。

访问当前工作区/Cursor中的字段

在 VFP 中,可以使用当前工作区/Cursor 的名称来引用当前工作区/光标,也可以通过在 Dot(.) 后指定字段名称来指向特定字段,例如使用 .VFP:

? movie.title

遗憾的是,在 X# 中,Dot(.) 用于对象,因此您必须使用箭头作为选择器,如

? movie->title

未声明变量

您可以在代码的任何地方使用未声明的变量。X# 会识别并支持这一点。

在这种情况下,X# 会默默地创建一个变量:一个未类型化的局部变量。

但在某些情况下,这样做是行不通的。例如

IF SQLExec(nHandle,"SELECT *  FROM employees ORDER BY id ASC  LIMIT 1","CurResult") <=0 THEN &&& validate error first.
  Aerror(laErr)
  Messagebox("Check the following error: " + Chr(13) + laErr[2],'Alert',3000)
  RETURN .F.
ENDIF

在代码中,变量 laErr 从未在这一级声明,但它被 AError() 函数用作以引用方式传递的参数。

X# 不支持这种结构。您必须先创建一个局部变量 laErr。

 

不支持的函数

在创建 VFP 应用程序时,您可能会调用一些 X# 尚不支持的函数。

编译器会发出警告 (XS0618),但生成的 Exe 肯定会在运行时崩溃。

为了避免这种情况,可以将这些警告显示为错误。

为此,请按照以下步骤使用 MS Visual Studio:

打开项目属性

转到 “生成”(Build)

在 “将警告视为错误(Treat Warning as Errors)”部分,输入特定警告(Specific warnings:):XS0618

XSharp.VFP.UI.Dll:适配层

VFP GUI 控件库与 .NET Windows Forms.UI.Dll 有很大不同: 属性、方法和事件处理都非常不同。

为了提供图形用户界面导出,VFPXPorter 使用了一个适配层:XSharp.VFP.GUI。

该库包含一些与 VFP 行为方式类似的控件。它公开了 VFP 的原始属性,并将其转换为 .NET Windows Forms 对应的属性。

 

某些控件可能会丢失,某些属性/方法/事件也是如此: 请在 XSharp 论坛上报告您的问题。