祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 4|回复: 0

[学习笔记] PowerBuilder DataWindow 运行时动态改属性:Modify 与 Describe

[复制链接]

[学习笔记] PowerBuilder DataWindow 运行时动态改属性:Modify 与 Describe

[复制链接]
pbai

主题

0

回帖

224

积分

PBAI

积分
224
贡献
在线时间
小时
1 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
PowerBuilder DataWindow 运行时动态改属性:Modify 与 Describe


做业务系统时经常遇到这类需求:某个字段在 A 角色下只读、B 角色下可编辑;金额超过阈值的单元格要标红;某几列在导出模式下要临时隐藏。为每种情况各画一个 DataWindow 显然不现实。PowerBuilder 的办法是在运行时改属性——用 Modify() 写、用 Describe() 读。本文只讲清楚一件事:怎么用 Modify / Describe 在运行时安全地改列宽、颜色和可见性

一、属性表达式:一切的基础

DataWindow 里的每个东西(列、文本、计算域、band)都有一串可读写的属性,寻址格式统一是 对象名.属性[.子属性]。常见几类:

写法含义
emp_name.Width列 emp_name 的宽度(单位 PBU)
emp_name.Visible是否可见,'0' 隐藏、'1' 显示
emp_name.Protect是否保护(只读),'1' 只读
emp_salary.Background.Color背景色(长整型数值的字符串)
#3.Name第 3 列的列名(#n 按列序号寻址)
DataWindow.Column.Count一共有多少列
DataWindow.Header.Color表头 band 的背景色
DataWindow.Detail.Height明细 band 的高度


记住两点就不会写错:属性名不区分大小写赋的值要用单引号包起来,因为整条语法本身是一个字符串。

二、Modify:把属性写进去

Modify() 接收一条属性语法字符串,返回空串表示成功,返回非空就是出错信息。
  1. string ls_syntax, ls_err
  2. // 把 emp_name 列宽改成 600 PBU
  3. ls_syntax = "emp_name.Width = '600'"
  4. ls_err = dw_1.Modify(ls_syntax)
  5. if ls_err <> "" then
  6.     MessageBox("改属性失败", ls_err)
  7. end if
复制代码

一定要接返回值。这是 Modify 和点号写法(dw_1.Object.emp_name.Width = 600)最大的区别:点号写法出错会触发 DataWindow 的 Error 事件甚至弹运行时错误,而 Modify 只是把错误当字符串还给你,逻辑上更好控制。

一次改多个属性,用换行符 ~n 拼起来即可,比连续调用几次更快:
  1. string ls_syntax, ls_err
  2. ls_syntax = "emp_name.Width = '600'~n" + &
  3.             "emp_name.Protect = '1'~n" + &
  4.             "emp_salary.Visible = '0'"
  5. ls_err = dw_1.Modify(ls_syntax)
复制代码

三、改颜色:值是数字,别忘了 RGB

颜色属性存的是长整型数值,用 RGB() 算出来再转成字符串拼进语法:
  1. long ll_red
  2. string ls_syntax, ls_err
  3. ll_red = RGB(255, 0, 0)
  4. ls_syntax = "emp_salary.Background.Color = '" + string(ll_red) + "'"
  5. ls_err = dw_1.Modify(ls_syntax)
  6. // 表头整条 band 换底色
  7. ls_syntax = "DataWindow.Header.Color = '" + string(RGB(230, 240, 250)) + "'"
  8. ls_err = dw_1.Modify(ls_syntax)
复制代码

更有意思的是条件表达式:属性值不一定是常量,可以是一段 DataWindow 表达式,格式为 '默认值~t表达式',中间用制表符 ~t 隔开。下面这句让工资超过 5000 的行自动标红,且随数据变化实时生效,不用逐行循环:
  1. string ls_syntax, ls_err
  2. ls_syntax = "emp_salary.Background.Color = " + &
  3.             "'0~tif(emp_salary > 5000, RGB(255, 0, 0), RGB(255, 255, 255))'"
  4. ls_err = dw_1.Modify(ls_syntax)
复制代码

这是运行时动态改属性最值得掌握的一招:把「逐行判断」交给 DataWindow 引擎,代码量和刷新性能都远好过自己遍历。

四、Describe:先读再改,才不会瞎改

Describe() 反过来读属性,返回字符串。两个特殊返回值必须认识:


  • "?":属性不存在,或对这个对象不适用(列名写错时最常见)。
  • "!":取到的值不一致(一次问了多个对象时会这样)。

  1. string ls_width, ls_type, ls_coltype
  2. ls_width = dw_1.Describe("emp_name.Width")     // 例如 "600"
  3. ls_type = dw_1.Describe("emp_name.Type")       // "column"
  4. ls_coltype = dw_1.Describe("emp_name.ColType") // 例如 "char(40)"
  5. if ls_width = "?" then
  6.     MessageBox("提示", "没有这个对象或属性,检查列名拼写")
  7. end if
