Database 版 (精华区)

发信人: starstar (今天打老虎), 信区: Database
标  题: DataWindow Object 的几个有用的属性
发信站: 哈工大紫丁香 (2001年09月12日21:22:32 星期三), 站内信件

dw_1.Object.DataWindow.Column.Count 属性记录的是 DataWindow 中的列数。 Data
Window 中的所有对象都有 Type 属性,通过访问他们的 Type 属性可以得知他们是 Co
lumn、Compute、Text 等等对象。 动态改变 DataWindow 某一列的 Edit Style : 将
某一列的原来的 Edit 风格变成 DropDownListBox dw_1.modify("column1.ddlb.useas
border=yes") 。 在 DataWindow 控件中有许多事件的参数都是 DWO。DWO 全称 DataW
indowObject 。它指的是 DataWindow 中的一个对象。例如一个计算列、Text 框、Pic
ture Box 等等 对象,或者是 DataWindow 本身。通过访问 DWO 我们就可以知道当前用
户触 发的是哪个对象。例如: Dwo.Name = "datawindow" //说明此时 DWO 代表 Data
window Object 本身。 Dwo.band = "header" //说明该 dwo 位于 header 区。
   DataWindow 内部函数 DataWindow 有许多内部函数(只能在 DataWindow 画笔中
使用),它们都不能从 PowerScript中直接调用。不过我们可以利用 DataWindow Cont
rol 的函数 Describe 与 DataWindow 的 Evalute 结合起来运行。例如 DataWindow 的
内部函数 LookupDisplay ( Column ) 则是获取某一列上的显示值的函数。它与 Power
script 中的 GetItem 函数不一样,GetItem 函数获取的是数据值。 例:dw_1.Descri
be ( "Evaluate('LookupDisplay(produceid)', 1)" ) 获取 productid 列的第一行记
录当前的显示值。 DataWindow 中都有那些内部函数,以及各个内部函数的使用与用意
的资料我们目前都没有找到。我们也只是一点一点的积累,如果有那位朋友知道的话,
可千万要拿出来与大家分享哦!!!
   Browse 的使用 Browse 是 PB 开发环境中的一个画笔,与 Library、Database、
DataWindow 一样。但是却很少有人提到过它。Browse 其实是一个非常有用的工具。有
人抱怨知道如何更改 DataWindow Object 属性,但是又不知道究竟有哪些可以修改。使
用 Browse 就简单了。Browse 中的 Tab 控件上的 DataWindow 页列出了当前应用程序
所有的的 DataWindow Object 。同时窗口的右边列出了 DataWindow Object 具备的所
有属性。右击一个属性,选择Copy 。此时 PB 就将访问该属性的脚本格式 Copy 到粘贴
板上去了。你只需在你的源代码中 Paste 即可。Browse还有许多其他用途。 Browse 可
以以树状的形式将你应用程序中的所有的 UserObject 或着 Window 之间的继承关系全
部显示出来。对于 PFC 的初学者将是受益非浅,它可以帮你把 PFC 所有对象之间的继
承关系清清楚楚的现实出来。Browse 中的 OLE页中也非常有用,它将你机器中的所有 
OLE对象、ActiveX对象、COM对象都清清楚楚的列出来。如果你想知道你的机器中有哪些
组件可以使用用它可以轻松找到。关于 Browse的具体使用说明本人也从没见过,我想可
能是大家都觉得没什么可讲的吧。其实想想也是,所有操作只需点右健,当然没什么可
以多说了!顺便问一句 PB 是不是很强大?
   PB 的怪现象 有许多 PB 开发人员都抱怨 PB 总是无缘无故的出现一些怪毛病。那
么我告诉大家一套规则: “如果你一大早来到 PB 面前,发现程序无缘无故出了 Bug 
。但是又死活想不出毛病在哪(昨晚还是好的,今早就坏了)。立即将你的应用程序的
所有对象都重新生成一边(在 Library 画笔中使用 Regenerate),最好是按继承顺序
 Regenerate 一边。说不定 Bug 就消失了”。 不要觉得这条规则好简单,说不定这条
归则就可以帮你节省大量的时间。你们有没有想过 Powersoft 公司为什么要在 PB 中提
供一个 Regenerate 功能。我觉得它就是为了应付这种毛病。因为,除了这种情况下,
我再也想不出使用 Regenerate 的理由。 PB 开发 COM 存在的问题 安装了 PB gerner
ate 的朋友可以使用
   PB 开发 COM 组件,但是目前还只能开发进程中 COM 。PB 开发 COM 有几个问题
需要注意一下。 1. 使用 PB 的 Project 画笔编译好了 COM 组件后还不能使用,还要
将对应的 PBL 编译成 PBD 或则 DLL,具体是 PBD 还是 DLL 要看在编译 COM 时如何设
定的。一般默认情况是 PBD 。编译好了 PBD 或 DLL后,才能正常使用 COM 组件。当然
使用前 COM组件还应注册。如果你要发行你的 COM 组件,还必须要 PB 的 DDDK 中的 
DLL,就发行应用程序一样,还需要 PB 的 DLL 支持。 2. 不支持函数覆盖(OverWrit
e) PB 制作 COM 时是将不可视用户自定义对象(不妨命名为 n_cst_object)编译成 
COM 组件的接口。它将 n_cst_object 所有共有属性、函数、事件都编译成 COM 组件的
一个结构。但是如果这个n_cst_object 还有一个父类,并且 n_cst_object还覆盖了父
类中的函数,那么此时编译 COM 操作将无法通过。原因是 PB 在制作 COM 组件时会将
 n_cst_object 的父类中的所有属性、函数、事件也编译进去。所以,此时 PB 发现两
个一模一样的函数,编译也自然通不过了。解决办法很简单,将原来需要覆盖的函数申
明成保护类型。这样函数就可以最随意覆盖了。但是申明成保护类型后外界也就无法访
问该函数了。那么我们再在 n_cst_object的父类中申明一个共有类型的函数,该函数只
是简简单单的调用原来南各函数。至此一切问题都解决,函数可以覆盖了。下面是关于
这个问题的伪代码。 问题代码: Class n_cst_parent { public : int a() { //do s
omething } int b() {//hello! } }; class n_cst_object : n_cst_parent { Public
 : int a() {//OverWrite Parent script } } 此时将 n_cst_object 编译成 COM 组件
的接口,那么这个接口具备的函数将会是 int a() // 来自n_cst_parent int b() // 
来自n_cst_parent int a() // 来自 n_cst_object 显然这种 COM 接口不可能出现,因
此编译失败了。将上面的问题代码改为如下形式: Class n_cst_parent { protected:
 visual int a1() {//完成原来 n_cst_parent.a() 要完成的工作 } public: int a()
 { return a1(); } int b (){ //hello } } Class n_cst_object : n_cst_parent { 
protected: int a1() {//完成原来 n_cst_object.a() 要完成的工作 } } 此时再将 n
_cst_object 编译成 COM 的接口,那么这个接口具备的函数将会是 int a() // 来自n
_cst_parent int b() // 来自n_cst_parent 而且 int a() 函数调用的将是 n_cst_ob
ject 中的 a1() 。因为 a1() 被申明成虚函数。 所有问题全部解决!!! 以上代码只
是伪代码,PB 中的对象继承根本不是这样。还有在 PB 中函数已经申明就已经是虚函数
。直接具备多态特性。
   PB 某些控件的中文显示问题 假如 PB 的 ListView 不能正常显示中文,则应该将
 ListView 的 FontCh arSet 属性设置成其他类型。将 ListView 所在的对象 Export 
成源码。在源码 中找到 ListView 定义部分,将 FontCharSet 属性该成 DefaultChar
Set! 如果 PB 的其他控件也发生相应的现象时,同样调整一下它的 FontCharSe t 属性
。 一般来说对于简体中文字体,在中文 WINDOWS 环境中应该设置成 Default CharSet
!。对显示中文有问题的控件将它的 FontChatSet 属性强制设置成 Defa ultCharSet! 
应该没有问题。 或者改变字体!!!
   PB 中关于数据的并发控制 背景知识: DataWindow 在更新数据时,会根据用户对
 DataWindow 中的数据进行的各种 操作自动地转换成 SQL 语句,然后再执行。例如:
用户删除了一条记录(也就是 脚本执行了 DeleteRow() 函数),然后保存数据(调用
 Update() 函数)。此时 Update 函数会将刚才使用 DeleteRow() 删除的行自动转换成
 SQL 语句。 正文: 几乎所有的数据库软件需要考虑并发控制问题。那么 PB 的 Data
Window 如 何实现并发控制。答案就在 DataWindow 的更新属性(Update Properties)
中。 打开 DataWindow 画笔中的 Rows->Update Proerties 窗口。“Where Clause f 
or Update/Delete”组合框中的三个选项就是三种处理数据并发问题的策略。 首先做一
个假设: 有两个用户,用户A与用户B。他们分别在两台计算机面前。他们两人都通过 
PB 的 DataWindow 访问一个表。用户A在用户B读数据之前已经读取了表中的数 据。 表
中各子段名假设如下: Column PR_C 主码 Column C1 Column C2 Column C3 Column C
4 然后开始讨论他们的数据并发控制问题。 选项“Key Columns”: 该选项的意思是 
DataWindow 生成的 SQL 语句的 Where 子句部分只包含主 码。也就是说 DataWindow 
自动生成的SQL 语句大概样式是: Update Set C2 = XXXX, Set C1 = XXXX ... Where
 PR_C=OLD_PK 那么这意味着什么呢?试想一下如果用户A要更改PR_C=XXXX的记录时,如
果 用户刚好将此条记录的PR_C字段内容改变了。那么,很明显上述的 Update 语句也就
无法执行。从而起到了控制并发操作。然而这种并发操作发生的可能性 非常小。因该说
这样的并发控制完全没有意义。所以,通常只有在开发单机版软 件时才选择它。这么做
的唯一好处就是减少了 DataWindow 的运算量。 选项“Key and Updateable Column”
: 改选项的意思是 DataWindow 生成的 SQL 语句的 Where 子句部分包含主码 与所有
可以更新的字段。注意可更新字段与已更新字段的区别。可更新字段指的 是 DataWind
ow 允许更新的列(可以在 Rows->Update Proerties 中设置),那些不允许更新的列,
即使数据被用户更改了,DataWindow 也不会为 这些更改生成 SQL 语句。因此,用户的
更改不会保存到数据库中。已更新字段指 的是被用户更改了的字段(在此文中同时也被
认为是可更新的列)。不妨假设列 C1、C2、C3为可更新列。所以此时 DataWindow 生成
的 SQL 语句大概样式是: Update Set C1=xxx, Set C2=xxx ,,, Where PR_C = Old_P
K C1 = Old_value1 and C2 = Old_value2 and C3 = Old_Value3 其中 old_pk 指的是
这条记录的原来 PK_C 字段上的值,old_value1 表示 c1 字段上原来的值。由此可见如
果此时用户B修改了该记录的任何一个可更新字 段,那么这条 Where 语句必定返回 fa
lse,因此也无法更新?nbsp; 处理自动增类型字段 MS Sql Server 有一种 Identity 类
型的字段。这种类型的字段 MS Sql Se rver 会自动对它进行增一操作。通常都用来做
主码。而这种类型的字段是完全由 MS Sql Server 负责,其他人都不得干预。这样便引
发了一个问题。我们知道在 PB 中如果你的 DataWindow 的数据源没有选中主码,那么
 DataWindow 将是无法进行任何操作的。但是如果 我们将 Identity 类型的主码字段选
进 DataWindow 中,那么 DataWindow 在进 行插入操作是就会向 Identity 字段插入数
据。根据刚才的介绍,DataWindow 仍 然不能进行插入操作,因为 Ms Sql Server 不允
许任何外界对 Identity 类型字段进行操作。其实除了 Sql Server 以外, 还有许多 
DBMS 都具备这种类似的字段。因此,针对这一问题 PB 早有解决方案 。 在 DataWind
ow 画笔中选择菜单 Rows->Update Properties 在窗体的最下方有一个标题为 “Ident
ity Column”的下拉列表框。 在下拉列表框中选中 Identity 类型的字段 点确定按钮
关闭窗口 所有问题全部解决。 顺便提一下,Rows->Update Properties 中的内容是非
常有用的!!! 两个窗口的 Always On Top 属性 现在有许多程序运行时可以放置在所
有窗口的前面。在 PB 中实现起来非常 简单。只需调用窗体的 SetPosition ( TopMos
t! ) 即可。 w_main.SetPosition ( TopMost! ) 但是如果两个窗口都被设为在最前端
,结果会怎样? 结果很简单,这两个窗口都在所有窗口的前面。但是这两个窗口之间是
谁被 激活谁就在前面。
   处理 ToolBar 的移动问题 在 PB 中只有 MDI FRAME 类型的窗口才能具备工具条
。有的窗口没必要设成 MDI FRAME 类型,但是为了显示 TOOLBAR ,也不得不设成 MDI
 FRAME 。由于 TOOLBAR 是可以被拖动的。因此当 TOOLBAT 被拖到另一个地方时就有可
能挡住窗口中原有的控件。解决这种问题的一种办法 就是禁止 TOOLBAR 的移动(具体
方法请到本站点找)。但是这样做又显得软件不 够专业化。下面就告诉大家如何编程解
决这个问题。 假设窗口中只有一个控件 dw_1 ,其中 dw_1.x = 0, dw_y = 0, dw_wid
th = th is.width, dw_height = this.height。 代码如下: 在窗口的 resize 事件中
 1 dw_1.x = This.WorkspaceX () 2 dw_1.y = This.WorkspaceY () 3 dw_1.width = 
This.WorkspaceWidth () 4 dw_1.height = This.WorkSpaceHeight () - MDI_1.Micro
HelpHeight 所有问题解决。 代码分析: 首先介绍一下 WorkSpace 。窗口分两大部分
,1 工作区域--WokSpace 、2 非工作区--NonWorkSpace 。 WorkSpace 指的是不包括边
框、标题栏、菜单、水 平滚动条、垂直滚动条、工具条 的窗体内部区域。但是对于 M
DI 父窗口他包括 MICROHELP 域。显然 NonWorkSpace 就是除了 WorkSpace 之外的空间
。我们的控件很自然的应该放在 WorkSpace 内。当用户移 动了 TOOLBAR 时窗口的 Wo
rkSpace 也发生了相应的变化。因此,事件的前三行 大家应该很好理解。至于第四行,
由于刚才已经说明了对于 MDI 窗口,WorkSpa ce 还包括了 MicroHelp 。MDI_1 这个对
象是 PB 内置的对象,只要你的窗口是 MDI 窗口,那么 这个窗口中便有一个 Instanc
e 的 MDI_1 对象。这个对象 的类是 MDIClient,表示的 MDI 的客户区域。关于 MDIC
LIENT 的详细说明请参 考 PB 的联机帮助。
   多个 Tab 页共享一个 DW 的技巧 我们在开发程序时经常会用到 Tab 控件。往往
在几个 Tab 页上都要用到 D ataWindow 控件。常规的做法就是每个 Tab 页放上一个 
DataWindow 控件。但是 ,这样做的话我们总是要非不少精力来对齐各个TAB 页上的 D
ATAWINDOW 控件,而且占用的资源也很多。其实我们完全可以只用一个 DataWindow 现
实所 有的 Tab 页上需要的数据。首先只在窗体上(不是 Tab 控件上)放置一个 Dat 
aWindow 控件。建立若干个 DataStore 。这样当你点技某一 Tab 页时,你只需 调用 
ds.sharedata(dw)即可达到原来的效果。而且,再不需要为控件的位置、大小而 烦恼。

   妙用 Library 画笔中的 Export 功能 使用函数 Modify、Describe 或者直接访问
 dw_1.object.DwObject.Attrib = ... 等方法都可以访问 DataObject 中的对象,修改
 DataObject 中的属性。 虽然大家都知道如何去访问与修改 DataObject 。但是,往往
因为不知道 DataO bject 中到底有哪些属性、哪些可以修改、它们是什么类型数据等。
使得我们仍然不知 道如何修改 DataObject。其实最好的资料就是 PB 的源代码。在 P
B 的 Librar y 中可以将 PB 对象 Export 成一个文件。而实际上这个文件就是 PB 的
源代码 。如果我们熟悉 PB 的这种源代码的语法规则,完全可以脱离 PB 的开发环境直
接写代码,当然这是 没必要的。我就是利用 PB 的 Export 功能将 DataWindow Objec
t Export 成源 代码的形式,再查看其中的内容。一目了然, DataObject 究竟有哪些
属性全部 在源代码中列了出来。 大家不妨将其他的对象都 Export 一下,说不定就有
意外收获! 普通窗口也能拥有工具条! 在 PB 中有一点非常不好,只有 MDI Frame 类
型的窗口才可以具备工具条。 有时我们窗口又不是 MDI 。但是又需要工具条,怎么办
?没办法只能硬把 这个窗口设为 MDI Frame 类型。工具条也就出来。问题好象解决了
。但是 PB 的工具条还可以随意拖动。本来设计时工具条在窗口上方,结果用户把它 拖
到下面,一下把我的窗口中的控件就给挡住了。怎么办? 很简单,不让用户拖动工具条
。 将 Application 对象的 ToolbarUserControl 属性设置为 False 。从此, 用户就
不能拖动工具条了。 这种程序看上去仍有一点美中不足。人家的工具条都可以拖来拖去
,显得我 们的有点不专业!!! 其实还有方法使得用户将工具条拖来拖去还不会挡住
任何控件。 想知道答案?到本站点找!!! 提示:绝对不是要大家自己做工具条,完
全是使用了一点 PB 技巧。 利用 PB 建库 许多数据库开发人员都喜欢直接使用 DBMS 
提供的管理工具建库。其实如果 要用 PB 作为软件的前台开发工具,那么建库最好也是
使用 PB (除非是 PB 无 法完成的建库操作)。因为使用 PB 建库可以节省许多的前台
开发工作。 例如:我们在 Database 画笔中建表时可以直接为各个字段设定好样式。 
可以设定 Header、Label。这样基于这个表的所有 DataWindow Object 关于 该字段的
 Header、Label都已经设定好了。这样无须一个一个设置,也不用担心 会出现不一致的
现象。 你还可以在 Database 画笔中为各个字段设定有效性原则,设定好出错时的 错
误信息等。这样就为后面建立 DataWindow 省了不少功夫,而且所有的 DataW indow 都
一致。 关于 Database 画笔的使用还有很多,许多书上都有详细的介绍 。一句话在 D
atabase 画笔中建库只要用得好就可以大大的减少后期工作量。需要提醒一点的就是,
当 DataWindow 建好之后,再去 Database 画笔中更改 Header、Label等各属性后 ,D
ataWindow 也不会发生任何变化! 随意改变父类 pb程序员可以随意改变一个对象的父
类。具体方法如下: 将对象EXPORT成源代码形式。找到形式 global type Objectname
 from Ano therObjectName 两行,一般都在源代码的前面。将AnObjectName该成你的父
类。如果你的子类重 载父类中的函数,则必须将子类的函数定义成父类函数的形式。同
样这也可以在 源代码里更改,只需更改函数头以及函数体的第一句申明和函数体的最后
一句结 束语。并却子类中重载父类的函数的函数必须排在 子类自身的函数前面,否则
在INPORT时会非法操作。源代码该完后即可INPORT生 成对象。
   拖动无标题窗口 现在有许多应用程序都具备那些无标题可拖动的窗口。有关这种
窗口在 VB、 DELPHI中的制作的文章也有不少。本篇文章将讲述如何在 PB 中实现。 在
 PB 中实现这种窗口的拖动与在 VB、Delphi 中一样,采用移花接木的技 巧。当鼠标拖
动时Windows 首先会向鼠标下的窗口发送一个 wm_nchittest 消息,窗口收到这个消息
后再由窗口的消息处理函数进行处理,消息处理函数将 会返回一个整数表示鼠标正处于
窗口的什么部位。大家只需要知道的是处理函数 返回2,表示鼠标正处于窗口的标题栏
上。根据这一点,我们只要截获这条消息, 然后直接返回2。这样不管鼠标真正位于窗
口的什 么部位,WINDOWS 一律认为鼠标位于标题栏上。因此,用户自然可以拖动窗口。
 下面是具体的步骤: 1 为窗口定义用户自定义事件 Event Name: ue_nchittest Even
t ID: pbm_nchittest 2 在事件 ue_nchittest 中编写代码 Return 2 3 大功告成 大家
不妨采用这种方法为 Button 、Text 等可视控件也加上上述的事件与代 码。看看有什
么情况?说不定你就可以开发一套自己的可视化开发工具!!! 疑问: 当然这种方法
很好的解决了无标题窗口仍然可以拖动的问题。但是如果我这 个窗口还需要一个背景图
片。如果放置一个 PictureBox 这种方法就无效了。因 为窗口无法接受 wm_nchittest
 消息,被 PictureBox 挡住了。怎么办?答案就 在本站点!!!
   拖动无标题窗口还有一种方法,在窗口的 MouseDown 事件中编写如下脚本 Send 
( Handle ( this ), 274, 61458, 0 ) 至于这种方法的原理是什么,暂时还没弄明白。
用这种方法制作的窗口在运 行时与第一种方法制作的窗口还有点不一样。只能是留给大
家一起去探讨了。
   拖动无标题窗口 现在有许多应用程序都具备那些无标题可拖动的窗口。有关这种
窗口在 VB、 DELPHI中的制作的文章也有不少。本篇文章将讲述如何在 PB 中实现。 在
 PB 中实现这种窗口的拖动与在 VB、Delphi 中一样,采用移花接木的技 巧。当鼠标拖
动时Windows 首先会向鼠标下的窗口发送一个 wm_nchittest 消息,窗口收到这个消息
后再由窗口的消息处理函数进行处理,消息处理函数将 会返回一个整数表示鼠标正处于
窗口的什么部位。大家只需要知道的是处理函数 返回2,表示鼠标正处于窗口的标题栏
上。根据这一点,我们只要截获这条消息, 然后直接返回2。这样不管鼠标真正位于窗
口的什 么部位,WINDOWS 一律认为鼠标位于标题栏上。因此,用户自然可以拖动窗口。
 下面是具体的步骤: 1 为窗口定义用户自定义事件 Event Name: ue_nchittest Even
t ID: pbm_nchittest 2 在事件 ue_nchittest 中编写代码 Return 2 3 大功告成 大家
不妨采用这种方法为 Button 拖动具有背景图片的无标题窗口 背景知识: 截获 wm_nc
hittest 消息,并返回 2。从而实现无标题窗口可拖动。 我们知道通过截获 wm_nchit
test 消息并返回 2,可以实现实现无标题窗口 可拖动的功能。但是这个 wm_nchittes
t 必须由窗体截获。如果我们要在窗口上 显示一幅背景图,那么问题就出现了。放置一
个 PictureBox ?调用 WIN API 直 接对窗体绘画?如果是放置一个 PictureBox 那么
消息 wm_nchittest 将会被 PictureBox 挡住无法传到窗体中。调用 API 直 接对窗体
绘画当然可以成功,但是这要求你对 API 绘画熟悉。本文将采用一种非 常简单的方法
解决这个问题。 我们首先分析一下放置了 PictureBox 后,窗体为什么会接收不到 wm
_nchi ttest 消息。熟悉 MFC 的朋友可能会知道 PictureBox 的父类实际上是 Window
 。也就是说 PictureBox 是一个特殊的窗体。所以很自然 wm_nchittest 消息传 递给
 PictureBox 了,窗体也就接收不到了。那么有没有可能 PictureBox 仍然在窗口上,
但是消 息却传给窗口。可以,将 PictureBox 隐藏而且图片仍然显示在窗口上! Pict
ureBox.Setredraw ( False ) PictureBox.Hide () 问题解决, PictureBox 隐藏了,
而且图片仍然在窗口上。这样 wm_nchitt est 消息就直接传到窗体了(也许有读者会想
,PictureBox 截获 wm_nchittest 消息后再将该消息发送给窗口!很遗憾这样做不行)
。 下面是该方法的源代码: 1. 假设窗体名为 w_main,PictureBox 控件名为 p_1 。
 2. 为 p_1 截获 wm_mousemove 消息 为 p_1 定义用户自定义事件 Event Name: ue_m
ousemove Event ID: pbm_mousemove 在 ue_mousemove 事件中编写代码 This.Setredr
aw ( False ) This.Hide () 3. 为 w_main 截获 wm_nchittest 消息 为 w_main 定义
用户自定义消息 Event Name: ue_nchittest Event ID: pbm_nchittest 在 ue_nchitt
est 事件中编写代码 Return 2 4. 为 w_main 截获 wm_paint 消息 为 w_main 定义用
户自定义消息 Event Name: ue_paint Event ID: pbm_paint 在 ue_paint 事件中编写
代码 This.Setredraw ( True ) This.Show () 说明: 步骤 2 用意:当鼠标移动到窗
口时 p_1 便隐藏了,这样用户随时都可以 拖动窗口。 步骤 4 用意:窗口上仍然显示
图片只是因为 p_1 不再重画,所以虽然 p _1 隐藏了,但是图片仍然保留在窗口上。也
正是这个原因,如果有任何其他窗体 或控件挡住了 图片那么图片便无法恢复。因此我
们要截获 wm_paint 消息,重新 显示一次 p_1 。 至此,所有问题圆满解决!!!
   有效性原则 用户可以在程序运行是动态更改DATAWINDOW的有效性原则 使用 GetV
alidate 和 SetValidate 函数。 在数据库画笔中建立的有效性原则将保存到PB的系统
表中, 也就是说原则一旦建立,可以适用于该数据库中任何相同类型的字段。 此时设
置的有效性原则将是DATAWINDOW OBJECT 中默认的有效性原则。 注意:若数据库中有效
性原则发生了变化,DATAWINDOW OBJECT 中有效性原 则不会发生变化!   有效性原
则中的表达式: 程序员可以使用任何POWERSCRIPT 函数,甚至是用户自定义函数!@co
l代表 当前行列col的数据。如果被检验的列属于字符串类型,则程序员可以使用MATCH
 函数。在DATABASE 画笔中定义有效性原则时点击MATCH按扭,即可自动生成MATC H函数
。 MATCH函数规则:match(@col,Textpattern),Textpattern 有点类似于正规 表达式
 Textpattern 的构造方式如下: Textpattern 分两部分:1、特殊符,2、非特殊符 特
殊符: 符号 ^:与字符串的第一个字符进行比较。 例 ^C 比较字符串的第一个字母是
否为 C 。 符号 $:与字符串的最后一个字符进行比较。 例 s$ 比较字符串最后一个字
母是否为 s 。 符号 .:任意一个字符。即通配符。 转义符 \: 恢复特殊字符的原义
。 符号[]: 方括号中字符代表“或”关系。 例如:[AEIOU]代表A、E、I、O或U。括号
中可以有连字符"-"。[A-Z]代 表任意一个大写字母。如果方括号中的第一个字符是 ^,
表示除去括号内的任意 字符。 符号 *:重复零次或多次 符号 +:重复一次或多次 符
号 ?:重复零次或多次 例子: AB Any string that contains AB; for example, ABA
, DEABC, graphAB_ one B* Any string that contains 0 or more Bs; for example,
 AC, B, BB, BBB, ABBBC, and so on AB*C Any string containing the pattern AC 
or ABC or ABBC, and so on (0 or more Bs) AB+C Any string containing the patt
ern ABC or ABBC or ABBBC, and so on (1 or more Bs) ABB*C Any string containi
ng the pattern ABC or ABBC or ABBBC, and so on (1 B plus 0 or more Bs) ^AB A
ny string starting with AB AB?C Any string containing the pattern AC or ABC 
(0 or 1 B) ^[ABC] Any string starting with A, B, or C [^ABC] A string contai
ning any characters other than A, B, or C ^[^abc] A string that begins with 
any character except a, b, or c ^[^a-z]$ Any single-character string that is
 not a lowercase le tter (^ and $ indicate the beginning and end of the stri
ng) [A-Z]+ Any string with one or more uppercase letters ^[0-9]+$ Any string
 consisting only of digits ^[0-9][0-9][0-9]$ Any string consisting of exactl
y three digits ^([0-9][0-9][0-9])$ Any consisting of exactly three digits en
close d in parentheses
   PB 的跨平台 其实除了 JAVA 的 CLASS 文件是跨平台的,用 PB 编译出来的 PBD
 文件同 样是跨平台的文件。你可以在任何平台下制作 PBD 文件,然后发行到任何一个
平 台上。当你的应用程序升级时你只需要发行你更改过的 PBD 文件,当然前提是你 的
应用程序的 Library List 没有发生变化。如果你的应用程序的 Library List 发生了
变化,那么你只能重 新编译你的 EXE 与 所有的 PBD 然后再发行。 SetRedraw(FALSE
) SetRedraw () 是 PB 中几乎所有的可是控件都具备的函数。SetRedraw 的用 意的关
闭或开启控件的重画功能。如果一个控件或窗口被别的 A 挡住了,然后 A 此时有移开
了或关闭了。那么 Window 将会通知这个控件或者窗口要求他们重 画一遍自己,这就是
重画的意思。 当 DataWindow 检索大量数据时 SetRedraw 函数就大有用途了。DataWi
ndo w 每检索出一条数据便会重画一边 DataWindow 。因此如果有大量的数据需要检 索
的话,那么 DataWindow 将会频繁闪烁。同时也消耗了大量的 CPU 资源。因此 ,我们
可以在检索数据之前调用 SetRedraw ( False ) 关闭重画功能,在数据检索完后在开启
重画功能,即 SetRedraw ( Tru e )。这样便消去了闪烁现象,最关键是大大地提高了
检索速度。 SetTrans vs SetTransObject 函数 SetTrans 与 SetTransObject 都是为
 DataWindow 指定事务对象。但 是这两个函数又有很大的区别。使用 SetTrans 函数 
DataWindow 每次访问数据 是都单独建立一次连接。也就是说 DataWindow 每次访问数
据库都要经过连接数 据库、断开连接的过程。使用 SetTransObject 函数 DataWindow
 的每次对数据库的访问都使用该函数设置的事务对象。一般情 况下,都使用 SetTran
sObject 。 使用 ID 字段的好处 有人会觉得并不是所有场合都需要使用 ID 字段。的
确如此,但是使用 ID 字段却有许多好处。 记录你的应用程序所发生的所有错误 记录
应用程序发生的错误是非常重要也是非常有意义的事情。本篇文章将为 大家介绍一种在
 PB 中记录应用程序错误的方法。 应用程序错误分为两大类。一种是与实际情况不符的
错误,例如软件中出现 了年龄大于两百岁的人。一种是物理错误,例如非法操作等。这
两种错误对于用 PB 开发出的软件经常都会发生。不管是那种错误我们都需要记录一些
相同的信 息。错误发生的描述,错误发生所在的 Window、menu 或 Object ,错误发生
所在的事件函数,PB 返回的错误号等。 具体做法: 为应用程序对象定义事件 ue_log
error Event Name: ue_logerror Event ID: 空 Arguments : Error aerr_error 脚本
如下: string ls_message Integer li_fhandle ls_message = & + 'Error Number '
 + string(aerr_error.number) & +'.~r~nError text = ' + aerr_error.text & +'.
~r~nWindow/Menu/Object = ' + aerr_error.windowmenu & +'.~r~nError Object/Con
trol = ' + aerr_error.object & +'.~r~nScript = ' + aerr_error.objectevent & 
+'.~r~nLine in Script = ' + string(aerr_error.line) + "." li_fhandle = FileO
pen ( "Error.log", LineMode! , write! , LockReadWrit e! , Append! ) ls_messa
ge = String ( CrtDate ) + " " + String ( CrtTime ) + " " + ls_ message FileW
rite ( FileHandle, ls_message ) FileClose ( FileHandle ) 对于应用程序的物理错
误处理采用方法: 在应用程序的 SystemError 事件中编写代码 This.Event ue_loger
ror ( Error ) Halt 对于应用程序出现与实际不符的错误则在脚本中: If ll_rc <= 
0 Then // 将错误记录到日志文件中 error lerr_error lerr_error = Create error 
lerr_error.text = "无法初始化安全服务" lerr_error.is_pblname = "" lerr_error
.windowmenu = "" lerr_error.object = "rs_n_cst_appmanager" lerr_error.object
event = "constructor" lerr_error.line = 84 lerr_error.number = ll_rc myapp.E
vent ue_logError ( lerr_error ) Destroy lerr_error return End If How to dete
rmine if you are connected 如果在使用 DataWindow 之前,SQLCA 并未连接到数据库
。那么程序将会出 现错误。所以有时有必要判断一下 SQLCA 是否已经连接到数据库。
 使用函数 dbhandle 。函数 dbhandle 将返回数据库服务器分配的 handle 。如果 ha
ndle 为 0 表示 sqlca 未连接到数据库。 PB 6.5 的 Timing Object PB 5 中只有 Wi
ndow 才有 Timer 事件。利用 Timer 事件可以实现一些定时 执行的功能。 pb 6 现在
还提供 Timing 标准不可视对象。利用该对象不仅可以 在窗体中实现定时功能,还可以
在用户自定义对象中实现定时功能。 制作一个用户自定义对象 ue_timer 继承 Timing
 对象 在 ue_timer 中定义属性 PowerObject ipo_object String is_event 在 Timer
 事件中 ipo_object.TriggerEvent ( is_event ) 至此通用 ue_timer 事件已经完成,
下面是使用该对象的方法 在 n_cst_object 对象中定义实例变量 ue_timer i_timer 在
 n_cst_object 的构造事件中 i_timer = create ue_timer i_timer.Interval = 1000
 // 一秒钟执行一次 i_timer.ipo_object = this i_timer.is_event_or_function = 
"ue_myevent" 在 n_cst_object 的析构事件中 destroy i_timer 在 ue_myevent 中编
写相应的代码
   向窗口传递参数的几种方法 向窗口传递参数有好几种方法。最简单的方法当然是
利用全局变量。其实这 更本不算是一种方法。传递参数的方法主要有两种。 1. 利用 
Message 全局变量,也是比较常用的方法。 OpenWithParm ( w_main, 1 ) OpenWithPa
rm 函数将会自动的将 1 放入 Message 对象的 Number 属性中。 然后再 w_main 窗口
的 Open 事件中访问 Message 的 Number 属性就可以获得由 OpenWithParm 函数传来的
参数。OpenWithParm 函数可以传递的参数不仅仅是 整型,还可以是 String、Double 
甚至是 PowerObject 类型。如果传递的是 String 类型,那么参数就会被放入 String
P arm 属性中。如果是 Double 类型,那么参数就会被放入 DoubleParm 中。同样 ,如
果参数是 PowerObject 类型,参数就会被放到 PowerObjectParm 中。这种方法是最常
用的方法,也是最简洁的方法。但是这种方法只能传递一个 参数。对于需要传递多个参
数的话那就的采用方法 2 。 2. 利用结构向窗口传递参数 由于 Message 对象的 Powe
rObjectParm 参数可以储存任何的 PB 对象。利 用这个特点,我们将所有需要传递个窗
口的参数都封装到一个结构中(类也可以 )。在使用 OpenWithParm 函数将结构作为参
数传给窗口。具体的源代码如下: 定义结构: global type s_a from structure str
ing a string b end type 传递参数: s_a ls_parm ls_parm.a = 'ha' ls_parm.b = 
'hb' OpenWithParm ( w_main, ls_parm ) w_main 的 open 事件: s_a ls_rec ls_re
c = Message.PowerObjectParm 至此,ls_rec 中就收到了有 OpenWithParm 函数传递来
的多个参数。
   处理表单打开时位置自动向右下方移动问题 PB 的 MDI 父窗口有一个非常令人讨
厌的问题。每次你打开一个表单, 表单的位置总是向右下方移动一点距离,而不管 MD
I 中是否只有一个表单。 下面的代码将为您解决这个问题。首先必须定义一个父类窗口
 w_sheet , 所有的表单都必须继承该 w_sheet 。 在 w_sheet 中定义共享变量: /* 
用于记录已打开表单的数目 */ integer si_count /* 用于记录表单所在的位置 */ in
teger si_win[] 定义如下的实例变量: int ii_count /* 当前表单号 */ 窗体的 Open
 事件: integer li_i /* 增加已打开的表单数 */ si_count++ /* 确定当前该 sheet
 所在的位置 */ FOR li_i = 1 TO UpperBound(si_win) IF si_win[li_i] = 0 THEN i
i_count = li_i EXIT END IF NEXT IF ii_Count = 0 THEN ii_Count = si_Count /* 
将新位置保存到数组中 */ si_win[ii_count] = 1 /* 将窗口移动到新位置 */ This.M
ove((ii_count - 1) * 75,(ii_count - 1) * 75) 窗体的 Close 事件中: /* 释放该窗
口在 si_win 中的位置 */ si_win[ii_count] = 0 /* 减少已打开的窗口数 */ si_cou
nt --
   Post 与 Trigger 的使用 PB 的函数与事件有两个种调用方式。一种同步方式、一
种异步方式。 同步方式的调用就是等待函数或事件执行完后再执行下一步的代码。异步
 方式就是不等待函数执行完毕就执行下一步的代码。一般情况的调用都是 同步方式的
。使用关键字 Post 表示采用异步调用。关键字 Trigger 表示同步调用,一般同步调用
不用使用任何关键字。 Post 方法是一种非常有用的方法。最典型的用法是用在数据库
连接的 时候。PB 初学者一般都在 Application 对象或者窗体的 Open 事件中连接数据
。这种做法是最常规的做法。一般大家在开发程序的时候很 少出现连接不上数据库的问
题或者找不到服务器的时候。因此,这种做法并 没有带来什么不变。而往往软件发放的
用户手中后,用户的环境总是不确定 的。出现找不到服务器、网络线路问题等等都是很
平常的事 如数据库的连接仍然在 Application 的 Open 事件或者 Window 窗口的 Ope
n 事件中,当数据库连接不上时会出现“死机”的假象。使用 Post 方法可以很好的解
决这种问题。方法如下: 1 为窗口定义自定义事件 Event Name:PostOpen EVent ID:
空 2 在窗体的 Open 事件中 Post Event PostOpen () 3 在 PostOpen 事件中编写关于
数据库的连接代码。 

--
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: hfi.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:204.925毫秒