Database 版 (精华区)

发信人: wodeji (西西), 信区: Database
标  题: [转载] owerBuilder 开 发 系 列 谈 (17) 
发信站: 紫 丁 香 (Tue Sep 29 17:52:07 1998), 站内信件

【 以下文字转载自 Programming 讨论区 】
【 原文由 two 所发表 】


        上 期 我 们 介 绍 了 使 用 自 定 义 用 户 对 象 取 代 系 统 自 身 的 数 据 窗 口 的
 技 术, 采 用 这 种 办 法 我 们 可 以 把 对 数 据 窗 口 经 常 作 的 操 作 编 写 成 为 对
 象 函 数, 在 数 据 窗 口 的 祖 先 对 象 中 进 行 定 义, 并 将 其 封 装 起 来, 而 不
 必 在 每 一 个 使 用 数 据 窗 口 的 窗 口 之 中 重 复 编 程。 在 数 据 窗 口 中 我 们 经
 常 要 使 用 对 各 条 记 录 的 选 择 操 作, 本 期 我 们 介 绍 如 何 将 这 样 的 功 能 在
 对 象 函 数 中 实 现, 以 拓 展 数 据 窗 口 的 基 本 功 能。 

        我 们 在 数 据 窗 口 中 需 要 进 行 行 选 择 操 作。 如 用 户 为 了 修 改 数 据 或 看
 到 更 详 细 的 内 容 而 选 择 了 某 一 行; 在 另 一 些 情 况 下, 用 户 可 能 要 同 时
 删 除 或 修 改 多 行, 这 时, 我 们 需 要 有 使 用 户 在 一 个 数 据 窗 口 中 同 时 选
 择 多 行 的 功 能。 这 在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")

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

                       



 中国计算机世界出版服务公司

--
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: 202.97.236.132]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: whs.hit.edu.cn]
--
※ 转载:.紫 丁 香 bbs.hit.edu.cn.[FROM: cadcam.hit.edu.c]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:207.511毫秒