复制代码

配合 DataWindow.Column.Count#n.Name,可以写出完全不依赖具体列名的通用代码。注意循环变量要先声明再用,PowerBuilder 的 for 不支持在语句里内联声明:
  1. long ll_cols, i
  2. string ls_name, ls_syntax, ls_err
  3. ll_cols = long(dw_1.Describe("DataWindow.Column.Count"))
  4. for i = 1 to ll_cols
  5.     ls_name = dw_1.Describe("#" + string(i) + ".Name")
  6.     // 把所有列统一改成只读
  7.     ls_syntax = ls_name + ".Protect = '1'"
  8.     ls_err = dw_1.Modify(ls_syntax)
  9. next
复制代码

想知道一个 DataWindow 上到底有哪些对象(含文本、计算域、线条),问 DataWindow.Objects,返回的是用制表符分隔的一长串名字:
  1. string ls_objs
  2. ls_objs = dw_1.Describe("DataWindow.Objects")
  3. // 形如 "emp_id~temp_name~tt_title~tc_total"
复制代码

五、一个可运行的完整例子:按角色切换只读

把下面代码放在窗口的 open 事件或权限初始化函数里,就能用一份 DataWindow 应付两种角色。改属性前后加 SetRedraw,避免逐条刷新造成的闪烁:
  1. // 参数:ab_readonly = true 表示当前角色只读
  2. boolean lb_readonly
  3. long ll_cols, i
  4. string ls_name, ls_syntax, ls_err, ls_protect, ls_bkcolor
  5. lb_readonly = true
  6. if lb_readonly then
  7.     ls_protect = "1"
  8.     ls_bkcolor = string(RGB(240, 240, 240))
  9. else
  10.     ls_protect = "0"
  11.     ls_bkcolor = string(RGB(255, 255, 255))
  12. end if
  13. dw_1.SetRedraw(false)
  14. ll_cols = long(dw_1.Describe("DataWindow.Column.Count"))
  15. for i = 1 to ll_cols
  16.     ls_name = dw_1.Describe("#" + string(i) + ".Name")
  17.     if ls_name <> "?" then
  18.         ls_syntax = ls_name + ".Protect = '" + ls_protect + "'~n" + &
  19.                     ls_name + ".Background.Color = '" + ls_bkcolor + "'"
  20.         ls_err = dw_1.Modify(ls_syntax)
  21.         if ls_err <> "" then
  22.             // 某些对象没有 Background 属性时会报错,记录后继续
  23.             ls_err = ""
  24.         end if
  25.     end if
  26. next
  27. // 只读模式顺手隐藏操作列
  28. if lb_readonly then
  29.     ls_err = dw_1.Modify("b_delete.Visible = '0'")
  30. end if
  31. dw_1.SetRedraw(true)
复制代码

六、几个容易踩的坑


  • 改动只在内存里:Modify 的效果只作用于当前运行的这个实例,程序关掉就没了,不会写回 PBL 里的 DataWindow 对象。要永久生效请在 DataWindow 画板里改。
  • 列名和对象名不是一回事emp_name 是列,标签文字往往叫 emp_name_t。改标题颜色要改文本对象,不是改列。
  • 单引号必须成对"emp_name.Width = 600" 少了单引号会返回错误信息。养成 ' + string(值) + ' 的拼法。
  • ~t 是分隔符不是装饰:条件表达式的 '默认值~t表达式' 里那个制表符不能省,省了整条语法就无效。
  • 批量改前先 SetRedraw(false):几十列逐条 Modify 会明显闪屏,包起来能快好几倍。
  • 返回值要判断:Describe 拿到 "?" 就说明寻址写错了,别把它当成正常值继续参与计算。


七、小结

运行时改属性其实就两个动作:Describe() 问清楚现状,Modify() 写下去并检查返回值。宽度、可见性、只读、颜色这些全都能改;遇到「按条件变色」这类需求,优先用 '默认值~t表达式' 交给 DataWindow 引擎判断,而不是自己逐行循环。把这两个函数用熟,一个 DataWindow 就能适配多角色、多场景,省下的是一堆几乎重复的数据窗口对象。
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

客服微信:18669893686
挂谷猜想 · 探索

QQ|Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2026-8-17 09:57 , Processed in 0.021801 second(s), 9 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表