| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1731 人关注过本帖
标题:VFP学习、开发漫谈 (16)
只看楼主 加入收藏
liuxingang28
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:山东济南
等 级:贵宾
威 望:47
帖 子:649
专家分:2156
注 册:2014-2-7
结帖率:96.77%
收藏
已结贴  问题点数:10 回复次数:18 
VFP学习、开发漫谈 (16)
在 VFP 的很多教科书中,都出现过“导航条”的设计,用于移动记录指针,但其功能往往不够完善和实用。下面的导航条,是我参考“Microsoft Visual FoxPro 9\Samples\Classes\Buttons.vcx”中的 Vcr 类建立的,应用于我开发的多个系统:
图片附件: 游客没有浏览图片的权限,请 登录注册

图片附件: 游客没有浏览图片的权限,请 登录注册

这是本讲座中第一个完整的实例,我已将该类打包,有需要的朋友可以下载:
Navigator.RAR (6.08 KB)

该导航条有如下特点:
1. 记录的移动及位置信息都是相对的,过滤条件(Set Filter To)和索引顺序(Set Order To)仍有效。例如:总记录数是通过Count命令获取的,不是取自 Reccount()函数。
2. 对按钮的启用和禁用作了智能判断。比如:当前记录为第一条记录时,则禁用“首记录”和“前一条”按钮;当前记录为最后一条记录时,则禁用“后一条”和“末记录”按钮。无记录时,禁用所有按钮。
3. 在导航条的中间位置添加了一个只读文本框,用于显示当前记录的位置及总记录数。这也是本导航条的最大优点。该思路受 Microsoft Access 中数据表维护界面的启发。
4. 可以由用户指定记录移动的目标位置。
5. 由用户确定是否显示记录的位置信息。在移动记录的操作中,获取当前记录的位置及总记录数需要耗费时间,当记录很多时,可能影响速度,为此设置了一个开关按钮,由用户在功能和速度之间作出权衡。
6. 支持快捷键操作。按下 Ctrl+Home 可移动到第一条记录,按下 PageUp 移动到上一条记录,按下 PageDown 移动到下一条记录,按下 Ctrl+End 移动到最后一条记录。由于上述快捷键与表格的按键冲突,因此,若在表格中按下快捷键不会执行导航条操作,仍执行表格的默认操作。

导航条类有 4 个自定义属性:
1. EnableDisableOnInit:初始化时,是否执行 EnableDisableButtons方法以设置按钮的状态和位置信息,默认值为 .t.。
2. Lock:是否屏蔽当前记录的位置信息,默认值为 .f.,即:显示位置信息。
3. Shortcut:是否支持快捷键,默认值为 .t.。
4. SkipTable:与导航条相关联的表别名。

在导航条的初始化事件中,设置导航条的初始状态及是否支持快捷键操作:
程序代码:
* Vcr.Init
* 初始化时,设置导航条状态
IF THIS.EnableDisableOnInit
    THIS.BeforeRecordPointerMoved    && 选定工作区
    GO TOP                           && 移动到首条记录
    THIS.EnableDisableButtons        && 设置导航条状态
ENDIF
THIS.chkLock.Value = THIS.Lock       && 设置锁定按钮的初始值

* 支持快捷键操作
IF THIS.ShortCut
    THISFORM.KeyPreview = .t.
    BINDEVENT(THISFORM,'KeyPress',THIS,'KeySkip')
    THIS.cmdTop.ToolTipText = '首记录 (Ctrl+Home)'
    THIS.cmdBottom.ToolTipText = '末记录 (Ctrl+End)'
    THIS.cmdPrior.ToolTipText = '前一条 (PageUp)'
    THIS.cmdNext.ToolTipText = '后一条 (PageDown)'
ENDIF

导航条还有 5 个自定义方法:
1. BeforeRecordPointerMoved:移动记录前执行的方法,其作用是选定工作区
* 选定工作区
IF !EMPTY(This.SkipTable)
    SELECT (This.SkipTable)
ENDIF

2. EnableDisableButtons:设置按钮的状态及位置信息,该方法是类的核心方法。
程序代码:
* 表为空或没有满足过滤条件的记录时
IF EOF()
    THIS.SetAll('Enabled', .f.,'CommandButton')
    IF !THIS.Lock
        THIS.txtCnt.Value = '0/0'
    ENDIF
    RETURN
ENDIF

