我们在数据窗口中需要进行行选择操作,如用户为了修改数据或看到更详细的内容而选择了某一行;在另一些情况下,用户可能要同时删除或修改多行,这时,我们需要有使用户在一个数据窗口中同时选择多行的功能。这在powerbuilder中是相当容易做到的,但是,如果在一个数据窗口祖先中没有标准的函数来处理这些,而在每个窗口中重复编程,就非常麻烦。 我们首先来看一看进行行选择的不同方法。 ·所有行都不加亮通常情况下数据窗口不加亮任何行。这对于那些只允许用户进行滚动和查看的数据列表或那些单行的数据窗口是合适的。 ·单行选择单行选择意味着用户在同一时间只能选择一行来执行一些动作,如删除或在主从关系的列表中显示详细信息,这是非常有用的。下面是实现单行选择功能的代码: event: rowfocuschangedif getrow() > 0 then selectrow( 0, false ) selectrow( getrow(), true )end if·多行的自动选择多行的自动选择表现为:当用户点击一个未加亮的行时,该行将变亮;反之,用户点击一个加亮行,该行将不加亮。为了实现上述功能,在rowfocuschanged事件中加入如下代码: event:rowfocuschangedobject: any datawindowif getrow() > 0 then if isselected( getrow() ) then selectrow( getrow(), false ) else selectrow( getrow(), true ) end ifend if或者简化成为下面的一行代码: if getrow() > 0 then selectrow( getrow(), not isselected( getrow()))·shift、control或control+shift+鼠标的使用windows的文件管理器或其它windows程序中,您可以使用shift、control或control+shift这种键盘与鼠标的组合来选择。powerbuilder在数据窗口中没有提供这样的能力,我们必须自己实现。 我们应当实现的组合功能是: 要建立这样的功能,数据窗口必须记录当前的起始行。我们声明这样一个实例变量: protected long il_ anchor _ row当用户点击鼠标或进行了键盘操作时,我们要测试用户是否同时按下了shift或control键,方法是用keydown()函数,检查有没有keyshift!和keycontrol!,如有这样的键按下则记录起始行。 编写行选择函数 为了在用户点击鼠标或进行键盘操作时使上述行为发生作用,我们必须在clicked事件和一个映射到pbm _ dwnkey事件的自定义用户事件中调用我们自己的行选择函数。这样,不管用户是点击鼠标还是击中键盘,选择行为都会发生。我们也可以将这个功能放入rowfocuschanged事件中。 为了使这个行选择功能可重用,这里我们建立两个函数。一个函数设置我们希望的选择行为类型,另外一个真正执行该选择行为。首先我们使用一个实例变量来设定选择行为的值: protected integer ii _ select_ behavior这个变量中将存放下面的一些值。 可能发生的选择行为 值 行为 0 不允许选择行为 1 只允许有一行选中 2 自动实现多行选择 3 允许使用鼠标和键盘组合选择 99 不允许选择,将鼠标变成手型 如果使用的是保护变量或私有变量,这就意味着本对象以外的程序无法访问,因此必须为其他程序员建立对这些变量赋值和获取这些变量值的函数。 另外,还需要一些函数来执行基于该变量的过程。 函数:uf_setselect(select_behavior)我们要写的第一个函数将允许程序员设置选择行为。 函数: public integer uf_ setselect( integer ai_ select_ behavior)/* 本函数设置数据窗口的选择行为值 下列为有效的选择行为值 */choose case ai_select_behavior case 0, 1, 2, 3, 99 ii_ select_ behavior = ai_ select_ behavior // 至少一行将被选中 if ai_ select_ behavior = 1 then uf_ process_ select( getrow(), "keyboard" ) end if if ai_ select_ behavior = 99 then setrowfocusindicator(hand!) else setrowfocusindicator(off!) end if return 0 case else return -1 end choose 一旦选择类型被设置,所有的行都必须被处理。我们把这部分代码放入一个叫作uf_ processselect的函数中。这个函数处理选择行为。我们需要告诉该函数要处理的行和该请求是通过鼠标还是键盘发出的。下面是该函数代码: 函数:uf_ processselect(long al_ row, string as_ input_ type) long l_ row boolean b_ reset_ anchor boolean b_ keyboard, b_ mouse // 鼠标动作还是键盘动作? if upper(left(as_input_type,1)) = "k" then b_ keyboard = trueelse b_ mouse = trueend if/* 确认鼠标点在了数据窗口的记录上*/if al_ row < 1 then return -1/* 是否要确定起始行 */b_ reset_ anchor = truesetredraw(false)choose case ii_ select_ behavior case 0, 99 // 无 case 1 // 单行选中 selectrow(0,false) selectrow(al_row,true) case 2 // 多行选中 if b_ mouse then selectrow(al_ row, not isselected( al_ row )) end if case 3 if keydown(keyshift!) and keydown(keycontrol!) then if il_anchor_row > al_row then for l_ row = il_ anchor_ row to al_ row step -1 this.selectrow(l_row,true) next else for l_ row = il_ anchor_ row to al_ row this.selectrow(l_row,true) next end if elseif keydown(keyshift!) then selectrow(0,false) if il_ anchor_ row > al_ row then for l_ row = il_ anchor_ row to al_ row step -1 this.selectrow(l_ row,true) next else for l_ row = il_ anchor_ row to al_ row this.selectrow(l_row,true) next end if b_ reset_ anchor = false elseif keydown(keycontrol!) then selectrow( al_row, not isselected( al_row ) ) else selectrow(0,false) selectrow(al_ row,true) end ifend choosesetredraw(true)if b_ reset_ anchor then il_ anchor_ row = al_ rowreturn 0现在,要执行行选择时,只需调用uf_processselect()函数。一般当用户在一个数据窗口中点击了鼠标或是按下了上、下箭头键时,调用这个函数。另外还有捕获home和end键的代码。下面是we_keydown用户事件映射到pbm_dwnkey事件中的代码: event: we_ keydown (pbm_dwnkey) object: any datawindow if keydown(keydownarrow!) and getrow() <> rowcount() then uf_ processselect( getrow() + 1 , "keyboard") elseif keydown(keyuparrow!) and getrow() <> 1 then uf_ processselect( getrow() - 1 , "keyboard") elseif keydown(keyhome!) and rowcount() > 0 then uf_ processselect( 1, "keyboard") elseif keydown(keyend!) and rowcount() > 0 then uf_ processselect( rowcount(), "keyboard") end if最后,我们需要在clicked事件中加入: uf_ processselect(getclickedrow(), "mouse")在这个祖先函数中编写这样一个行选择的函数只是作为一个简单的实例,相信读者一定能因此受到启发,编写出更多的函数,以拓展数据窗口的基本功能。