
前言:
在各种 AI IDE 盛行的今天,VFP 作为一个 MS 的弃子,似乎无法搭上 AI 的快车。不久前,西班牙的易文翰(Irwin)发布了 FoxPilot ,这是第一个在 VFP IDE 里使用 AI 的插件。限于国内网络环境,它无法正常使用。因此,本人开发了这个 VFP AI 插件。
本插件有偿共享,有意可通过留言或公众号私信了解详情。
安装和启动:
AI 插件使用的是 DeepSeek-V3.2-Exp,未来计划支持其他 LLM 。
使用 AI 插件前,需要首先在 DeepSeek 官网申请 API KEY:
可以将所获得的压缩包 AI.ZIP 解压至任意文件夹下,假设你将其中的文件解压至 VFP 安装目录,执行以下命令即可启动 AI 插件:
Do AI.app第一次启动时,需要提供 API KEY:

通过调整请求体参数控制 AI 的幻觉,建议在使用过程中,根据自己 对 AI 回复结果的判断进行适当调整。通常情况下,三项参数的值越小,幻觉越少:

系统提示词控制 AI 在生成代码时的质量,可以通过导入默认提示词并进行修改,使之更符合自己的代码规范并获得更高可用性的结果:

这些参数设置,可以在 AI 插件运行时随时调整并即时可用(除菜单和工具栏的显示状态)。
你可以通过菜单或者工具栏调用其提供的功能:

AI 插件同样支持快捷键:
快捷键 | 功能 |
|---|---|
CTRL+U | 聊天 |
CTRL+I | 内联聊天 |
CTRL+O | 参数设置 |
CTRL+P | 代码补全 |
CTRL+Q | 退出 |
代码补全:
顾名思义,它仅仅会依据所书写的注释和代码,将执行逻辑补充完整。下面是一个很极端的示例,仅仅给出了简单的注释和一个基本的类定义:

将光标置于 Form 这个单词之后,按 CTRL + P,即可开始进行代码补全:

但是它似乎并不是完整的代码,没关系,继续按 CTRL + P:

