Database 版 (精华区)
发信人: wodeji (西西), 信区: Database
标 题: [转载] owerBuilder 开 发 系 列 谈 (31)
发信站: 紫 丁 香 (Tue Sep 29 17:53:22 1998), 站内信件
【 以下文字转载自 Programming 讨论区 】
【 原文由 two 所发表 】
Email: sjhzyz@public.bta.net.cn
在 上 期 中 我 们 讨 论 了 在Master/Detail 数 据 窗 口 中, 当Master 数 据 窗 口 没 有
使 用"Retrieve as Needed" 选 项 时, 两 个 数 据 窗 口 同 时 滚 动 的 问 题。 可 是 当Master
数 据 窗 口 使 用 了"Retrieve as Needed" 选 项 时, 我 们 却 遇 到 了 麻 烦。 在 点 击dw_2
的 滚 动 条 时, 如 果dw_1 从 数 据 库 中 取 得 了 新 数 据, 将 导 致dw_2 的 复
位,dw_2 就 不 能 显 示 正 确 的 结 果 了。 解 决 这 个 问 题, 我 们 最 容 易 想 到 的 解
决 方 法 就 是 利 用dw_2 在scrollvertical 事 件 中 获 得 的dw_2 当 前 滚 动 条 的 位 置,
对dw_2 进 行 重 新 赋 值。
即 对dw_1 的SCROLLVERTICAL 事 件 编 程 如 下:
integer vmax_1, vpos_1,vmax_2, vpos_2
string r_code
decimal vmax_1_percent
vmax_1 = integer(dw_1.describe("datawindow.verticalscrollmaximum"))
vpos_1 =integer(dw_1.describe("datawindow.verticalscrollposition"))
vmax_2 = integer(dw_2.describe("datawindow.verticalscrollmaximum"))
vmax_1_percent = vpos_1 / vmax_1
vpos_2 = vmax_1_percent * vmax_2
r_code = dw_2.modify("datawindow.verticalscrollposition="+string(vpos_2))
// 检 验 是 否 修 改 成 功
if r_code <> "" then
beep(6)
mle_1.text = "dw_1scroll = "+r_code+" vpos_2 = "+string(vpos_2)
//在scrollvertical事件中无法使用MessageBox弹出错误信息框
end if
对dw_2 的SCROLLVERTICAL 事 件 编 程 如 下:
integer vmax_1, vpos_1,vmax_2, vpos_2
string r_code
decimal vmax_2_percent
vmax_2 = integer(dw_2.describe("datawindow.verticalscrollmaximum"))
vpos_2 = integer(dw_2.describe("datawindow.verticalscrollposition"))
vmax_1 =integer(dw_1.describe("datawindow.verticalscrollmaximum"))
vmax_2_percent = vpos_2 / vmax_2
vpos_1 = vmax_2_percent * vmax_1
r_code = dw_1.modify("datawindow.verticalscrollposition="+string(vpos_1))
// 检 验 是 否 修 改 成 功
if r_code <> ""then
beep(6)
mle_1.text = "dw_1 mod "+r_code
end if
r_code = dw_2.modify("datawindow.verticalscrollposition="+string(vpos_2))
// 检 验 是 否 修 改 成 功
if r_code <> "" then
beep(6)
sle_1.text = "dw_2 mod" + r_code
end if
键 入 上 述 代 码 后, 运 行 时 你 就 会 发 现 点 击dw_2 时 运 行 的 结 果 是 正 常
的, 然 而 点 击dw_1 的 滚 动 条 却 发 生 了 错 误。 这 是 为 什 么 呢 ?
首 先 我 们 还 是 对 用 户 点 击dw_1 的 滚 动 条 向 下 滚 动 时, 系 统 进 行 了 哪 些
操 作 进 行 一 下 仔 细 地 分 析: 当 用 户 点 击 鼠 标 使dw_1 滚 动 到 了 最 后 一 行 时,
这 时 系 统 没 有 立 即 进 行 显 示 滚 动 的 操 作, 它 首 先 发 现 数 据 窗 口 的Primary! 缓
冲 区 的 数 据 已 经 告 罄, 于 是 就 向 后 台 的 数 据 库 中 攫 取 数 据, 取 得 新 的 数
据 后, 系 统 会 将 与dw_1 共 享 数 据 的dw_2 复 位, 使 之 回 到 显 示 第 一 条 记 录 的
位 置。 这 就 触 发 了dw_2 的scrollvertical 事 件( 我 们 称 之 为 事 件 一)。 在 这 个 事
件 中, 由 于 此 时dw_2 显 示 的 是 第 一 条 记 录, 它 将 修 改dw_1 的 滚 动 条 位 置,
使 之 也 显 示 第 一 条 记 录。 并 立 即 触 发dw_1 的scrollvertical 事 件 二。 在 事 件 二
中,dw_1 又 根 据 自 己 的 位 置 修 改dw_2, 但 是 由 于dw_2 修 改 前 后 的 位 置 相
同, 所 以 没 有 对 系 统 造 成 什 么 影 响, 又 回 到 了 事 件 一。 在 事 件 执 行 完 毕
后, 系 统 开 始 响 应 用 户 的 下 滚dw_1 的 操 作, 首 先 将dw_1 向 下 滚 动 一 条 记
录, 这 样dw_1 显 示 的 是 第 二 条 记 录, 并 触 发 了dw_1 的scrollvertical 事 件 三。 当
事 件 三 执 行 时, 将dw_2 也 滚 动 到 第 二 条 记 录, 并 触 发 了dw_2 的scrollvertical 事
件 四, 不 过 这 一 事 件 四 也 不 会 对 任 何 一 个 数 据 窗 口 造 成 影 响, 最 后 返 回
执 行 完 事 件 三。 这 就 完 成 了 用 户 点 击 鼠 标 后 的 一 连 串 响 应。 但 是 最 后 两
个 数 据 窗 口 却 显 示 的 是 第 二 条 记 录。 有 兴 趣 的 读 者 可 以 仔 细 分 析 这 一 系
列 事 件 发 生 的 顺 序。
用 户 点 击 滚 动 条 而 使 得 上 述 代 码 对 各 个 事 件 触 发 及 其 执 行 过 程 虽 然 十
分 复 杂, 并 不 是 每 一 个 人 都 有 兴 趣 对 其 分 析 清 楚, 但 是 这 个 代 码 的 错 误
却 是 一 目 了 然 的, 只 须 稍 加 测 试 就 可 发 现。 可 是 令 人 不 解 的 是 这 段 代 码
在 美 国 却 几 乎 被 视 作 经 典, 而 且 向 美 国PowerSoft 技 术 支 持 中 心 提 出 这 个 问
题, 那 里 的 工 作 人 员 也 会 引 用 这 段 代 码 作 为 回 答。
事 实 上 解 决 这 个 问 题 的 方 法 并 不 十 分 复 杂, 我 们 只 需 将 修 改 滚 动 条 位
置 的 时 间 稍 加 改 变 就 可 以 得 到 正 确 的 结 果。 首 先 我 们 在 这 两 个 数 据 窗 口
中 各 声 明 一 个ue_scrollvertical 的 用 户 自 定 义 事 件 事 件。 传 递 一 个 参 数, 参 数
名 为vpos,integer 型, 通 过 传 值 法 传 递。 然 后 键 入 下 列 代 码:
对dw_1 的SCROLLVERTICAL 事 件 编 程 如 下:
integer li_vmax_1, li_vpos_1,li_vmax_2, li_vpos_2
decimal ld_vmax_1_percent
li_vmax_1 = integer(dw_1.describe("datawindow.verticalscrollmaximum"))
li_vpos_1 = integer(dw_1.describe("datawindow.verticalscrollposition"))
li_vmax_2 = integer(dw_2.describe("datawindow.verticalscrollmaximum"))
ld_vmax_1_percent = li_vpos_1 / li_vmax_1
li_vpos_2 = ld_vmax_1_percent * li_vmax_2
if abs( li_vpos_2 - integer(dw_1.describe
("datawindow.verticalscrollposition")) ) > 1 then
//如dw_2应显示的位置与dw_2的当前位置不符,产生修改dw_2的事件
event post ue_scrollvertical( li_vpos_2 )
end if
对dw_1 的UE_SCROLLVERTICAL 事 件 编 程 如 下:
事 件: 自 定 义ue_scrollvertical
参 数:vpos integer 型
返 回 值:integer
string ls_ret_code
dw_2.modify("datawindow.verticalscrollposition="+string(vpos))
if ls_ret_code <> "" then
beep(6)
sle_1.text = "dw_1scroll = " + ls_ret_code + " vpos = " + string(vpos)
// 在scrollvertical 事 件 中 将 不 能 弹 出 错 误 信 息 框
end if
return 1
对dw_2 的SCROLLVERTICAL 事 件 编 程 如 下:
integer li_vmax_1, li_vpos_1,li_vmax_2, li_vpos_2
string ls_ret_code
decimal ld_vmax_2_percent
li_vmax_2 = integer(dw_2.describe("datawindow.verticalscrollmaximum"))
li_vpos_2 = integer(dw_2.describe("datawindow.verticalscrollposition"))
li_vmax_1 =integer(dw_1.describe("datawindow.verticalscrollmaximum"))
ld_vmax_2_percent = li_vpos_2 / li_vmax_2
li_vpos_1 = ld_vmax_2_percent * li_vmax_1
event post ue_scrollvertical(li_vpos_1)
//由于dw_1使用了retreive-as-needed,可能会自动将dw_2
滚回第一行,表现重新设置dw_2
ls_ret_code = dw_2.modify
("datawindow.verticalscrollposition="+string(li_vpos_2))
// 检 验 是 否 修 改 成 功
if ls_ret_code <> "" then
beep(6)
sle_1.text = "dw_2 mod" + ls_ret_code
end if
对dw_2 的UE_SCROLLVERTICAL 事 件 编 程 如 下:
事 件: 自 定 义ue_scrollvertical
参 数:vpos integer 型
返 回 值:integer
string ls_ret_code
ls_ret_code = dw_1.modify("datawindow.verticalscrollposition="+string(vpos))
// 检 验 是 否 修 改 成 功
if ls_ret_code <> ""then
beep(6)
sle_1.text = "dw_1 mod " + ls_ret_code
end if
我 们 再 分 析 一 下 上 述 代 码 执 行 的 过 程: 用 户 点 击 了dw_1 的 滚 动 条,
使dw_1 将 滚 动 到 最 后 一 行, 产 生 了dw_1 的scrollvertical 事 件 一, 但 并 没 有 立 即
执 行, 只 放 在 了 事 件 队 列 的 后 面。 系 统 首 先 发 现 数 据 窗 口 的Primary! 缓 冲 区
中 数 据 为 空, 向 后 台 数 据 库 取 数 据, 并 使dw_2 复 位, 回 到 显 示 第 一 条 记 录
的 位 置。 这 触 发 了dw_2 的scrollvertical 事 件 二, 在 首 先 执 行 的 这 个 事 件 二
中,PowerBuilder 根 据dw_2 当 前 显 示 的 是 第 一 条 记 录 这 一 条 件, 产 生 一
个ue_scrollvertical 事 件 三, 将dw_1 也 滚 回 显 示 第 一 条 记 录, 但 是 这 个 事 件 三 并
没 有 立 即 触 发 执 行, 而 是 放 在 了 事 件 队 列 的 最 后。 当 事 件 二 执 行 完 毕 后,
系 统 响 应 用 户 对dw_1 进 行 的 向 下 翻 页 的 操 作, 并 触 发dw_1 事 件 一 的 执 行。
这 时dw_1 显 示 的 是 用 户 希 望 看 到 的 正 确 的 记 录,PowerBuilder 根 据dw_1 的 当
前 位 置, 计 算 出dw_2 与 之 相 对 应 的 位 置, 将 修 改dw_2 位 置 的 操
作ue_scrollvertical 事 件 四 放 在 了 事 件 队 列 的 最 后。 这 时 该 执 行 事 件 三 了, 事
件 三 修 改dw_1 滚 动 条 的 位 置 至 第 一 条 记 录, 这 一 操 作 触 发 了dw_1
的scrollvertical 事 件 五, 此 时 两 个 数 据 窗 口 均 显 示 的 是 第 一 条 记 录。 在 这 一 事
件 中,PowerBuilder 经 过 计 算, 得 到 了dw_2 应 显 示 的 位 置 与 当 前 位 置 相 等 的
结 论, 因 此 不 产 生ue_scrollvertical 事 件, 事 件 五 没 有 对 系 统 产 生 任 何 影 响。 接
下 来 执 行 的 是 事 件 队 列 中 仅 存 的 事 件 四, 在 这 个 事 件 里, 系 统 将dw_2 滚 动
至 正 确 的 显 示 位 置 上, 并 触 发 了dw_2 的scrollvertical 事 件 六。 在 事 件 六 中, 系
统 又 产 生dw_2 的ue_scrollvertical 事 件 七, 但 是 这 两 个 事 件 均 没 有 对 显 示 造 成 任
何 影 响, 这 两 个 事 件 执 行 过 程 中 也 没 有 再 产 生 新 的 事 件, 这 一 系 列 的 响
应 便 最 终 结 束 了。 而 最 终 的 结 果 是 两 个 数 据 窗 口 都 是 停 在 了 正 确 的 结 果
上 了。
同 理, 我 们 对 用 户 滚 动dw_2 后 系 统 的 响 应 进 行 细 致 地 分 析, 也 可 以 看
到 上 述 代 码 的 正 确 性, 这 里 就 不 再 赘 述 了。
我 们 在 本 篇 中 编 写 的 代 码 可 能 并 不 一 定 在 您 开 发 的 软 件 中 使 用 得 上,
但 是 如 果 您 能 够 对 这 一 代 码 执 行 的 过 程 全 部 自 行 分 析 清 楚, 或 者 有 足 够
的 耐 性 看 明 白 了 上 面 文 章 的 分 析, 那 么 您 对PowerBuilder 的 事 件 一 定 会 有 更
深 的 理 解。
--
※ 来源:.紫 丁 香 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)
页面执行时间:203.959毫秒