四、进一步完善
该表单虽已可顺利运行,但却存在着如下两个主要不足之处:
1.输入焦点不能自动下移,即在第一行最后一个字段上打回车键,焦点不能自动转到下一行的第一个字段上,而是回到第一行的第一个字段上。
2.信息提示列(最左一列)无法固定,即随着输入焦点的右移,信息提示列将移出屏幕而不再可见,失去其信息提示的作用。
下面我们就来详细讨论并解决这两个难题。
(一) 输入焦点自动下移
解决此问题可用的方法较多。经过多方比较、测试,我们认为采用表单的KeyPress事件解决这个问题较为合适(当然采用Grid控件的BeforeRowColChange事件或AfterRowColChange事件也完全可以)。KeyPress事件在用户按下并释放某键时发生,由具有焦点的对象接收。表单可在下列两种情况下接收KeyPress事件:
(1)表单中不包含任何控件或所有控件都不可见或都未激活。(2)表单的KeyPreview 属性设置为.T.。
显然本例不适用情况(1),只适用情况(2)。为此,需在表单的Init事件代码中增加如下代码:
ThisForm.KeyPreview=.T.
然后在表单的KeyPress事件中写入如下代码:
至此, 输入焦点自动下移的问题基本解决。
(二) 固定信息提示列(最左一列)
一般情况下,第一列往往是整条记录的提示信息。Foxpro的Browse命令有Lock参数,可指定在浏览窗口左分区中可见字段数,这样在数据浏览时,可保证当发生水平滚动而使最左几列不可见时,仍能在浏览窗口的左分区中看到这几列的内容。这在输入带有较多字段的数据情况下非常有用。
在Grid控件中可通过设置其Panel、Partition及PanelLink属性解决这个问题。这里我们要解决更难些的问题: 当Grid控件右面板的第一列可见时,左面板第一列消失,因为这时不需要显示两个第一列;而当Grid控件右面板的第一列不可见时,左面板显示第一列的内容。也即所谓的固定信息提示列(最左一列)。
解决此问题的方法也很多,为简化编程,我们仍采用表单的Init事件及KeyPress事件(当然也可采用Grid控件的BeforeRowColChange事件或AfterRowColChange事件)。
在表单的Init事件代码中增加如下代码:
注:Partition属性指定一个表格是否拆分为两个分区,并且指定相对于表格左分区的拆分位置。当Partition设置为零时,表示不拆分表格;为非零时表示拆分位置的值(实际上就是左分区的宽度)。这里我们判断一下该Grid控件的宽度是否超过表单宽度(实际上是表单宽度乘0.95,以使Grid左右留有一定空白,以美化界面),是则Partition设置为信息提示列的宽度,以适应前面提出的固定信息提示列的要求;否则Partition设置为零(因为此时已不需要分区)。
(三)其他细节问题
经过上述一系列改进后,报表通用录入界面已基本实现,但仍存在着几个细节问题:
(1) 初始进入该界面及录完一行进入下一行时,信息提示列会出现重复显示,如附图1示,解决方法:分别在表单的Init事件及KeyPress事件代码中适当位置增加如下代码即可: KeyBoard "{TAB}{BACKTAB}" Plain
(2) 我们希望在最后一行的最后一列数据在打回车后,焦点能自动移到命令按钮上,以便我们选择进行下一步工作, 如”存盘退出”. “继续录入”. “放弃关闭”等等,实践中发现在KeyPress事件代码中适当位置增加ThisForm.CmdExit.SetFocus()不行,只能用KeyBoard "{Ctrl+Tab}" Plain实现。
(3) 不设置水平及垂直滚动条的优点显而易见,一是界面简洁美观,如附图2示, 带有水平及垂直滚动条的录入界面显得不简洁,有些拖泥带水,且右分区的左下端垂直滚动条上的那个细黑条是分区标志,拉动它可以重新调整左右分区,以致破坏业已设计好的录入界面;二是编程大大简化,如单击水平滚动条时左右分区的拆分会出现问题(当然可通过Grid控件的Scrolled事件编程解决)。但不可否认也带来上下左右翻屏的不便,主要是上下翻屏的不便(左右滚屏可通过连续按TAB键、Shift+TAB组合键实现)。上下翻屏原可通过PgUp/PgDn键解决,但此时使用PgUp/PgDn会出现信息提示列与右分区的数据列不相对应的情况,因此我们重新定义PgUp/PgDn键,在表单的Init事件代码中增加如下2行代码:
注:通过DoCmd函数、MessageBox函数实现以下功能:
按PgUp向上滚动12行,若已到首行则提示“已是第一条记录!”;按PgDn向下滚动12行,若已到末行则提示“已是最后一条记录!”。
五、结束语
至此,我们已较为圆满的实现了使用Grid控件设计通用录入界面。应该指出的是,可以进一步完善的地方仍很多:
1.信息提示列及各数据列的宽度设置。可用RowMsg.DBF及ColMsg.DBF中的相应字段长度乘上某一系数得到,也可在RowMsg.DBF及ColMsg.DBF中设置相应字段直接确定其宽度。我们采用了前法。
2.水平及垂直滚动条的设置。当数据列超过30列后,有水平滚动条就显得较为方便。遗憾的是,VFP本身未提供单独的滚动条控件(当然损失一些界面的美观简洁,使用Grid控件自身的滚动条完全可以实现),因此,我们只能使用OLE控件,如MicroSoft Forms 2.0 ScrollBar,并通过设置其相应的属性及事件编程,解决这个问题。本文限于篇幅,不再讨论。另外,不使用Grid控件而直接使用已较好解决这些问题第三方OLE控件,如TrueDBGrid、FlexGrid、MicroSoft DataGrid Control等等,也是一种解决方法,但已不属本文范围,不再讨论。
本例在Windows9x/WindowsXP、Visual Foxpro 5.0/6.0下调试通过。本例所有事件的完整代码附下。
表单的Init事件完整代码如下:
观看地址: http://www.qqread.com/foxpro/i425856060.html进入讨论组讨论。
该表单虽已可顺利运行,但却存在着如下两个主要不足之处:
1.输入焦点不能自动下移,即在第一行最后一个字段上打回车键,焦点不能自动转到下一行的第一个字段上,而是回到第一行的第一个字段上。
2.信息提示列(最左一列)无法固定,即随着输入焦点的右移,信息提示列将移出屏幕而不再可见,失去其信息提示的作用。
下面我们就来详细讨论并解决这两个难题。
(一) 输入焦点自动下移
解决此问题可用的方法较多。经过多方比较、测试,我们认为采用表单的KeyPress事件解决这个问题较为合适(当然采用Grid控件的BeforeRowColChange事件或AfterRowColChange事件也完全可以)。KeyPress事件在用户按下并释放某键时发生,由具有焦点的对象接收。表单可在下列两种情况下接收KeyPress事件:
(1)表单中不包含任何控件或所有控件都不可见或都未激活。(2)表单的KeyPreview 属性设置为.T.。
显然本例不适用情况(1),只适用情况(2)。为此,需在表单的Init事件代码中增加如下代码:
ThisForm.KeyPreview=.T.
然后在表单的KeyPress事件中写入如下代码:
| LPARAMETERS nKeyCode, nShiftAltCtrl &&这行代码由系统自动产生,不必录入 **/判断当前焦点是否在Grid控件上及按键是否是回车键或TAB键**/ With ThisForm.ActiveControl IF Upper(.Name)='GRIDDAT' And (m.nKeyCode=13 OR m.nKeyCode=9) if .ActiveColumn=Recc("ColMsg")+1 &&判断当前焦点是否在Grid控件的最后一个字段上 KeyBoard "{DnArrow}" Plain &&是则下移一行 Endif ENDIF EndWith |
至此, 输入焦点自动下移的问题基本解决。
(二) 固定信息提示列(最左一列)
一般情况下,第一列往往是整条记录的提示信息。Foxpro的Browse命令有Lock参数,可指定在浏览窗口左分区中可见字段数,这样在数据浏览时,可保证当发生水平滚动而使最左几列不可见时,仍能在浏览窗口的左分区中看到这几列的内容。这在输入带有较多字段的数据情况下非常有用。
在Grid控件中可通过设置其Panel、Partition及PanelLink属性解决这个问题。这里我们要解决更难些的问题: 当Grid控件右面板的第一列可见时,左面板第一列消失,因为这时不需要显示两个第一列;而当Grid控件右面板的第一列不可见时,左面板显示第一列的内容。也即所谓的固定信息提示列(最左一列)。
解决此问题的方法也很多,为简化编程,我们仍采用表单的Init事件及KeyPress事件(当然也可采用Grid控件的BeforeRowColChange事件或AfterRowColChange事件)。
在表单的Init事件代码中增加如下代码:
| ThisForm.GridDat.Panel=1 &&指定右分区活动 ThisForm.GridDat.PanelLink=.T. &&左右分区相关联 ThisForm.GridDat.Patition= ThisForm.GridDat.Column1.Width **/注:m.lnGridLen是该Grid控件信息提示列及各数据列的宽度之和**/ This.GridDat.Width=IIF(m.lnGridLen>This.Width*0.95,This.Width*0.95,m.lnGridLen) This.GridDat.Left=(ThisForm.Width - This.GridDat.Width)/2 &&使Grid控件居中 This.GridDat.Partition=IIF(m.lnGridLen>This.Width*0.95,This.GridDat.Column1.Width,0) |
注:Partition属性指定一个表格是否拆分为两个分区,并且指定相对于表格左分区的拆分位置。当Partition设置为零时,表示不拆分表格;为非零时表示拆分位置的值(实际上就是左分区的宽度)。这里我们判断一下该Grid控件的宽度是否超过表单宽度(实际上是表单宽度乘0.95,以使Grid左右留有一定空白,以美化界面),是则Partition设置为信息提示列的宽度,以适应前面提出的固定信息提示列的要求;否则Partition设置为零(因为此时已不需要分区)。
(三)其他细节问题
经过上述一系列改进后,报表通用录入界面已基本实现,但仍存在着几个细节问题:
(1) 初始进入该界面及录完一行进入下一行时,信息提示列会出现重复显示,如附图1示,解决方法:分别在表单的Init事件及KeyPress事件代码中适当位置增加如下代码即可: KeyBoard "{TAB}{BACKTAB}" Plain
(2) 我们希望在最后一行的最后一列数据在打回车后,焦点能自动移到命令按钮上,以便我们选择进行下一步工作, 如”存盘退出”. “继续录入”. “放弃关闭”等等,实践中发现在KeyPress事件代码中适当位置增加ThisForm.CmdExit.SetFocus()不行,只能用KeyBoard "{Ctrl+Tab}" Plain实现。
(3) 不设置水平及垂直滚动条的优点显而易见,一是界面简洁美观,如附图2示, 带有水平及垂直滚动条的录入界面显得不简洁,有些拖泥带水,且右分区的左下端垂直滚动条上的那个细黑条是分区标志,拉动它可以重新调整左右分区,以致破坏业已设计好的录入界面;二是编程大大简化,如单击水平滚动条时左右分区的拆分会出现问题(当然可通过Grid控件的Scrolled事件编程解决)。但不可否认也带来上下左右翻屏的不便,主要是上下翻屏的不便(左右滚屏可通过连续按TAB键、Shift+TAB组合键实现)。上下翻屏原可通过PgUp/PgDn键解决,但此时使用PgUp/PgDn会出现信息提示列与右分区的数据列不相对应的情况,因此我们重新定义PgUp/PgDn键,在表单的Init事件代码中增加如下2行代码:
| ON KEY LABEL PgUp IIF(Bof("Dat"),Application.DoCmd("=MessAgeBox('已是第一条记录!',; '提示信息')"),Application.DoCmd("SKIP -12")) ON KEY LABEL PgDn IIF(EoF("Dat"),Application.DoCmd("=MessAgeBox(‘已是最后一条记录!’,; ’提示信息’)"),Application.DoCmd("SKIP 12")) |
注:通过DoCmd函数、MessageBox函数实现以下功能:
按PgUp向上滚动12行,若已到首行则提示“已是第一条记录!”;按PgDn向下滚动12行,若已到末行则提示“已是最后一条记录!”。
五、结束语
至此,我们已较为圆满的实现了使用Grid控件设计通用录入界面。应该指出的是,可以进一步完善的地方仍很多:
1.信息提示列及各数据列的宽度设置。可用RowMsg.DBF及ColMsg.DBF中的相应字段长度乘上某一系数得到,也可在RowMsg.DBF及ColMsg.DBF中设置相应字段直接确定其宽度。我们采用了前法。
2.水平及垂直滚动条的设置。当数据列超过30列后,有水平滚动条就显得较为方便。遗憾的是,VFP本身未提供单独的滚动条控件(当然损失一些界面的美观简洁,使用Grid控件自身的滚动条完全可以实现),因此,我们只能使用OLE控件,如MicroSoft Forms 2.0 ScrollBar,并通过设置其相应的属性及事件编程,解决这个问题。本文限于篇幅,不再讨论。另外,不使用Grid控件而直接使用已较好解决这些问题第三方OLE控件,如TrueDBGrid、FlexGrid、MicroSoft DataGrid Control等等,也是一种解决方法,但已不属本文范围,不再讨论。
本例在Windows9x/WindowsXP、Visual Foxpro 5.0/6.0下调试通过。本例所有事件的完整代码附下。
表单的Init事件完整代码如下:
| Set Talk Off Set Safe Off CLOSE ALL ON KEY LABEL PgUp IIF(Bof("Dat"),Application.DoCmd("=MessAgeBox('已是第一条记录!','提示信息')"),Application.DoCmd("SKIP -12")) ON KEY LABEL PgDn IIF(EoF("Dat"),Application.DoCmd("=MessAgeBox(‘已是最后一条记录!’,’提示信息’)"),Application.DoCmd("SKIP 12")) With ThisForm .KeyPreview=.T. .AutoCenter=.T. .ControlBox=.F. .Width=_Screen.Width EndWith Sele 0 Use ColMsg Copy To TmpStru Field Field_Name,Field_Type,Field_Len,Field_Dec Copy To TmpColMsg For NeedIn Create Dat From TmpStru Eras TmpStru.DBF Sele 0 Use TmpColMsg Alias ColMsg Sele 0 Use RowMsg Index On AllTrim(Code) To TmpRowMsg Scan Insert Into Dat(Code) Values (RowMsg.Code) EndScan Sele Dat Go Top Set Rela To AllTrim(Code) Into RowMsg With ThisForm.GridDat .FontName="宋体" .FontSize=10 .DeleteMark=.F. .ScrollBars=0 .ColumnCount=Recc("ColMsg")+1 .RecordSourceType=2 .RecordSource="Dat" .Column1.ControlSource="Code+RowMsg.Name" .Column1.Enabled=.F. .Column1.Width=Len(Code+RowMsg.Name)*8 .Column1.BackColor=RGB(192,192,192) .Column1.Header1.Caption=" 指标代码及名称 " .Panel=1 .PanelLink=.T. lnGridLen=.Column1.Width+10 Sele ColMsg Scan lcCol=AllTrim(Str(Recn()+1,5)) With .Column&lcCol. .ControlSource="Dat."+Alltrim(Field_Name) .Header1.Caption=AllTrim(Name) .Width=Len(.Header1.Caption)*7 lnGridLen=m.lnGridLen+.Width EndWith EndScan .Width=IIF(m.lnGridLen>ThisForm.Width,ThisForm.Width*0.95,m.lnGridLen) .Left=(ThisForm.Width - .Width)/2 .Partition=IIF(m.lnGridLen>ThisForm.Width*.95,.Column1.Width,0) ThisForm.CmdExit.Left= (ThisForm.Width - ThisForm.CmdExit.Width)/2 EndWith KeyBoard "{Tab}{BackTab}" Plain 表单的KeyPress事件完整代码如下: LPARAMETERS nKeyCode, nShiftAltCtrl With ThisForm.ActiveControl IF Upper(.Name)='GRIDDAT' And (m.nKeyCode=13 OR m.nKeyCode=9) IF .ActiveColumn=Recc("ColMsg")+1 KeyBoard "{DnArrow}" Plain KeyBoard "{Tab}{BackTab}" Plain If .ActiveRow=Recc("RowMsg") KeyBoard "{Ctrl+Tab}" Plain Endif ENDIF ENDIF EndWith 命令按钮CmdExit的Click事件完整代码如下: ON KEY LABEL PgUp ON KEY LABEL PgDn Close All Eras TmpColMsg.DBF Eras TmpRowMsg.IDX ThisForm.Release |
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
相关专题
- VFP基础教程 第一章 数据库系统 (4188次浏览)
- VFP基础教程 第三章 表的创建和 (2880次浏览)
- VFP基础教程 第二章 VFP语言基础 (2460次浏览)
- VFP基础教程 第七章 表单设计 (2301次浏览)
- FOXPRO常用编程命令及常用函数 (2155次浏览)
- Visual FoxPro 6.0与大型数据库的无“数据 (2084次浏览)
- Visual FoxPro9.0构建管理系统图解 (1557次浏览)
- VFP基础教程 第四章 数据库的创 (1452次浏览)
- VFP基础教程 第六章 面向对象的 (1447次浏览)
- VFP基础教程 第五章 创建查询和 (1418次浏览)