* 记下当前记录(nRec)、首记录(nTop)、末记录(nBottom)的绝对位置
LOCAL nRec, nTop, nBottom ,nCurRec,nCnt
nRec = RECNO()
GO TOP
nTop = RECNO()
GO BOTTOM
nBottom = RECNO()

* 显示当前记录的相对位置
IF !THIS.Lock
    GO TOP
    COUNT TO nCurRec WHILE RECNO() # nRec    && 当前记录的相对位置 nCurRec
    COUNT REST TO nCnt
    nCnt = nCnt + nCurRec                    && 总记录数 nCnt
    THIS.txtCnt.Value = LTRIM(STR(nCurRec + 1)) + '/' + LTRIM(STR(nCnt))
ELSE
    THIS.txtCnt.Value = '(锁定)'
ENDIF
GO nRec

* 设置按钮的可用状态
DO CASE
CASE nRec = nTop AND nRec = nBottom
    && 仅有一条记录时,禁用全部按钮
    THIS.SetAll('Enabled', .f.,'CommandButton')
CASE nRec = nTop
    && 当前记录为首记录时,禁用“第一个”和“上一个”按钮
    THIS.cmdTop.Enabled = .f.
    THIS.cmdPrior.Enabled = .f.
    THIS.cmdNext.Enabled = .t.
    THIS.cmdBottom.Enabled = .t.
    THIS.cmdGo.Enabled = .t.
CASE nRec = nBottom
    && 当前记录为最后一条记录时,禁用“下一个”和“最后一个”按钮
    THIS.cmdTop.Enabled = .t.
    THIS.cmdPrior.Enabled = .t.
    THIS.cmdNext.Enabled = .f.
    THIS.cmdBottom.Enabled = .f.
    THIS.cmdGo.Enabled = .t.
OTHERWISE
    && 当前记录为中间记录时,所有按钮可用
    THIS.SetAll('Enabled', .t.,'CommandButton')
ENDCASE

3. KeySkip:用键盘操作导航条
程序代码:
* 用键盘操作导航条
LPARAMETERS nKeyCode, nShiftAltCtrl
IF THIS.Enabled
    DO CASE
    CASE TYPE('_Screen.ActiveForm.ActiveControl') = 'O' ;
        AND _Screen.ActiveForm.ActiveControl.BaseClass = 'Grid'
        * 不处理表格中的按键
    CASE nKeyCode = 18 AND THIS.cmdPrior.Enabled
        * 按下 PgUp 键,移动到上一条记录
        THIS.cmdPrior.Click
    CASE nKeyCode = 3 and THIS.cmdNext.Enabled
        * 按下 PgDn 键,移动到下一条记录
        THIS.cmdNext.Click
    CASE nKeyCode = 29 and THIS.cmdTop.Enabled
        * 按下 Ctrl+Home 键,移动到第一条记录
        THIS.cmdTop.Click
    CASE nKeyCode = 23 and THIS.cmdBottom.Enabled
        * 按下 Ctrl+End 键,移动到最后一条记录
        THIS.cmdBottom.Click
    ENDCASE
ENDIF

4. RecordPointerMoved:移动记录指针后执行的方法,该方法十分简单,只有一条语句:THISFORM.Refresh
5. VcrRefresh:刷新导航条。当新增或删除记录后,只需执行导航条的 VcrRefresh 方法即可:
程序代码:
* 刷新导航条
LOCAL nSelect
nSelect = SELECT()               && 保存环境
THIS.BeforeRecordPointerMoved    && 选定工作区
THIS.EnableDisableButtons        && 设置导航条状态
THIS.RecordPointerMoved          && 刷新表单
SELECT (nSelect)                 && 恢复环境

四个记录移动按钮的代码大同小异,下面仅列出 cmdNext 的代码:
程序代码:
* 移动到下一条记录
WITH THIS.Parent
    .BeforeRecordPointerMoved    && 选定工作区
    SKIP                         && 移动记录指针
    IF EOF()
        GO BOTTOM
    ENDIF
    .EnableDisableButtons        && 设置导航条状态
    .RecordPointerMoved          && 刷新表单
ENDWITH

