剑三丐帮秘籍获取:Visual Foxpro表格的使用方法与技巧
来源:百度文库 编辑:中财网 时间:2024/04/28 16:53:10
一、 概述
网格(Grid),是Visual Foxpro 3.0下一个功能极为强大的容器控件。从外观上看,它非常类似于我们熟悉的Browse窗口,但实际上它提供了比Browse窗口更为丰富的控制方式。如作为一个容器,它的每一列均可容纳不同的控件,这样就提供了比Browse更方便的输入方式;又如它能设置列对象的动态字体和颜色,这样就使得每一行、每一列甚至每一单元格都可定制自己的显示风格,从而提供了比Browse更丰富的显示效果。笔者在对网格控件的使用过程中觉得,如果恰当地运用网格的属性以及网格控件提供的事件与方法,可以完成一些看起来非常难以实现的编辑功能。下面从一个具体例子出发,讨论VFP下网格的使用方法与技巧。 二、输入焦点的自动转移
为叙述方便起见,首先利用VFP的项目管理器建立一个测试项目,然后以该项目为原型分析本文中关于网格使用技巧方面的例子。我们将项目命名为Test,然后在该项目下新建一个数据库,也命名为Test,再在数据库Test建立一个表Test1,该表有两个字段,1)Name:字符型,宽度为10; 2)Value:数值型,宽度为10,小数位数为1。
下面先建立Test1表的输入表单Test11,并在表单的"数据环境"中将表Test1添加进去。然后在表单上放置一网格,并将网格的数据源(RecordSource属性)设为Test1,同时设置网格为两列,分别绑定Test1表的Name和Value字段。这样我们就可以开始讨论具体问题及其解决方案了。
1. 问题的提出
假定Test1表的Name字段的内容为在一般情况下固定不变的一些数据(这种情况还是比较常见的,如Name字段表示项目指标,Value字段表示对应该指标的数值,Name字段的数据一旦一次输入后,一般情况下是不用改变的),而需要改变的是对应Name的Value值,为使在网格输入时Name字段的值不被用户修改,可将网格的第一列Column1的Enabled属性设为.F.,但这样做以后,问题就出现了。
我们希望用户在Value字段列中的某一行输完数据(即到达字符最大宽度或输入一位小数)后,或输入数据并按下回车键或TAB键后,焦点能自动转到下一行,以便输入下一个数据。而事实上很遗憾,焦点根本不动,仍停留在原输入数据上,用户必须按下箭头键才能输入下一行数据。显然,出现该问题的原因与Column1的Enabled属性为.F.有关,但即使Enabled=.T.(这时需要设定Column1的ReadOnly属性为.T.),焦点也将移到同一行的第一列,而不会移到下一行的同一列。事实上,在Foxpro的Browse窗口中,也存在同样的问题。
2. 解决方法
解决此问题的关键在于利用网格提供的BeforeRow ColChange或AfterRowColChange事件。 其中BeforeRow ColChange事件当用户更改活动的行或列,而新单元还未获得焦点时发生,也可以在表格列中当前对象和数据库中任何规则的 Valid 事件之前发生;AfterRowColChange事件当用户移到表格的另一行或列时,新单元获得焦点以及新行或列中对象的 When 事件发生后发生。而在上述问题中,用户输完数据后正好发生这两个事件,因此解决上述焦点移动问题的关键就在于编写其事件代码,当然选用BeforeRowColChange事件或AfterRowColChange事件均可,在本例中我们采用了BeforeRowColChange事件。
在BeforeRowColChange事件代码中,首先判断目前活动列是否为第二列,如果是而且输入或修改了数据,就使用Keyboard命令模拟按下箭头键,这样焦点就自动转到了下一行。下面是BeforeRowColChange事件代码:
LPARAMETERS nColIndex
IF This.ActiveColumn =2
IF ThisForm.ModifyData.and.!MDown()
ThisForm.ModifyData=.F.
KEYBOARD '{dnarrow}'
ENDIF
ENDIF
这里ModifyData变量是在Form中新增的属性,如果ModifyData属性为.T.,表明输入或修改了数据,为.F.则相反。可以看出,通过上述代码,我们实现了希望达到的效果,但仍存在一些问题,下面进一步讨论。 3. 问题讨论
(1) ModifyData属性的设置
怎样设置ModifyData属性呢?我们只要在网格Column2列Text1对象(即输入Value字段值的文本框)的InteractiveChange事件中编写如下代码即可:
ThisForm.ModifyData=.T.
(2) 使用箭头键的问题
从表面上看,似乎实现了上述代码后,就解决了我们提到的问题,事实上也确实解决了,但却带来了新的问题。在测试中,我们发现,当输入了数据但不按回车或TAB键,而是按上箭头键(UpArrow)时,焦点不动,按下箭头键(DownArrow)时,焦点向下移动了两行。原因很简单,正是"KEYBOARD '{dnarrow}'"命令带来的问题,在这两种情况下,是不应该再按DownArrow键的。要解决此问题,可以在Column2列Text1对象的KeyPress事件中编写如下代码:
LPARAMETERS nKeyCode, nShiftAltCtrl
IF nKeyCode=24 OR nKeyCode=5 && Down Arrow Or Up Arrow
thisform.ModifyData=.F.
ENDIF
这里判断如果在数据输入时按了箭头键,则置ModifyData属性为.F.,从而在BeforeRowColChange事件中不再按DownArrow键,也就解决了上述问题。
(3) 鼠标移动焦点的问题
同使用箭头键的问题一样,如果输入了数据但不按回车或TAB键,而是用鼠标将焦点转到另一行的话,这时焦点会自动多移一行,从而使输入很不方便。解决此问题的第一个想法是仿上述方法编写Column2列Text1对象的MouseDown事件代码,经过实验发现这种方法是不行的,因为文本框的MouseDown事件是在网格BeforeRowColChange事件后发生的。但编写网格的MouseDown事件代码是否可行呢?同样不行,因为此时根本不发生此事件(焦点在文本框上,容器内的控制响应了此事件而容器本身则不会获得此事件)。经过反复的分析和实验,我们发现,解决此问题的方法却异乎寻常的简单,正如我们在前面网格BeforeRowColChange事件代码中所写的一样,使用了MDOWN()函数。如果调用 MDOWN( )时有鼠标键按下,则该函数返回"真"(.T.)。调用 MDOWN( )时若没有鼠标键按下,则返回"假"(.F.)。由于用户用鼠标改变输入焦点时正好鼠标键按下,所以MDOWN函数返回.T.,这时将不执行"KEYBOARD '{dnarrow}'"命令,从而不会出现焦点自动多移一行的问题。
解决了上述三个问题后,可以说比较完满地达到了我们的要求。但解决该问题,还有其他一些方案,这些方案是否可行,存在什么问题,我们在下面进一步加以讨论。
4. 其他问题讨论
(1) 使用ActivateCell方法
从原理上讲,不用Keyboard命令,而是用网格的ActivateCell方法也能达到同样的效果。ActivateCell方法用于激活表格控制中的一个单元。在上述网格的BeforeRowColChange事件代码中,将"KEYBOARD '{dnarrow}'"改为如下代码:
=This.ActivateCell(This.ActiveRow+1,This. ActiveColumn)
也能实现同样的功能,而且更为灵活。我们发现,这样做后,确实能够实现与KEYBOARD命令同样的效果。但存在一个令人费解的问题,即在网格没有进行垂直卷滚时,没有任何问题;而在网格垂直卷滚后,这时第一行不再可见,则输完后焦点不动,无法移到下一行。由于VFP联机文档中没有关于这方面的详细叙述,解决此问题也颇费周折,最后我们发现,应该使用网格的RelativeRow属性代替ActiveRow属性,即将上述代码改为如下代码: =This.ActivateCell(This.RelativeRow+1,This. ActiveColumn)即可。 RelativeRow属性指出表格控制可见部分中的活动行,如果在表格中滚动,使第一行不再可见,而活动行是表格中第一个可见行,这时RelativeRow 就为1。现在的问题正是滚动时出现的,用RelativeRow正好解决。这也说明,使用 ActivateCell方法激活的是相对的行或列。
(2) 使用文本框的LostFocus事件
与使用网格的BeforeRowColChange事件相比,还有一种更为简单的方法,即使用文本框的LostFocus事件。去掉网格的BeforeRowColChange事件代码,然后在文本框的LostFocus事件里编写如下代码:
LPARAMETERS nColIndex
IF ThisForm.ModifyData.and.!MDown()
ThisForm.ModifyData=.F.
KEYBOARD '{dnarrow}'
ENDIF
也能达到同样的效果,而代码更为简洁。
(3) 关于TAB键与回车键
在上述例子中,仅当用户修改了数据才自动移动焦点,但有时也需要在按了TAB键或回车键后就开始移动焦点,而不用等到对数据进行输入或修改。这时可在文本框的KeyPress事件中加入如下代码:
IF nKeyCode=9 OR nKeyCode=13 && Tab Or Enter Key
ThisForm.ModifyData=.T.
ENDIF
当然KeyPress的其他代码仍然是必要的。这时ModifyData属性已失去了其本身的含义,只是作为一个允许焦点转换的标志而已。
另外,如果不考虑数据输完后(即到达字符最大宽度或输入一位小数)即进行焦点转移,而只是在按了TAB键或回车键才移动焦点,代码就变得更简单了,这时只需要编写文本框的KeyPress事件代码即可,其他代码可全部省略。
IF nKeyCode=9 OR nKeyCode=13 && Tab Or Enter Key
KEYBOARD '{dnarrow}'
ENDIF
三、 网格的自动拆分 在上面实现焦点自动转移的例子中,主要使用的网格事件为BeforeRowColChange(或AfterRowColChange),另外还提到网格的ActiveRow,ActiveColumn,RelativeRow,RelativeColumn等属性,这些都是网格编程中常用的事件与属性,在下面的例子中,我们将看到,这些属性和事件将会得到进一步的应用。
在本例中,我们仍然利用上面提到Test项目,并在数据库Test再建立一个新表Test2,该表有六个字段,1)Name:字符型,宽度为10;2)Value1:数值型,宽度为10,小数位数为1;3)Value2:数值型,宽度为10,小数位数为1;4)Value3:数值型,宽度为10,小数位数为1;5)Value4:数值型,宽度为10,小数位数为1;6)Value5:数值型,宽度为10,小数位数为1。
同上例一样我们先建立一个上述Test2表的输入表单Test2,并在表单的"数据环境"中将表Test2添加进去。然后在表单上放置一网格,并将网格的数据源(RecordSource属性)设为Test2,同时设置网格为六列,分别绑定Test2表的各个字段。这样我们就可以开始讨论具体问题及其解决方案了。
1. 问题的提出
我们知道,Foxpro的Browse命令有一个参数,即lock。使用lock参数可指定不需滚动就能在浏览窗口左分区中看见字段数,这样在进行数据浏览时,如果使用browse lock 1命令就可以保证当发生水平滚动而使第一列不可见时,仍能在浏览窗口的左分区中看到第一列的内容。事实上,在很多情况下,第一列往往是整条记录的标识或提示信息,用户在通过网格输入带有很多字段的数据时,总希望即使发生水平滚动后也能看到第一列的提示,这时lock提供的方式就非常有用。
我们也希望能在网格中实现这一点,事实上由于网格提供面板属性(Panel),因此实现该功能是非常容易的,只要在表单设计时就将网格分为两个面板即可。但这里我们想提出一个更难一些的问题,即希望当网格的右面板的第一列可见时,左面板消失,因为这时并不需要显示两个第一列;而当网格的右面板的第一列不可见时,左面板出现并显示第一列的内容。也就是说,实现网格两个面板的自动拆分。
2. 解决方法
解决此问题的关键仍然在于利用网格提供的BeforeRowColChange或AfterRowColChange事件。下面是网格的AfterRowColChange事件代码:
LPARAMETERS nColIndex
IF This.RelativeColumn#This.ActiveColumn
This.Partition=100
ELSE
This.Partition=0
ENDIF
我们对上述代码的有关问题做一简单分析。
(1)Partition属性
网格的Partition属性指定一个表格是否拆分为两个面板,并且指定相对于表格左边的拆分位置。 当设置Partition属性值为零时,表示不拆分表格;为非零时表示拆分位置的值(实际上就是左面板的宽度)。在上述代码中,当网格的RelativeColumn属性不等于ActiveColumn属性时,表示网格进行了水平滚动使第一列不再可见,从而需要进行窗口拆分;否则就不进行拆分。
(2)使用BeforeRowColChange还是使用AfterRowColChange事件?
本例与上例不一样,使用BeforeRowColChange和AfterRowColChange事件的效果是不同的。因为进行拆分必须当列变化以后再加以判断,因此应该使用AfterRowColChange事件。如果使用BeforeRowColChange事件,也能进行拆分,但总是漏掉一列,即当网格的第一列第一次不可见时,不能进行拆分,按右箭头键再向后移动就可以了。
3. 问题讨论
实现了AfterRowColChange事件代码后,当移动箭头键时可以进行网格拆分,但仍存在一个问题,即当用鼠标拖动水平卷滚条时网格仍不能进行拆分。解决此问题的关键在于网格的Scrolled事件,此事件当单击水平或垂直滚动条,或移动滚动条中的滚动块时发生。下面是该事件的代码:
LPARAMETERS nDirection
IF nDirection>=4
IF This.RelativeColumn#This.ActiveColumn
This.Partition=100
ELSE
This.Partition=0
ENDIF
ENDIF
这里nDirection>=4表示进行的卷滚是水平方向的(详细情况可见VFP的帮助),下面几行代码所做的工作与AfterRowColChange事件代码一样。实现了上述代码后,网格在用鼠标拖动水平卷滚条或单击滚动块时均可以自动拆分。
网格(Grid),是Visual Foxpro 3.0下一个功能极为强大的容器控件。从外观上看,它非常类似于我们熟悉的Browse窗口,但实际上它提供了比Browse窗口更为丰富的控制方式。如作为一个容器,它的每一列均可容纳不同的控件,这样就提供了比Browse更方便的输入方式;又如它能设置列对象的动态字体和颜色,这样就使得每一行、每一列甚至每一单元格都可定制自己的显示风格,从而提供了比Browse更丰富的显示效果。笔者在对网格控件的使用过程中觉得,如果恰当地运用网格的属性以及网格控件提供的事件与方法,可以完成一些看起来非常难以实现的编辑功能。下面从一个具体例子出发,讨论VFP下网格的使用方法与技巧。 二、输入焦点的自动转移
为叙述方便起见,首先利用VFP的项目管理器建立一个测试项目,然后以该项目为原型分析本文中关于网格使用技巧方面的例子。我们将项目命名为Test,然后在该项目下新建一个数据库,也命名为Test,再在数据库Test建立一个表Test1,该表有两个字段,1)Name:字符型,宽度为10; 2)Value:数值型,宽度为10,小数位数为1。
下面先建立Test1表的输入表单Test11,并在表单的"数据环境"中将表Test1添加进去。然后在表单上放置一网格,并将网格的数据源(RecordSource属性)设为Test1,同时设置网格为两列,分别绑定Test1表的Name和Value字段。这样我们就可以开始讨论具体问题及其解决方案了。
1. 问题的提出
假定Test1表的Name字段的内容为在一般情况下固定不变的一些数据(这种情况还是比较常见的,如Name字段表示项目指标,Value字段表示对应该指标的数值,Name字段的数据一旦一次输入后,一般情况下是不用改变的),而需要改变的是对应Name的Value值,为使在网格输入时Name字段的值不被用户修改,可将网格的第一列Column1的Enabled属性设为.F.,但这样做以后,问题就出现了。
我们希望用户在Value字段列中的某一行输完数据(即到达字符最大宽度或输入一位小数)后,或输入数据并按下回车键或TAB键后,焦点能自动转到下一行,以便输入下一个数据。而事实上很遗憾,焦点根本不动,仍停留在原输入数据上,用户必须按下箭头键才能输入下一行数据。显然,出现该问题的原因与Column1的Enabled属性为.F.有关,但即使Enabled=.T.(这时需要设定Column1的ReadOnly属性为.T.),焦点也将移到同一行的第一列,而不会移到下一行的同一列。事实上,在Foxpro的Browse窗口中,也存在同样的问题。
2. 解决方法
解决此问题的关键在于利用网格提供的BeforeRow ColChange或AfterRowColChange事件。 其中BeforeRow ColChange事件当用户更改活动的行或列,而新单元还未获得焦点时发生,也可以在表格列中当前对象和数据库中任何规则的 Valid 事件之前发生;AfterRowColChange事件当用户移到表格的另一行或列时,新单元获得焦点以及新行或列中对象的 When 事件发生后发生。而在上述问题中,用户输完数据后正好发生这两个事件,因此解决上述焦点移动问题的关键就在于编写其事件代码,当然选用BeforeRowColChange事件或AfterRowColChange事件均可,在本例中我们采用了BeforeRowColChange事件。
在BeforeRowColChange事件代码中,首先判断目前活动列是否为第二列,如果是而且输入或修改了数据,就使用Keyboard命令模拟按下箭头键,这样焦点就自动转到了下一行。下面是BeforeRowColChange事件代码:
LPARAMETERS nColIndex
IF This.ActiveColumn =2
IF ThisForm.ModifyData.and.!MDown()
ThisForm.ModifyData=.F.
KEYBOARD '{dnarrow}'
ENDIF
ENDIF
这里ModifyData变量是在Form中新增的属性,如果ModifyData属性为.T.,表明输入或修改了数据,为.F.则相反。可以看出,通过上述代码,我们实现了希望达到的效果,但仍存在一些问题,下面进一步讨论。 3. 问题讨论
(1) ModifyData属性的设置
怎样设置ModifyData属性呢?我们只要在网格Column2列Text1对象(即输入Value字段值的文本框)的InteractiveChange事件中编写如下代码即可:
ThisForm.ModifyData=.T.
(2) 使用箭头键的问题
从表面上看,似乎实现了上述代码后,就解决了我们提到的问题,事实上也确实解决了,但却带来了新的问题。在测试中,我们发现,当输入了数据但不按回车或TAB键,而是按上箭头键(UpArrow)时,焦点不动,按下箭头键(DownArrow)时,焦点向下移动了两行。原因很简单,正是"KEYBOARD '{dnarrow}'"命令带来的问题,在这两种情况下,是不应该再按DownArrow键的。要解决此问题,可以在Column2列Text1对象的KeyPress事件中编写如下代码:
LPARAMETERS nKeyCode, nShiftAltCtrl
IF nKeyCode=24 OR nKeyCode=5 && Down Arrow Or Up Arrow
thisform.ModifyData=.F.
ENDIF
这里判断如果在数据输入时按了箭头键,则置ModifyData属性为.F.,从而在BeforeRowColChange事件中不再按DownArrow键,也就解决了上述问题。
(3) 鼠标移动焦点的问题
同使用箭头键的问题一样,如果输入了数据但不按回车或TAB键,而是用鼠标将焦点转到另一行的话,这时焦点会自动多移一行,从而使输入很不方便。解决此问题的第一个想法是仿上述方法编写Column2列Text1对象的MouseDown事件代码,经过实验发现这种方法是不行的,因为文本框的MouseDown事件是在网格BeforeRowColChange事件后发生的。但编写网格的MouseDown事件代码是否可行呢?同样不行,因为此时根本不发生此事件(焦点在文本框上,容器内的控制响应了此事件而容器本身则不会获得此事件)。经过反复的分析和实验,我们发现,解决此问题的方法却异乎寻常的简单,正如我们在前面网格BeforeRowColChange事件代码中所写的一样,使用了MDOWN()函数。如果调用 MDOWN( )时有鼠标键按下,则该函数返回"真"(.T.)。调用 MDOWN( )时若没有鼠标键按下,则返回"假"(.F.)。由于用户用鼠标改变输入焦点时正好鼠标键按下,所以MDOWN函数返回.T.,这时将不执行"KEYBOARD '{dnarrow}'"命令,从而不会出现焦点自动多移一行的问题。
解决了上述三个问题后,可以说比较完满地达到了我们的要求。但解决该问题,还有其他一些方案,这些方案是否可行,存在什么问题,我们在下面进一步加以讨论。
4. 其他问题讨论
(1) 使用ActivateCell方法
从原理上讲,不用Keyboard命令,而是用网格的ActivateCell方法也能达到同样的效果。ActivateCell方法用于激活表格控制中的一个单元。在上述网格的BeforeRowColChange事件代码中,将"KEYBOARD '{dnarrow}'"改为如下代码:
=This.ActivateCell(This.ActiveRow+1,This. ActiveColumn)
也能实现同样的功能,而且更为灵活。我们发现,这样做后,确实能够实现与KEYBOARD命令同样的效果。但存在一个令人费解的问题,即在网格没有进行垂直卷滚时,没有任何问题;而在网格垂直卷滚后,这时第一行不再可见,则输完后焦点不动,无法移到下一行。由于VFP联机文档中没有关于这方面的详细叙述,解决此问题也颇费周折,最后我们发现,应该使用网格的RelativeRow属性代替ActiveRow属性,即将上述代码改为如下代码: =This.ActivateCell(This.RelativeRow+1,This. ActiveColumn)即可。 RelativeRow属性指出表格控制可见部分中的活动行,如果在表格中滚动,使第一行不再可见,而活动行是表格中第一个可见行,这时RelativeRow 就为1。现在的问题正是滚动时出现的,用RelativeRow正好解决。这也说明,使用 ActivateCell方法激活的是相对的行或列。
(2) 使用文本框的LostFocus事件
与使用网格的BeforeRowColChange事件相比,还有一种更为简单的方法,即使用文本框的LostFocus事件。去掉网格的BeforeRowColChange事件代码,然后在文本框的LostFocus事件里编写如下代码:
LPARAMETERS nColIndex
IF ThisForm.ModifyData.and.!MDown()
ThisForm.ModifyData=.F.
KEYBOARD '{dnarrow}'
ENDIF
也能达到同样的效果,而代码更为简洁。
(3) 关于TAB键与回车键
在上述例子中,仅当用户修改了数据才自动移动焦点,但有时也需要在按了TAB键或回车键后就开始移动焦点,而不用等到对数据进行输入或修改。这时可在文本框的KeyPress事件中加入如下代码:
IF nKeyCode=9 OR nKeyCode=13 && Tab Or Enter Key
ThisForm.ModifyData=.T.
ENDIF
当然KeyPress的其他代码仍然是必要的。这时ModifyData属性已失去了其本身的含义,只是作为一个允许焦点转换的标志而已。
另外,如果不考虑数据输完后(即到达字符最大宽度或输入一位小数)即进行焦点转移,而只是在按了TAB键或回车键才移动焦点,代码就变得更简单了,这时只需要编写文本框的KeyPress事件代码即可,其他代码可全部省略。
IF nKeyCode=9 OR nKeyCode=13 && Tab Or Enter Key
KEYBOARD '{dnarrow}'
ENDIF
三、 网格的自动拆分 在上面实现焦点自动转移的例子中,主要使用的网格事件为BeforeRowColChange(或AfterRowColChange),另外还提到网格的ActiveRow,ActiveColumn,RelativeRow,RelativeColumn等属性,这些都是网格编程中常用的事件与属性,在下面的例子中,我们将看到,这些属性和事件将会得到进一步的应用。
在本例中,我们仍然利用上面提到Test项目,并在数据库Test再建立一个新表Test2,该表有六个字段,1)Name:字符型,宽度为10;2)Value1:数值型,宽度为10,小数位数为1;3)Value2:数值型,宽度为10,小数位数为1;4)Value3:数值型,宽度为10,小数位数为1;5)Value4:数值型,宽度为10,小数位数为1;6)Value5:数值型,宽度为10,小数位数为1。
同上例一样我们先建立一个上述Test2表的输入表单Test2,并在表单的"数据环境"中将表Test2添加进去。然后在表单上放置一网格,并将网格的数据源(RecordSource属性)设为Test2,同时设置网格为六列,分别绑定Test2表的各个字段。这样我们就可以开始讨论具体问题及其解决方案了。
1. 问题的提出
我们知道,Foxpro的Browse命令有一个参数,即lock。使用lock参数可指定不需滚动就能在浏览窗口左分区中看见字段数,这样在进行数据浏览时,如果使用browse lock 1命令就可以保证当发生水平滚动而使第一列不可见时,仍能在浏览窗口的左分区中看到第一列的内容。事实上,在很多情况下,第一列往往是整条记录的标识或提示信息,用户在通过网格输入带有很多字段的数据时,总希望即使发生水平滚动后也能看到第一列的提示,这时lock提供的方式就非常有用。
我们也希望能在网格中实现这一点,事实上由于网格提供面板属性(Panel),因此实现该功能是非常容易的,只要在表单设计时就将网格分为两个面板即可。但这里我们想提出一个更难一些的问题,即希望当网格的右面板的第一列可见时,左面板消失,因为这时并不需要显示两个第一列;而当网格的右面板的第一列不可见时,左面板出现并显示第一列的内容。也就是说,实现网格两个面板的自动拆分。
2. 解决方法
解决此问题的关键仍然在于利用网格提供的BeforeRowColChange或AfterRowColChange事件。下面是网格的AfterRowColChange事件代码:
LPARAMETERS nColIndex
IF This.RelativeColumn#This.ActiveColumn
This.Partition=100
ELSE
This.Partition=0
ENDIF
我们对上述代码的有关问题做一简单分析。
(1)Partition属性
网格的Partition属性指定一个表格是否拆分为两个面板,并且指定相对于表格左边的拆分位置。 当设置Partition属性值为零时,表示不拆分表格;为非零时表示拆分位置的值(实际上就是左面板的宽度)。在上述代码中,当网格的RelativeColumn属性不等于ActiveColumn属性时,表示网格进行了水平滚动使第一列不再可见,从而需要进行窗口拆分;否则就不进行拆分。
(2)使用BeforeRowColChange还是使用AfterRowColChange事件?
本例与上例不一样,使用BeforeRowColChange和AfterRowColChange事件的效果是不同的。因为进行拆分必须当列变化以后再加以判断,因此应该使用AfterRowColChange事件。如果使用BeforeRowColChange事件,也能进行拆分,但总是漏掉一列,即当网格的第一列第一次不可见时,不能进行拆分,按右箭头键再向后移动就可以了。
3. 问题讨论
实现了AfterRowColChange事件代码后,当移动箭头键时可以进行网格拆分,但仍存在一个问题,即当用鼠标拖动水平卷滚条时网格仍不能进行拆分。解决此问题的关键在于网格的Scrolled事件,此事件当单击水平或垂直滚动条,或移动滚动条中的滚动块时发生。下面是该事件的代码:
LPARAMETERS nDirection
IF nDirection>=4
IF This.RelativeColumn#This.ActiveColumn
This.Partition=100
ELSE
This.Partition=0
ENDIF
ENDIF
这里nDirection>=4表示进行的卷滚是水平方向的(详细情况可见VFP的帮助),下面几行代码所做的工作与AfterRowColChange事件代码一样。实现了上述代码后,网格在用鼠标拖动水平卷滚条或单击滚动块时均可以自动拆分。
Visual foxpro的问题
Visual FoxPro 的命令
求一个Microsoft Visual FoxPro的,含表单和表格的程序
visual foxpro中用"?"命令编写表格打印程序时表格的外框在键盘上怎样输入?
visual fox与visual foxpro的区别
visual foxpro 9.0与visual foxpro 6.0的区别
VISUAL FOXPRO的出学者!
visual foxpro 6.0的序列号???
visual foxpro 6.0的序列号
安装Visual Foxpro的问题
有关visual foxpro的问题
Visual Foxpro 9.0的序列号
Visual foxpro二级的参考资料
关于visual foxpro 的问题
急需Visual Foxpro 的论文!
Visual FoxPro的实际操作题
关于visual foxpro的问题!
Visual FoxPro的实际应用
visual foxpro的一个问题
关于visual foxpro的交互式
excel中的表格能导入到visual foxpro中吗
Visual FoxPro
Visual FoxPro
visual foxpro