如何使用参数编写 VFP 通用菜单
虽然 VFP有生成菜单的工具,笔者是想通过这样一个范例,去表述如何在编写应用程序时,应充分利用参数进行控制,使得应用程序具有自适应性,不因应用需求发生微小的变化而重写或修改源程序,而是要以“不变应多变”,这样会使我们面对多变的客观的需求,而不会忙于奔命。这个理念是工具软件所不具有的,我们必须对大量的应用对象进行归纳,找出某一类的应用所具有的共同属性,从而归纳出共性的特征。虽然这样做很费劲,是常规编程工作的若干倍,一旦提炼成功后,日后的编程量就会大大地减少,而且会使这些自定义的通用模块(或称通用函数)的生命周期大大延长,甚至可以终身受用。
下面所示是一个应用菜单范例:
数据导入 数据导出 编辑数据 打印数据 外部软件
导入工作表 导出工作表 编辑当月变动数据 打印当月明细数据 调用Excel
导入纯文本 导出纯文本 编辑基本资料数据 打印当月汇总数据 调用Word
导入自由表 导出自由表 新增基本资料数据 /- 调用浏览器
退出 删除基本资料数据 打印某月明细数据
打印汇总明细数据
该范例,若使用传统的编程方法,将是如下所示。
PROCEDURE Generalmenu
***************
* 传统菜单模块
***************
CLEAR
SET SYSMENU SAVE
SET SYSMENU TO
DEFINE PAD MENUPAD1 OF _MSYSMENU PROMPT '数据导入'
DEFINE PAD MENUPAD2 OF _MSYSMENU PROMPT '数据导出'
DEFINE PAD MENUPAD3 OF _MSYSMENU PROMPT '编辑数据'
DEFINE PAD MENUPAD4 OF _MSYSMENU PROMPT '打印数据'
DEFINE PAD MENUPAD5 OF _MSYSMENU PROMPT '外部软件'
ON PAD MENUPAD1 OF _MSYSMENU ACTIVATE POPUP POPMENU1
ON PAD MENUPAD2 OF _MSYSMENU ACTIVATE POPUP POPMENU2
ON PAD MENUPAD3 OF _MSYSMENU ACTIVATE POPUP POPMENU3
ON PAD MENUPAD4 OF _MSYSMENU ACTIVATE POPUP POPMENU4
ON PAD MENUPAD5 OF _MSYSMENU ACTIVATE POPUP POPMENU5
DEFINE POPUP POPMENU1 MARGIN RELATIVE
DEFINE BAR 1 OF POPMENU1 PROMPT '导入工作表'
DEFINE BAR 2 OF POPMENU1 PROMPT '导入纯文本'
DEFINE BAR 3 OF POPMENU1 PROMPT '导入自由表'
DEFINE BAR 4 OF POPMENU1 PROMPT '退出'
DEFINE POPUP POPMENU2 MARGIN RELATIVE
DEFINE BAR 1 OF POPMENU2 PROMPT '导出工作表'
DEFINE BAR 2 OF POPMENU2 PROMPT '导出纯文本'
DEFINE BAR 3 OF POPMENU2 PROMPT '导出自由表'
DEFINE POPUP POPMENU3 MARGIN RELATIVE
DEFINE BAR 1 OF POPMENU3 PROMPT '编辑当月变动数据'
DEFINE BAR 2 OF POPMENU3 PROMPT '编辑基本资料数据'
DEFINE BAR 3 OF POPMENU3 PROMPT '新增基本资料数据'
DEFINE BAR 4 OF POPMENU3 PROMPT '删除基本资料数据'
DEFINE POPUP POPMENU4 MARGIN RELATIVE
DEFINE BAR 1 OF POPMENU4 PROMPT '打印当月明细数据'
DEFINE BAR 2 OF POPMENU4 PROMPT '打印当月汇总数据'
DEFINE BAR 3 OF POPMENU4 PROMPT '/-'
DEFINE BAR 4 OF POPMENU4 PROMPT '打印某月明细数据'
DEFINE BAR 5 OF POPMENU4 PROMPT '打印汇总明细数据'
DEFINE POPUP POPMENU5 MARGIN RELATIVE
DEFINE BAR 1 OF POPMENU5 PROMPT '调用Excel'
DEFINE BAR 2 OF POPMENU5 PROMPT '调用Word'
DEFINE BAR 3 OF POPMENU5 PROMPT '调用浏览器'
ON SELECTION POPUP POPMENU1;
DO choice IN Generalmenu WITH PROMPT()
ON SELECTION POPUP POPMENU2;
DO choice IN Generalmenu WITH PROMPT()
ON SELECTION POPUP POPMENU3;
DO choice IN Generalmenu WITH PROMPT()
ON SELECTION POPUP POPMENU4;
DO choice IN Generalmenu WITH PROMPT()
ON SELECTION POPUP POPMENU5;
DO choice IN Generalmenu WITH PROMPT()
ACTIVATE MENU _MSYSMENU && 激活系统菜单
RETURN
PROCEDURE Choice
PARAMETERS Mprompt && 子菜单条
IF Mprompt='退出'
SET SYSMENU TO
SET SYSMENU TO DEFAULT && 还原 VFP 系统菜单
ELSE
IF FILE(Mprompt+".PRG") OR FILE(Mprompt+".FXP")
DO (Mprompt) && 执行菜单条模块
ELSE
MESSAGEBOX('['+Mprompt+']功能模块不存在!','系统提示')
ENDIF
ACTIVATE MENU _MSYSMENU && 激活系统菜单
ENDIF
ACTIVATE MENU _MSYSMENU && 激活系统菜单
RETURN
若使用抽象的通用理念去编写,是利用 VFP 中的数据表作为菜单(参数)的载体,用户可随时变更菜单的内容,而程序始终不变。
通用菜单数据表结构如下(暂定数据表名为:通用菜单.DBF):
字段 类型 宽度 小数
菜单栏1 字符型 20
菜单栏2 字符型 20
菜单栏3 字符型 20
菜单栏4 字符型 20
菜单栏5 字符型 20
菜单栏6 字符型 20
菜单栏7 字符型 20
菜单栏8 字符型 20
菜单栏9 字符型 20
菜单栏10 字符型 20
注:菜单栏最多为 10 栏,数据表预置 16 条空白记录,第一条为主菜单栏(PAD),第二至第十六条为对应子菜单(BAR)菜单条,用户可随应用需求填入菜单内容。
按范例要求,在数据表内填入菜单内容。
菜单栏1 菜单栏2 菜单栏3 菜单栏4 菜单栏5 菜单栏6 ....
===========================================================================================================
数据导入 数据导出 编辑数据 打印数据 外部软件
导入工作表 导出工作表 编辑当月变动数据 打印当月明细数据 调用Excel
导入纯文本 导出纯文本 编辑基本资料数据 打印当月汇总数据 调用Word
导入自由表 导出自由表 新增基本资料数据 /- 调用浏览器
退出 删除基本资料数据 打印某月明细数据
打印汇总明细数据
===========================================================================================================
该范例,若使用传统的编程方法,将是如下所示。
PROCEDURE Generalmenu
****************************************
* 通用菜单模块 最后修改时间 2011.01.08
****************************************
PARAMETERS CAIDANBIAO && 用户菜单数据表
CLEAR
SET SYSMENU TO
IF FILE(CAIDANBIAO+".DBF")
SELECT 125
USE (CAIDANBIAO)
ELSE
MESSAGEBOX("["+CAIDANBIAO+"]菜单表不存在! ",48,"系统提示")
RETURN
ENDIF
RELEASE TS,QD,POM
DIMENSION TS(10),QD(10,16),POM[10]
CAIDAN=1
**************************************************
DO WHILE .T.
CDL="菜单栏"+ALLTRIM(STR(CAIDAN))
IF EMPTY(&CDL) && 若菜单栏空
CAIDAN=CAIDAN-1 && 指针减1
EXIT && 退出循环
ELSE && 否则
TS[CAIDAN]=ALLTRIM(&CDL) && 主菜单栏
MPAD="MENUPAD"+ALLTRIM(STR(CAIDAN))
PP="POPMENU"+ALLTRIM(STR(CAIDAN))
****** 定义主菜单栏 ****************************
DEFINE PAD &MPAD OF _MSYSMENU PROMPT TS[CAIDAN]
****** 激活子菜单 ******************************
ON PAD &MPAD OF _MSYSMENU ACTIVATE POPUP &PP
****** 定义子菜单 ******************************
DEFINE POPUP &PP MARGIN RELATIVE
CAIDAN=CAIDAN+1 && 指针加1
ENDIF
ENDDO
**************************************************
FOR LIE=1 TO CAIDAN
ZCD="菜单栏"+ALLTRIM(STR(LIE))
JISUAN=1
DO WHILE .T.
GO JISUAN+1
IF EMPTY(&ZCD)
JISUAN=JISUAN-1
EXIT
ELSE
QD[LIE,JISUAN]=ALLTRIM(&ZCD)
JISUAN=JISUAN+1
ENDIF
ENDDO
POM[LIE]=JISUAN
ENDFOR
*-----------------------------------------------------------
FOR LAN=1 TO CAIDAN
PP="POPMENU"+ALLTRIM(STR(LAN))
FOR CDT=1 TO POM[LAN]
DEFINE BAR CDT OF &PP PROMPT QD[LAN,CDT] && 定义子菜单条
ENDFOR
*** 当选择子菜单条时,调用 choice 模块 ***
ON SELECTION POPUP &PP DO choice ;
IN Generalmenu WITH PROMPT()
ENDFOR
*-----------------------------------------------------------
ACTIVATE MENU _MSYSMENU && 激活系统菜单
RETURN
PROCEDURE Choice
PARAMETERS Mprompt && 子菜单条
IF Mprompt='退出'
SET SYSMENU TO
SET SYSMENU TO DEFAULT && 还原 VFP 系统菜单
ELSE
IF FILE(Mprompt+".PRG") OR FILE(Mprompt+".FXP")
DO (Mprompt) && 执行菜单条模块
ELSE
MESSAGEBOX('['+Mprompt+']功能模块不存在!','系统提示')
ENDIF
ACTIVATE MENU _MSYSMENU && 激活系统菜单
ENDIF
RETURN
用户在调用 Generalmenu 通用菜单时,只要编写几句语句即可,而对应的功能模块,则由用户自行编写。
PROCEDURE RUN_MENU
Generalmenu("通用菜单")
RETURN
其它应用模块
PROCEDURE 导入工作表
...........
RETURN
PROCEDURE 导入纯文本
...........
RETURN
PROCEDURE 导入自由表
...........
RETURN
...........
以上程序在 VFP6 和 VFP7 上通过。