在数据窗口中进行行选择操作

发表于:2007-07-02来源:作者:点击数: 标签:
我 们 在 数 据窗 口 中 需 要 进 行 行 选择 操 作。 如 用 户 为 了 修 改 数 据 或看 到 更 详 细 的 内 容 而 选 择 了 某 一 行; 在 另 一 些 情 况下, 用 户 可 能 要同 时 删 除 或 修 改 多 行, 这 时, 我 们 需要 有 使 用 户 在 一 个 数 据

       我 们 在 数 据窗 口 中 需 要 进 行 行 选择 操 作。 如 用 户 为 了 修 改 数 据 或看 到 更 详 细 的 内 容 而 选 择 了 某 一 行; 在 另 一 些 情 况下, 用 户 可 能 要同 时 删 除 或 修 改 多 行, 这 时, 我 们 需要 有 使 用 户 在 一 个 数 据 窗 口 中 同 时 选 择 多 行 的 功 能。这 在PowerBuilder 中 是 相 当 容 易 做 到 的, 但 是, 如 果 您 在 一个 数 据 窗 口 祖 先 中 没 有 标 准 的 函 数 来 处 理 这 些, 而 在每 个窗 口 中 重 复 的 编 程, 这 当 然 就 要 麻 烦 多 了。

       我 们 首 先 来看 一 看 进 行 行 选 择 的不 同 方 法。
所 有行 都 不 加 亮
       数 据 窗 口 的标 准 行 为 是 不 加 亮 任 何 行。 这 当 然 实 现 起 来 很 简 单了, 您 什 么 也 不 需 要 做。 这 种 做 法 对于 那 些 只 允 许 用户 进 行 滚 动 和 查 看 的 数 据 列 表 或 那 些 单 行 的 数 据 窗口 是 合 适 的。
单 行选 择
       单 行 选 择 意味 着 用 户 在 同 一 时 间 只 能 选 择 一 行。 在 用 户 选 择 一 行来 执 行 一 些 动 作, 如 删 除 或 是 在主 从 关 系 的 列 表 中 显示 详 细 信 息, 这 是 非 常 有 用 的。 下 面 是 实 现 允 许 单 行选 择 功 能 所 应 编 写 的 代码:

 

Event: RowFocusChanged

if GetRow() > 0 then

                    SelectRow( 0, FALSE )

                    SelectRow( GetRow(), TRUE )

end if

 
多 行的 自 动 选 择
       多 行 的 自 动选 择 时, 当 用 户 点 击 一 个 未 加 亮 的 行 时, 该 行 将 变亮。 如 果 用 户 点 击 一 个 加 亮 行, 该 行将 不 加 亮。

       为 了 实 现 上述 行 为, 您 可 以 将 以 下 的 代 码 放 入RowFocusChanged 事 件 中:

 

Event:RowFocusChanged

Event: RowFocusChanged

Object: Any DataWindow

if GetRow() > 0 then

                    if IsSelected( GetRow() ) then

                                        SelectRow( GetRow(), FALSE )

                    else

                                        SelectRow( GetRow(), TRUE )

                    end if

end if

       或者简化成为下面的一行代码:
       if GetRow() > 0 then SelectRow( GetRow(), NOT IsSelected( GetRow()))
       按住shift,control或control+shift点击鼠标的使用
       windows 的 文 件 管 理 器 或 其 它windows 程 序 中, 您 可以 使 用 按 住shift,control 或control+shift 这 种 键 盘与 鼠 标 的 组 合 来 改 变 选 择 行 为。PowerBuilder 在 数 据 窗 口 中没 有 提 供 这 样 的 能 力, 我 们 必 须 自 己 实 现。
       我 们 应 当 实 现 的 组 合 功 能 是:
       按 下 键
       动 作
       无
       只 加 亮 当 前 行, 将 其 它 行 的 显示 设 为 正 常
       Control
       保 持 其 它 行 的 状 态, 并 将 当 前行 也 加 亮
       Shift
       加 亮 起 始 行 至 当 前 行 之 间 的 所有 行, 将 其 它 行 的 显 示设 为 正 常
       Control-Shift
       保 持 其 它 行 的 状 态, 并 加 亮 起始 行 至 当 前 行 之 间 的 所有 行,
       建 立 这 样 的 功 能, 我 们 首 先 需要 对 起 始 行 进 行 跟 踪。在 用 户 使 用shift 或control-shift 键时, 系 统 应 当 把 当 前 用 户 用 鼠 标 点 击 或 键 盘 选 中 的 行与 在 此之 前 进 行 操 作 的 起 始 行 之 间 的 所 有 行 全 部 加亮。 因 此, 数 据 窗 口 必 须 记 录 当 前 的 起 始 行。 我 们 声明这 样 一 个 实 例 变 量:
       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(long al_row, string as_input_type)
       一 旦 选 择 类 型 被 设 置, 所 有 的行 都 必 须 被 处 理。 我 把这 部 分 代 码 放 入 一 个 叫 作uf_ProcessSelect 的 函 数 中。 这 个 函 数 处 理 选 择 行 为。 您 需 要 告 诉 该函数 您 想 要 处 理 的 行 和 该 请 求 是 通 过 鼠 标 还 是 键 盘 发出 的。 下 面 是 该 函 数:

 

long                                l_row

boolean                         b_reset_anchor

boolean                         b_keyboard, b_mouse

//  鼠 标 动 作 还 是 键 盘 动 作 ?

if Upper(left(as_input_type,1)) = "K" then

                                        b_keyboard = TRUE

else

                                        b_mouse = TRUE

end if

/*                  确 认 鼠 标 点 在 了 数 据 窗 口 的 记 录 上   */

IF al_row <1 THEN Return 1 /* 是 否 要 确 定 起 始 行 */ b_reset_anchor="TRUE" SetRedraw(FALSE) /* 有 效 的 操 作 值 0="不" 允 许 选 择 行 为 1="只" 允 许 有 一 行 选 中 2="自" 动 实 现 多 行 选 择 3="允" 许 使 用 鼠 标 和 键 盘 组 合 选 择 99="不" 允 许 选 择, 将 鼠 标 变 成 手 型*/ 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 IF

END CHOOSE

SetRedraw(TRUE)

if b_reset_anchor then il_anchor_Row = al_row

return 0

       现 在, 当 我们 希 望 执 行 行 选 择 时, 所 要 做 的 全 部 操 作 就 是 调 用uf_ProcessSelect() 函 数。 一 般 当用 户 在 一 个 数 据 窗 口 中 点 击 了 鼠 标 或 是按 下 了 上、 下 箭 头 键 时, 调 用 这 个 函 数。 另 外 还 有 捕获home 和end 键 的 代 码。 下 面 是we_keydow 用 户 事 件( 映 射 到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")

       在 这 个 祖 先函 数 中 编 写 这 样 一 个 行 选 择 的 函 数 只 是 作 为 一 个 简单 的 实 例, 相 信 您 一 定 能 因 此 收 到启 发, 编 写 出 更 多的 函 数, 以 拓 展 数 据 窗 口 的 基 本 功 能。

 

原文转自:http://www.ltesting.net