经过几次之后,真的得到了完整的代码(如下)。略经修改之后(仅仅将前几行代码从类定义之后调换至类定义之前,并将 Local 更换成了 Public),它是这个样子:
*!* 创建计算器实例并显示
Public loCalculator As counter
m.loCalculator = CreateObject([counter])
m.loCalculator.Show()
*!* 这是一个VFP版本的计算器
Define Class counter As Form
Width = 300
Height = 400
Caption = "计算器"
MaxButton = .F.
MinButton = .F.
Closable = .T.
AutoCenter = .T.
*-- 显示计算结果的文本框
Add Object txtDisplay As TextBox With ;
Top = 20, ;
Left = 20, ;
Width = 260, ;
Height = 30, ;
Alignment = 1, ;
FontSize = 14, ;
Value = "0"
*-- 数字按钮0-9
Add Object cmd0 As CommandButton With ;
Top = 340, ;
Left = 20, ;
Width = 50, ;
Height = 30, ;
Caption = "0", ;
FontSize = 12
Add Object cmd1 As CommandButton With ;
Top = 300, ;
Left = 20, ;
Width = 50, ;
Height = 30, ;
Caption = "1", ;
FontSize = 12
Add Object cmd2 As CommandButton With ;
Top = 300, ;
Left = 80, ;
Width = 50, ;
Height = 30, ;
Caption = "2", ;
FontSize = 12
Add Object cmd3 As CommandButton With ;
Top = 300, ;
Left = 140, ;
Width = 50, ;
Height = 30, ;
Caption = "3", ;
FontSize = 12
Add Object cmd4 As CommandButton With ;
Top = 260, ;
Left = 20, ;
Width = 50, ;
Height = 30, ;
Caption = "4", ;
FontSize = 12
Add Object cmd5 As CommandButton With ;
Top = 260, ;
Left = 80, ;
Width = 50, ;
Height = 30, ;
Caption = "5", ;
FontSize = 12
Add Object cmd6 As CommandButton With ;
Top = 260, ;
Left = 140, ;
Width = 50, ;
Height = 30, ;
Caption = "6", ;
FontSize = 12
Add Object cmd7 As CommandButton With ;
Top = 220, ;
Left = 20, ;
Width = 50, ;
Height = 30, ;
Caption = "7", ;
FontSize = 12
Add Object cmd8 As CommandButton With ;
Top = 220, ;
Left = 80, ;
Width = 50, ;
Height = 30, ;
Caption = "8", ;
FontSize = 12
Add Object cmd9 As CommandButton With ;
Top = 220, ;
Left = 140, ;
Width = 50, ;
Height = 30, ;
Caption = "9", ;
FontSize = 12
*-- 运算符按钮
Add Object cmdAdd As CommandButton With ;
Top = 220, ;
Left = 200, ;
Width = 50, ;
Height = 30, ;
Caption = "+", ;
FontSize = 12
Add Object cmdSubtract As CommandButton With ;
Top = 260, ;
Left = 200, ;
Width = 50, ;
Height = 30, ;
Caption = "-", ;
FontSize = 12
Add Object cmdMultiply As CommandButton With ;
Top = 300, ;
Left = 200, ;
Width = 50, ;
Height = 30, ;
Caption = "*", ;
FontSize = 12
Add Object cmdDivide As CommandButton With ;
Top = 340, ;
Left = 200, ;
Width = 50, ;
Height = 30, ;
Caption = "/", ;
FontSize = 12
*-- 其他功能按钮
Add Object cmdClear As CommandButton With ;
Top = 180, ;
Left = 20, ;
Width = 50, ;
Height = 30, ;
Caption = "C", ;
FontSize = 12
Add Object cmdEquals As CommandButton With ;
Top = 340, ;
Left = 80, ;
Width = 110, ;
Height = 30, ;
Caption = "=", ;
FontSize = 12
Add Object cmdDecimal As CommandButton With ;
Top = 340, ;
Left = 140, ;
Width = 50, ;
Height = 30, ;
Caption = ".", ;
FontSize = 12
*-- 存储计算状态和数值的变量
lcCurrentValue = "0"
lcOperator = ""
llNewNumber = .T.
*** <summary>
*** 初始化事件
*** </summary>
Procedure Init()
*!* 绑定按钮事件
This.BindEvents()
EndProc
*** <summary>
*** 绑定所有按钮的Click事件
*** </summary>
Procedure BindEvents()
*!* 绑定数字按钮事件
With This
.cmd0.Click = .HandleNumberClick(0)
.cmd1.Click = .HandleNumberClick(1)
.cmd2.Click = .HandleNumberClick(2)
.cmd3.Click = .HandleNumberClick(3)
.cmd4.Click = .HandleNumberClick(4)
.cmd5.Click = .HandleNumberClick(5)
.cmd6.Click = .HandleNumberClick(6)
.cmd7.Click = .HandleNumberClick(7)
.cmd8.Click = .HandleNumberClick(8)
.cmd9.Click = .HandleNumberClick(9)
*!* 绑定运算符按钮事件
.cmdAdd.Click = .HandleOperatorClick("+")
.cmdSubtract.Click = .HandleOperatorClick("-")
.cmdMultiply.Click = .HandleOperatorClick("*")
.cmdDivide.Click = .HandleOperatorClick("/")
*!* 绑定其他功能按钮事件
.cmdClear.Click = .HandleClearClick()
.cmdEquals.Click = .HandleEqualsClick()
.cmdDecimal.Click = .HandleDecimalClick()
EndWith
EndProc
*** <summary>
*** 处理数字按钮点击事件
*** </summary>
*** <param name="tnNumber">数字值</param>
Procedure HandleNumberClick(tnNumber As Integer)
If This.llNewNumber
This.txtDisplay.Value = AllTrim(Str(m.tnNumber))
This.llNewNumber = .F.
Else
This.txtDisplay.Value = This.txtDisplay.Value + AllTrim(Str(m.tnNumber))
EndIf
EndProc
*** <summary>
*** 处理运算符按钮点击事件
*** </summary>
*** <param name="tcOperator">运算符</param>
Procedure HandleOperatorClick(tcOperator As String)
This.lcCurrentValue = This.txtDisplay.Value
This.lcOperator = m.tcOperator
This.llNewNumber = .T.
EndProc
*** <summary>
*** 处理等号按钮点击事件
*** </summary>
Procedure HandleEqualsClick()
Local lnResult As Number
Do Case
Case This.lcOperator = "+"
m.lnResult = Val(This.lcCurrentValue) + Val(This.txtDisplay.Value)
Case This.lcOperator = "-"
m.lnResult = Val(This.lcCurrentValue) - Val(This.txtDisplay.Value)
Case This.lcOperator = "*"
m.lnResult = Val(This.lcCurrentValue) * Val(This.txtDisplay.Value)
Case This.lcOperator = "/"
If Val(This.txtDisplay.Value) = 0
Messagebox("除数不能为零!", 16, "错误")
Return
Else
m.lnResult = Val(This.lcCurrentValue) / Val(This.txtDisplay.Value)
EndIf
Otherwise
Return
EndCase
This.txtDisplay.Value = AllTrim(Str(m.lnResult))
This.llNewNumber = .T.
This.lcOperator = ""
EndProc
*** <summary>
*** 处理清除按钮点击事件
*** </summary>
Procedure HandleClearClick()
This.txtDisplay.Value = "0"
This.lcCurrentValue = "0"
This.lcOperator = ""
This.llNewNumber = .T.
EndProc
*** <summary>
*** 处理小数点按钮点击事件
*** </summary>
Procedure HandleDecimalClick()
If This.llNewNumber
This.txtDisplay.Value = "0."
This.llNewNumber = .F.
Else
If At(".", This.txtDisplay.Value) = 0
This.txtDisplay.Value = This.txtDisplay.Value + "."
EndIf
EndIf
EndProc
EndDefine
虽然直接运行代码会报错,但是它给出了一个类定义的完美架构,略经修改就可以直接运行:

虽有瑕疵,但结果还不错。
如果是在书写应用时,有准确的注释和执行逻辑,那么它应该可以在烦杂的细节处理上发挥作用。