cmdGo 按钮的作用是移动到用户指定的记录,代码如下:
程序代码:
* 移动到指定记录
LOCAL cValue,i,nCurRec,nCnt,nRec,cInput
WITH THIS.Parent
    * 获取当前位置和总记录数
    cValue = .txtCnt.Value                && 包含当前位置和总记录的字符串,如:1/100
    i = AT('/',cValue)
    IF i > 0
        nCurRec = VAL(LEFT(cValue,i-1))   && 当前位置
        nCnt = VAL(SUBSTR(cValue,i+1))    && 总记录数
    ELSE
        * 不显示记录位置时,获取当前位置和总记录数
        .BeforeRecordPointerMoved         && 选定工作区
        nRec = RECNO()
        GO TOP
        COUNT TO nCurRec WHILE RECNO() # nRec    && 当前记录的相对位置 nCurRec
        COUNT REST TO nCnt
        nCnt = nCnt + nCurRec                    && 总记录数 nCnt
        nCurRec = nCurRec + 1                    && 当前位置 nCurRec
        GO nRec
    ENDIF
    * 由用户指定位置
    cInput = INPUTBOX('要移动到哪条记录(1-' + TRAN(nCnt)+')?','定位记录')
    DO CASE
    CASE EMPTY(cInput)
        * 取消
    CASE BETWEEN(VAL(cInput),1,nCnt)
        * 有效位置
        .BeforeRecordPointerMoved    && 选定工作区
        SKIP VAL(cInput) - nCurRec   && 移动记录指针
        .EnableDisableButtons        && 设置导航条状态
        .RecordPointerMoved          && 刷新表单
    OTHERWISE
        * 无效位置
        MESSAGEBOX('指定的位置超出了范围(1-' + TRAN(nCnt)+')!',64,'提示')
    ENDCASE
ENDWITH

chkLock 复选框的作用是:是否显示记录的位置信息,其 Style 属性设为“1-Graphical”,代码如下:
程序代码:
* 显示/隐藏记录位置信息
WITH THIS.Parent
    .Lock = THIS.Value           && 保存锁定状态,在设置导航条状态时是通过 .Lock 来判断的
    IF THIS.Value                && 不显示记录位置
        .txtCnt.Value = '(锁定)'
    ELSE                         && 重新显示记录位置
        .BeforeRecordPointerMoved
        .EnableDisableButtons
    ENDIF
ENDWITH

在使用时,将该类添加到表单,并设置一下其 SkipTable 属性即可。


[ 本帖最后由 liuxingang28 于 2014-4-10 07:58 编辑 ]
收到的鲜花
  • tlliqi2014-04-09 17:48 送鲜花  50朵   附言:辛苦费
搜索更多相关主题的帖子: Microsoft 教科书 朋友 开发 记录 
2014-04-09 16:41
tlliqi
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:204
帖 子:15453
专家分:65956
注 册:2006-4-27
收藏
得分:3 
学习下
2014-04-09 17:48
hu9jj
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:红土地
等 级:贵宾
威 望:400
帖 子:11785
专家分:43421
注 册:2006-5-13
收藏
得分:3 
很实用的一项功能

活到老,学到老!http://www.(该域名已经被ISP盗卖了)E-mail:hu-jj@
2014-04-09 21:12
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9809
专家分:26987
注 册:2012-2-5
收藏
得分:3 
学习了

坚守VFP最后的阵地
2014-04-10 09:53
flash7914
Rank: 2
等 级:论坛游民
帖 子:40
专家分:14
注 册:2013-4-7
收藏
得分:3 
继续关注并学习。感谢大神的奉献精神
2014-04-10 12:53
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9809
专家分:26987
注 册:2012-2-5
收藏
得分:0 
楼主,1楼的截图用的是什么软件

坚守VFP最后的阵地
2014-04-11 17:34
liuxingang28
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:山东济南
等 级:贵宾
威 望:47
帖 子:649
专家分:2156
注 册:2014-2-7
收藏
得分:0 
以下是引用sdta在2014-4-11 17:34:21的发言:

楼主,1楼的截图用的是什么软件

Snagit 10

泉城飞狐
2014-04-12 08:24
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9809
专家分:26987
注 册:2012-2-5
收藏
得分:0 
谢谢楼主

坚守VFP最后的阵地
2014-04-12 09:12
qczx3358
Rank: 2
等 级:论坛游民
帖 子:44
专家分:15
注 册:2014-1-19
收藏
得分:0 
谢谢楼主,很有奉献精神。真的不错。
2014-04-24 21:13
zzpp1978
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2007-2-9
收藏
得分:0 
感谢大神的奉献精神
2014-05-04 10:34
快速回复:VFP学习、开发漫谈 (16)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.026087 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved