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毫秒