PowerBuilder 7.0编程技巧十则 一、实现运行窗口居中 要实现窗口的自动居中，我们可以用函数Move（）来实现。但是，由于我们开发出来的应用程序往往会在不同的设置环境中运行，虽然一般情况下是由我们为用户配置好的，但我们总不能保证用户显示器的设置模式不会改变。所幸的是，PB为我们提供了环境对象Environment,该对象其实是一个系统结构，其中保存了PB应用程序的运行平台信息，例如，代码集，CPU类型等。其中当然会有我们需要的屏幕宽和高。为了得到该结构我们可以用函数GetEnvironment（）。该函数的作用是得到关于操作系统，处理器和屏幕的系统信息。具体用法如下：
Environment my_system
Integer li_ScreenWidth, li_ScreenHeight
GetEnvironment(my_system)
// 得到屏幕的总宽度和长度
li_ScreenWidth = PixelsToUnits(my_system. ScreenWidth, XPixelsToUnits!)
li_ScreenHeight = PixelsToUnits(my_system. ScreenHeight, XPixelsToUnits!)
// 函数PixelsToUnits（）的作用是将屏幕的像数转换成PowerBuilder使用的单位，因为像数通常不用于方形中，具体用法请参见函数手册。
然后就可以用Move（）来实现窗口居中。
this.Move((li_ScreenWidth - this.Width)/2, &
(li_ScreenHeight - this.Height)/2 )
二、数据窗口中实现字段的组合
你有没有碰到这样的情况，我们输入了客户的详细地址资料，包括省份，城市，地址，邮编。当我们要给客户们邮寄信函时需要将他们的省份，城市，地址，邮编连成在一起打印出来。然而，这些信息是分开存储的，即存在不同的字段。这时我们就可以利用PowerBuiler提供的在数据窗口添加计算域（Compute Field）来实现字符字段的组合显示。
现在假设客户的省份，城市，地址，邮编分别存放在不同的字段中，它们是Province、City、Address、PC。我们要得到“邮编+省份+城市+地址”的格式，如：“（214001）江苏省无锡市人民路1号。”，具体实现如下：
1.在需要显示的位置添加一个计算域（Compute Field）
2.在它的表达式栏中写上" '（' + PC + ' ）' + Province + City + Address "
3.单击确定完成。
很容易是不是。需要提醒大家的是，计算域只能用来显示，不能对它进行修改，因为它没有TAB属性，不能得到焦点。
三、数据窗口中的条码显示
在数据窗口中显示条码是不是很神秘？这对于没有接触过条码的人来说也许是这样。其实，它简单的不能再简单了。别忘了我们在写文稿时是如何使文稿看上去更有艺术化。没错我们会给它用上各种字体。问题不就解决了吗？条码也是种字体，只不过我们看不懂罢了。我们只要将需要用条码显示的字段的字体换上相应的条码字体就行了，比如，常用的3 of 9条码字库等。这些字体大多数是免费的，可以到网上去下载，然后安装就行了。
四、数据窗口的自动刷新技术
在我们编写诸如像库存，销售等应用系统时，总希望程序能动态的自动刷新库存量或销售量，比如说每隔1秒刷新一次。要实现这样的功能只要我们利用数据窗口的时间间隔属性（Timer Interval），当该值为0时数据窗口不进行刷新，如果要使数据窗口以每一秒钟的频率刷新的话，只要将该值设为1000，即1000毫秒。
我们还可以为应用程序添加闪烁报警的功能。就拿库存量来说吧，最常用的是当某货物的库存量达到一个最低库存量时程序应能自动判别，并用警告色显示，通常是红色。此时，我们只要在运用了上述的方法后再在需要闪烁的字段上，比如，库存量，在它的颜色属性中写上相应的语句。下面这段代码实现“当某一物品的库存量小于20的时候，程序以红色闪烁显示警告”。
if ( Store_Num < 20, &
if mod( Second(Now()), 2) <> 0, & // 每秒一次，偶数显示红色，奇数显示白色，即底色
RGB(255, 255, 255), RGB(255, 0, 0) )
五、数据窗口中实现自动折行
有时为了界面的考虑需要将一些长字段折行显示，但又不能确保在所有情况下都会出现长字段。比如，我们要求当客户地址超过50个字符时将它分两行显示，对于没满50个字符的客户仍然按照正常格式显示。具体实现如下：
1.在数据窗口中选择要自动折行的列Address。
2.选择位置属性（Position）并选中Autosize Height选项。
3.选择编辑属性（Edit）并去掉Auto Horz Scroll选项。
4.选择数据窗口中细目带的属性Autosize Height选项。注意，是当你拖动细目栏时出现的属性。
设置完毕后在左下角预览窗口中将显示图例的结果。
在进行列自动折行显示的时候，还要注意一点，系统判断自动折行的断点是以空格或标点符号为依据的，如果我们输入一长串字符且中间没有任何标点符号或空隔的话，即使该字符串再长也无济于事。因此，我们一定要提醒用户在录入时适当的加入一些空格或回车。
六、数据窗口中记录颜色的隔层显示
相信你一定见过这样的显示，第一行记录的背景色是浅黄色，第二行记录的背景色是白色，第三行又是浅黄色，第四行又是白色......，依次类推。
要想让显示的数据达到上述效果，我们首先要知道的是这些数据存放在数据窗口中的什么地方。很显然，数据窗口中的所有数据是在细目带中列出的，因此只要在细目带中设置一些数据属性就会影响到这个细目带中的所有内容。具体实现如下：
1.打开数据窗口，单击细目带（Detail），注意是点击有“Detail”字的一栏，不是它存放数据的地方。点击它鼠标会出现上下小箭头。
2.选择常规属性，单击颜色属性（Color）旁边的一个带有红色图标的小按钮。
3.在表达式一栏中输入
if ( Mod( GetRow(), 2) = 0, RGB(255, 255, 200), RGB(255, 255, 255))
// RGB(255, 255, 200)，浅黄色
OK，预览一下，效果不错，大功告成。
七、实现数据窗口的动态排序
在用到Windows的资源管理器的时候，当我们需要按照文件的类型或名称排序的时候只要用鼠标点击一下相应的标题栏，系统会按照升序或降序交替排序，这完全取决于用户鼠标点击的奇偶数。如此方便的操作何不用到我们的数据窗口中--实现按某列的动态排序。
为了实现上述功能，程序首先需要用到一个全局变量（相对于PB来说可以用窗体变量），用它来控制连续两次点击之间的排序方向。因为字段的排序方向只有升序和降序两种，所以我们可以用一个Boolean型。本例中是Boolean ib_flag。接着在数据窗口控件的Clicked事件中写上如下代码:
String ls_column, ls_sort
ls_column = this.GetObjectAtPointer() // 得到鼠标按下位置的对象名
ls_column = left(ls_column, len(ls_column) - 2) // 得到列标题名字
if not Lower(right(ls_column, 2)) = "_t" then return
// 如果不是缺省的列标题，即以"_t"结尾或鼠标根本没有点在列标题上则退出
ls_column = left(ls_column, len(ls_column) - 2) // 去掉列标题末尾的"_t"，得到有效的列标题名
// 进行升序和降序的切换
if ib_flag then
ls_sort = ls_column + " A" // 升序
else
ls_sort = ls_column + " D" // 降序
end if
ib_flag = not ib_flag // 为下一次排序准备
ls_sort = ls_sort
this.setsort(ls_sort)
this.sort()
注：这里所叙述的数据窗口中列的动态排序是以系统默认的列标题名为前提，即在标题栏中列标题名字是以“_t”结尾。如果其中有设计者命名的列标题时只需增加一个条件分支，具体如何实现请读者自己完成。
八、设置系统时间
在开发具有数据服务器的应用软件时，有时为了使所有计算机的时间都保持相同，或者接近相同，主要是为了避免数据录入时出现的时间差异，通常我们会在客户机每次使用应用软件前将本地时间设置成跟服务器相同。从而确保输入的数据在时间上具有较高的正确性。即，要实现系统时间的设置。下面就讲述一下实现的过程。
本程序是通过调用外部函数SetSystemTime（）实现系统时间的设置,该函数返回布尔型。查阅一下有关参考手册就会发现该函数需要一个表示系统时间结构（Struct）的数据类型作为参数。此结构的定义如下：
struct _SYSTEMTIME {
INT iYear;
INT iMonth;
INT iDayOfWeek;
INT iDay;
INT iHour;
INT iMinute;
INT iSecond;
INT iMilliseconds; // 毫秒
} str_SystemTime;
要在程序中使用外部函数首先需要进行外部函数声明，可以根据函数的使用范围放在全局外部函数声明区或局部外部函数区声明。具体声明如下：
Function Boolean SetSystemTime(str_SystemTime str_MyTime) Library "Kernel32.dll"
声明之后就可以使用了。下面代码实现将系统日期设置成“2001年4月10日”
str_SystemTime str_MyTime
// 给结构赋值
str_MyTime.iYear = 2001 // 2000年
str_MyTime.imonth = 4 //4月
str_MyTime.iDay = 10 // 10日
// 设置系统日期
if SetSystemTime(ref str_MyTime) then
Beep(1)
MessageBox("提示","系统日期设置成功！")
else
Beep(1)
MessageBox("提示","系统日期设置失败！")
end if
注意:如果只有日期没有时间的话系统会将时间设置成默认的上午8点整。设置系统的时间方法和设置日期类似，只要将结构中的时、分、秒分别设置成想要的就行了。具体实现请读者自己完成。
九、用回车键获得焦点
在开发应用系统的时候，数据窗口中用户焦点要从一 个字段转移到另外一个字段的时候，只能用Tab键来实现，而用户通常是用回车键来改变焦点， 为了保持用户的习惯，在系统中实现良好的用户操作界面，我们就必须实现在数据窗口中用Enter 代替Tab在字段间移动。实现方法：
1.创建一个可视的用户对象（UserObject）， 在标准（Standard）对象中选择DataWindow。
2.选择Declare菜单项中的UserEvents子菜单， 定义一个用户事件，取用户事件名为pb_enter（事件名可任意指定），事件号（EventID）选择pbm_dwnprocessenter（此事件号不能任意指定）。点OK按钮退回。
3.在创建的用户对象上单击鼠标右键，选择弹出菜单上的Scripts项来编写程序，在selectevent上选择你刚才定义的pb_enter事件，在编辑窗中输入以下两条语句后退出：
Send(Handle(this),256,9,Long(0,0))
return1
4.给你的用户对象取一个名字后保存即可。
在你新建窗口需要用到数据窗口对象时，你就可以把你所定义的用户对象放入你的窗口中来代替PB提供的数据窗口对象，它就可以实现用Enter代替Tab在字段间移动。
十、实现列数据的自动折行
我们在PowerBuilder应用程序的开发过程中,使用数 据窗口时,经常会遇到某列的数据太长,不能同时全部显示的情况。若采用自动水平滚动,操作起来又不够简便。下面介绍一种方法,实现列数据多行显示,即实现列数据的自动折行。具体步骤如下:
1.打开一个数据窗口。
2.在需设定自动折行的列上双击鼠标,弹开此列的属性窗口。
3.选择Position选项卡,选中AutosizeHeight复选框;选择Edit选项卡,不选中AutoHorzScroll复选框。
4.单击OK按钮,保存所做的修改。
5.点中Detail带(写有Detail的灰色长带),单击鼠标右键,选择Properties菜单项。 选中AutosizeHeight复选框。
6.单击OK按钮,保存所做的修改。
7.保存此数据窗口。
注意:连在一起的汉字(中间没有标点或空格分隔), 系统将认为是一个单词,不会自动进行折行。

（夏 翔）