4.4 设备还库模块的设计
在设备还库模块中将实现设备还库数据的添加和修改库存等功能,按照前面介绍的步骤设计设备还库表。
设备还库表所可能用到的控件的属性如表所示:
(1)Form1控件的主要属性:
select 现有库存表
*先在该表单的数据环境中添加现有库存表
getid=thisform.设备号1.text1.value
set order to 设备号
seek getid
*在现有库存表中查找设备号等于getid的纪录
if found()
getnum=thisform.归还数量1.text1.value
update 现有库存表;
set 现有库存=(现有库存-getnum) where (设备号=getid)
insert into 操作日志表(操作员,操作内容,操作时间);
values (thisform.归还人1.text1.value,'设备还库',date())
*如果库存表中有该项设备,则更新库存表,同时更新操作日志
else
messagebox("出错",1,"错误的设备号")
*如果没有该设备号则报告出错信息
endif
保存后运行表单,可得到如图所示的设备还库表。
4.5 设备需求模块的设计
在设备需求模块中将实现设备需求数据的添加和保存日志等功能。首先通过Visual Foxpro的表单向导生成所需的设备需求表单,选择部门需求表的所有可用字段,然后为保持程序风格的一致,继续采用表单的阴影式和图片按钮的风格。在“步骤3-排序次序”时。选择设备号的升序排列。最后单击“完成”按钮,把表单保存在“c:仓库管理”目录下,名为“设备需求.scx”。
通过表单向导生成的表单如图所示,我们可以调节控件的位置,修改表单中控件的属性,最后结果所下图所示:
在表单设计器中,双击“保存日志”命令按钮。添加click事件代码如下:
insert into 操作日志表 (操作员,操作内容,操作时间) values (username,'设备需求',date())
双击回主界面命令按钮,添加click事件代码如下:
thisform.release
do form 仓库管理
保存对表单所作的修改。
4.6 设备采购模块的设计
在设备采购模块中将实现设备采购数据的添加和保存日志等功能。
(1)由数据表生成表单
通过Visual Foxpro的表单向导,生成设备采购计划表单。在选择数据库和表时,选择仓库管理数据库和设备采购计划表。在选择字段时,选择所有可用字段,选择阴影式和图片按钮作为设备采购计划表的样式。选择计划采购时间的升序排列作为设备采购计划表的索引。
(2)为窗体修改和添加命令按钮
添加2个命令按钮“保存日志”和“回主界面”。设置表单中控件的属性。下面的表列出了需要修改的控件的名称以及属性值。
(1)Form1控件的主要属性:
(3)为按钮添加click事件代码:
在表单设计器中,双击保存日志命令按钮。添加click事件代码如下:
insert into 操作日志表 (操作员,操作内容,操作时间) values (username,"设备需求",date())
*把设备需求写入操作日志表中
双击回主界面按钮,添加click事件代码如下:
thisform.release
*释放本表单
do form 仓库管理
*运行仓库管理界面
保存对表单所作的修改,表单运行效果如图所示:
4.7 显示报表模块的设计
在该模块中,一共要显示3个报表,分别提供库存不足,库存过多和操作日志等信息。 1. 设计显示报表表单
在项目管理器的文档视图下选择“新建”,然后选择新建表单,如图所示。
在如图所示的空白表单中添加一个页框控件,并按照下表设置页框的属性,同时在数据环境里添加现有库存表和操作日志表。
操作日志表
设置表格控件的属性,如表所示:
grid1控件的主要属性表:
2. 代码设计
定义Pageframe1.Page1.grid1的init事件
运行“显示报表”表单,界面所图所示:
local Custs1
select 设备号,最大库存,现有库存 from 现有库存表 where (现有库存>最大库存) into cursor Custs1
thisform.页框.库存过多.库存过多表.recordsource="Custs1"
定义Pageframe1.Page2.grid1的init事件
local Custs2
select 设备号,最小库存,现有库存 from 现有库存表 where (现有库存<最小库存) into cursor Custs2
thisform.页框.库存不足.库存不足表.recordsource="Custs2"
定义Pageframe1.Page3.grid1的init事件
local Custs3
select * from 操作日志表 into cursor Custs3
thisform.页框.操作日志.操作日志表1.recordsource="Custs3"
运行“显示报表”表单,界面如图所示。
4.8 开发中的难点和解决技巧
Visual FoxPro6.0中的向导包括表向导、数据库向导、表单向导、查询向导、报表向导、标签向导、邮件合并向导、数据透视表向导、导入向导、文档向导、安装向导、升迁向导、应用程序向导、WEB发表向导等、我们合理应用向导可以在编程中提高效率。
为了快速开发高效的软件,本设计中的多数表单的设计采用利用表单设计向导生成,然后在生成的表单的基础上修改。
数据库软件用来管理数据的优势在于可以迅速从成千上万的数据中找到我们需要的数据,而查询功能的设计也是数据库应用软件设计过程中的重点也是难点。本设计过程中利用表单向导强大的功能,轻松完成了数据的查询功能。而且表单向导生成的查询功能非常强大,完全可以满足数据库应用软件的需要。
第五章 系统的编译和发行
5.1 设置主文件
用主图标标记的文件是用户在启动.app或者.exe时被调用的文件。它可以是一个表单、菜单或者程序,建议使用程序作为主文件。
5.2 构造主文件
如果主文件是一个程序,它将调用应用程序框架中的各个功能组件,然后由这些组件调用应用程序的其余部分。
如果要建立一个简单的主程序,可以按下列步骤进行。
(1) 现设置应用环境界面。
(2) 建立初始用户界面。
(3) 建立事件循环。
(4) 恢复环境,退出应用程序。
例如,可以建立下面的程序作为主程序:
为了避免无限循环,必须在READ EVENTS命令之前安排CLEAR EVENTS命令。可以在主菜单或者主表单中添加一个“退出”项,该项发出CLEAR EVENTS命令。
5.3 在.app和.exe文件中包含和排除文件
如果在发布的应用程序中不想再更改这些文件,可把它们放在项目中并设置为“包含”。那么这些文件变成只读的,不能修改。如果想修改这些文件,把它们放在项目中并设置为“排除”,然后作为独立文件随着应用程序一起发布。
在默认情况下,Visual FoxPro6.0在嵌放的过程中排除了数据库、表格、成为.ff的c库文件和.app文件。建议除了一些特定的表格,最好不要包含这类文件。数据库和表格需要变化和添加,而如果编译后包含自.exe或者是.app文件中,由于这二个文件被创建后都是静态的,因此被包含的文件也是静态的和只读的。把数据库和表格包含在这些文件中很明显会带来问题。
因为这些文件不能被包含在文件.exe或者是.app文件中,所以要在发布一个应用程序之前为这些文件做好准备。
如要排除可修改的文件,首先在项目管理器中,选择可修改的文件,然后从“项目”菜单中选择“排除”命令。在一个文件被排除后,则在文件的左方加入一个排除符号。
小结
一个完整的仓库管理系统到此就制作完成了。在本例中详细的讲述了从创建数据库到系统设计和各模块的创建、面向对象的表单的设计、基本功能如查询的实现、主程序的编写。
致 谢
在本次毕业设计的过程中,我的导师和学院的老师们给了我很大的指导和帮助。不仅使我在规定的时间内完成了系统的设计,同时还使我学到了很多有益的经验。在此, 我谨向他表示最衷心的感谢。
同时,学校给了我这次毕业设计的机会,使我得到了很好的锻炼,在此,我也向学校的各位老师表示最诚挚的感谢。 主要参考文献
作者. 书名. 出版社. 出版日期
1. 李加福•Visual FoxPro6.0•北京•清华大学出版社•1999年6月
2.周建成•FoxPro2.5命令与函数专辑•北京•人们邮电出版社•1994年7月
3.梁杰、效英、殷咸青•Foxpro 2.6 for windows使用详解•西安•西安电子科技大学出版社•1995年5月
附录:程序运行界面:
1:主界面:
附录2:主要控件的源代码清单:
1:主程序源代码:
SET TALK off
set sysmenu off
set cent on
_screen.windowstate=2
_screen.icon="iconshappy.ico"
_screen.maxbutton=0
_screen.minbutton=1
_screen.closable=.f.
modify window screen noclose
MODIFY WINDOW SCREEN TITLE " 仓库管理信息系统 "
ZOOM WINDOW SCREEN MAX
set default to data
do form 登录表单
read events
clear
close all
return
endif
2:登录表单的确定按钮控件的click源代码:
locate for alltrim(用户名)==alltrim(thisform.combo1.value) and alltrim(密码)==alltrim(thisform.text1.value)
if !eof()
if alltrim(级别)=="管理员"
public jb,username
jb=1
username=alltrim(thisform.combo1.value)
else
public jb,username
jb=0
username=alltrim(thisform.combo1.value)
endif
do menu.mpr
thisform.release
do form 仓库管理
else
#define missmatch_loc "用户或口令错,请重新登录!"
wait window missmatch_loc timeout 1
thisform.combo1.value=''
thisform.text1.value=''
thisform.text1.setfocus
numcount=numcount+1
if numcount=4
numcount=0
mess =messagebox("三次口令错,将退出程序!",4+16+2,"退出")
clear event
release thisform
endif
endif
3:密码修改表单的修改按钮的click事件源代码:
if empty(thisform.text4.value)
mess=messagebox("用户名不能为空!",48,"警告")
else
if empty(thisform.text1.value)
mess=messagebox("旧密码不能为空!",48,"警告")
else
if empty(thisform.text2.value)
mess=messagebox("新密码不能为空!",48,"警告")
else
if empty(thisform.text3.value)
mess=messagebox("重复密码不能为空!",48,"警告")
else
if alltrim(thisform.text2.value)<>alltrim(thisform.text3.value) or len(alltrim(thisform.text2.value))<>len(alltrim(thisform.text3.value))
mess=messagebox("二次密码不一致!",48,"警告")
else
locate for alltrim(用户名)==alltrim(thisform.text4.value) and alltrim(密码)==alltrim(thisform.text1.value)
if eof()
mess=messagebox("密码错误,系统将取消你的修改权利!",48,"警告")
thisform.release
else
repl 密码 with alltrim(thisform.text3.value)
mess=messagebox("密码修改成功!",48,"信息")
thisform.release
endif
4:添加操作员表单的最首按钮的click事件源代码:
go top
thisform.grid1.setfocus
thisform.grid1.refresh
5:添加操作员表单的上一个按钮的click事件源代码:
skip-1
if bof()
?? chr(7)
=messagebox("警告,这已经是第一条记录!",48,"信息窗口")
go top
endif
thisform.grid1.setfocus
thisform.grid1.refresh
6:添加操作员表单的下一个按钮的click事件源代码:
skip
if eof()
?? chr(7)
=messagebox("警告,这已经是最后一条记录!",48,"信息窗口")
go bottom
endif
thisform.grid1.setfocus
thisform.grid1.refresh
7:添加操作员表单的最末按钮的click事件源代码:
go bottom
thisform.grid1.setfocus
thisform.grid1.refresh
8:添加操作员表单的修改按钮的click事件源代码:
if thisform.command5.caption='修改'
thisform.text1.readonly=.f.
thisform.text2.readonly=.f.
thisform.text3.readonly=.f.
thisform.combo1.readonly=.f.
thisform.command5.caption='保存'
thisform.command1.enabled=.f.
thisform.command2.enabled=.f.
thisform.command3.enabled=.f.
thisform.command4.enabled=.f.
thisform.command6.enabled=.f.
thisform.command7.enabled=.f.
thisform.command8.enabled=.f.
else
thisform.command5.caption='修改'
thisform.text1.readonly=.t.
thisform.text2.readonly=.t.
thisform.text3.readonly=.t.
thisform.combo1.readonly=.t.
thisform.command1.enabled=.t.
thisform.command2.enabled=.t.
thisform.command3.enabled=.t.
thisform.command4.enabled=.t.
thisform.command6.enabled=.t.
thisform.command7.enabled=.t.
thisform.command8.enabled=.t.
endif
thisform.grid1.setfocus
thisform.grid1.refresh
9:添加操作员表单的添加按钮的click事件源代码:
if thisform.command6.caption='添加'
thisform.text1.readonly=.f.
thisform.text2.readonly=.f.
thisform.text3.readonly=.f.
thisform.combo1.readonly=.f.
thisform.command6.caption='保存'
thisform.command1.enabled=.f.
thisform.command2.enabled=.f.
thisform.command3.enabled=.f.
thisform.command4.enabled=.f.
thisform.command5.enabled=.f.
thisform.command7.enabled=.f.
thisform.command8.enabled=.f.
appe blan
else
thisform.command6.caption='添加'
thisform.text1.readonly=.t.
thisform.text2.readonly=.t.
thisform.text3.readonly=.t.
thisform.combo1.readonly=.t.
thisform.command1.enabled=.t.
thisform.command2.enabled=.t.
thisform.command3.enabled=.t.
thisform.command4.enabled=.t.
thisform.command5.enabled=.t.
thisform.command7.enabled=.t.
thisform.command8.enabled=.t.
endif
thisform.grid1.setfocus
thisform.grid1.refresh
10:添加操作员表单的删除按钮的click事件源代码:
cMessageTitle='系统警告'
cMessageText='确认要删除吗?'
nDialogType=4+32
nanswer=messagebox(cMessageText,nDialogType,cMessageTitle)
if nanswer=6
dele
thisform.grid1.setfocus
thisform.grid1.refresh
endif
11:类baseform的picrecord的源代码:
IF TYPE("THIS.APP_MEDIATOR.BaseClass")#"C"
RETURN
ENDIF
IF THIS.APP_MEDIATOR.PickRecordToWorkOn()
IF THIS.APP_MEDIATOR.lAdding AND !EMPTY(ALIAS())
THIS.REFRESH()
* Check if we have blank record already from txtbtns
IF GETFLDSTATE(1) #3
THIS.AddRecord()
ENDIF
ENDIF
ENDIF
12:类baseform的queryunload的源代码:
IF TYPE("THIS.APP_MEDIATOR.BaseClass")#"C"
IF !THIS.ResolveConflicts()
NODEFAULT
RETURN .F.
ENDIF
RETURN
ENDIF
IF DODEFAULT()
IF NOT THIS.App_Mediator.QueryUnload()
NODEFAULT
RETURN .F.
ENDIF
ELSE
NODEFAULT
RETURN .F.
ENDIF
13:类baseform的release的源代码:
IF !THIS.Queryunload()
NODEFAULT
RETURN .F.
ENDIF
14:类baseform的resolveconflicts的源代码:
#DEFINE PROMPTTOSAVE_LOC "Data has been changed. Would you like to save changes?"
IF !THIS.lSaveBufferedData
RETURN
ENDIF
LOCAL nDECursors, aDECursors, cDataEnvRef, lPromptSave,lHadPrompt
LOCAL lcAlias, lnFields, nPromptSave, i, loCurrentControl
* Flush current control
IF TYPE("THIS.ActiveControl.baseclass")="C" AND;
PEMSTATUS(THIS.ActiveControl,"value",5) AND;
PEMSTATUS(THIS.ActiveControl,"controlsource",5) AND;
!EMPTY(THIS.ActiveControl.controlsource)
loCurrentControl = THIS.ActiveControl
* Check if data actually changed
IF !EVAL(loCurrentControl.controlsource)= loCurrentControl.Value
loCurrentControl.Value = loCurrentControl.Value
ENDIF
loCurrentControl=""
ENDIF
nDECursors = 0
cDataEnvRef = ""
DIMENSION aDECursors[1]
DO CASE
CASE TYPE("THISFORM.DataEnvironment") = "O"
nDECursors = AMEMBERS(aDECursors,THISFORM.DataEnvironment,2)
cDataEnvRef = "THISFORM.DataEnvironment"
CASE TYPE("THISFORMSET.DataEnvironment") = "O"
nDECursors = AMEMBERS(aDECursors,THISFORMSET.DataEnvironment,2)
cDataEnvRef = "THISFORMSET.DataEnvironment"
CASE THIS.lUpdateAllBufferedTables
nDECursors=AUSED(aDECursors)
OTHERWISE
IF !EMPTY(ALIAS())
aDECursors[1]=ALIAS()
nDECursors=1
ENDIF
ENDCASE
FOR i = 1 TO m.nDECursors
IF EMPTY(m.cDataEnvRef)
lcAlias = aDECursors[m.i]
ELSE
WITH EVAL(m.cDataEnvRef + "." + aDECursors[m.i])
IF ATC("CURSOR",.BaseClass)=0 &&skip relations
LOOP
ENDIF
lcAlias = .ALIAS
ENDWITH
ENDIF
IF USED(lcAlias) AND CursorGetProp("sourcetype",lcAlias )=3 AND ;
CursorGetProp("buffering",lcAlias )>1
IF !m.lHadPrompt
IF CursorGetProp("buffering",lcAlias )>3
IF GETNEXTMODIFIED(0,lcAlias )=0
LOOP
ENDIF
ELSE
lnFields = GETFLDSTATE(-1,lcAlias)
IF REPLICATE("1",LEN(lnFields))=TRANS(lnFields)
LOOP
ENDIF
ENDIF
nPromptSave = MESSAGEBOX(PROMPTTOSAVE_LOC,35)
IF nPromptSave=2
RETURN .F.
ENDIF
lPromptSave=(nPromptSave=6)
lHadPrompt = .T.
ENDIF
IF m.lPromptSave
TableUpdate(.T.,.T.,lcAlias) && update on exit
ELSE
TableRevert(.T.,lcAlias) && update on exit
ENDIF
ENDIF
ENDFOR
15:类baseform的show的源代码:
LPARAMETERS nStyle
LOCAL lcAppRef
IF TYPE("THIS.APP_MEDIATOR.BaseClass")#"C" OR !THIS.lShowFirstTime
RETURN
ENDIF
THIS.lShowFirstTime = .F.
THIS.lSaveBufferedData = .F.
THIS.PickRecord()