PB应用程序就是由许多共同协作完成特定任务的窗口组成的集合。

窗口在应用程序的开发工作中占有很大的比重,是非常重要的一个 PB 对象

一、窗口类型

PB从入坑到放弃(五)窗口使用技巧-LMLPHP

二、窗口属性

2.1 General 属性页属性

2.2 Scroll 属性页属性

2.3 ToolBar 属性页属性

2.4 Other 属性页中的属性

三、11种常用控件

PB从入坑到放弃(五)窗口使用技巧-LMLPHP

四、窗口事件

4.1 常用事件

4.2 举个栗子

① open事件

Cb_Save.Enabled=False //禁用“保存”按钮的功能
SetPointer(HourGlass!) //将鼠标形状置为沙漏形
Dw_1.SetTransObject(SQLCA) //为数据窗口设置事务对象
Dw_1.Retrieve() //检索数据

② 避免用户因疏忽退出窗口而丢掉在数据窗口中的修改数据 ,通常在 CloseQuery 事件中判
断某些工作是否完成,并显示一个提示窗口询问用户,根据用户的确认,返回一个值来决定
是否触发窗口的 Close 事件。

返回值为 1,表示取消关闭动作;返回值为 0,表示继续执行Close 事件

Int li_flag
//如果数据窗口中没有修改,则允许执行 Close,直接返回
If dw_1.ModifiedCount() <= 0 And dw_1.DeletedCount() <= 0 Then Return 0
//如果数据窗口有修改,询问用户是否保存
li_flag = MessageBox("提示","数据已经修改,是否保存? ",Question!,YesNoCancel!,1)
Choose Case flag_i //根据用户选择执行
	Case 1 //用户选择要保存数据
		If dw_1.Update() = 1 Then //如果修改数据成功
			Commit; //提交
			Return 0 //继续执行 Close 事件
		Else //修改数据不成功
			rollback; //回退事务
			li_flag = MessageBox("提示","数据错误,是否继续关闭!",Question!,YesNoCancel!,2) //显示错误
			If li_flag = 1 Then
				Return 0 //允许关闭
			Else
				Return 1 //不允许关闭
			End If
		End If
	Case 2 //用户选择不保存数据
        Rollback; //回退事务
        Return 0 //允许执行 Close 事件
	Case 3 //用户选择取消
		Return 1 //不允许关闭
End Choose //用户所有的选择情况处理完毕

③ 在窗口的 Resize 事件中编写脚本,当用户调整窗口大小时,根据用户调整的
比例对窗口上的控件大小进行调整。首先定义两个实例变量用来保存调整之前的窗口大小

//open事件中代码
ii_width = This.width
ii_height = This.height
//Resize事件中代码
Int li_index //循环变量
DragObject lobj_every //用来获取窗口上的控件
For li_index = 1 To UpperBound(this.control[]) //对窗口中的所有控件逐一处理
    lobj_every = control[li_index] //保存当前控件
    lobj_every.x = lw_obj.x * (newwidth / ii_width) //重新设置 x 坐标
    lobj_every.width = lobj_every.width * (newwidth / ii_width) //重新设置宽度
    lobj_every.y = lobj_every.y * (newheight / ii_height) //重新设置 y 坐标
    lobj_every.height = lobj_every.height * (newheight / ii_height) //重新设置高度
Next
ii_width = newwidth //保存当前宽度
ii_height = newheight //保存当前高度

五、窗口常用函数

5.1 open 函数

① 语法

Open ( Windowvar)

② 参数

  • Windowvar 是一个 Window 类型的参数,是要打开的窗口名称

③ 返回

  • 成功时返回1,否则返回-1
  • 数为 Null, 则返回 Null

④ 举个栗子

//打开主窗口
Open(w_main)

注:连续调用Open函数,窗口不会被打开两次,只是第二次调用时会再次触发窗口 Activate 事件。为了避免这种情况,可以将脚本修改如下

If Not IsValid(w_main) Then //如果窗口没有打开
	Open(w_main) //则打开该窗口
Else //如果窗口已经打开
	W_main.BringToTop = True //将该窗口显示在最顶层
End If

竟然open函数调用两次也不能打开两个窗口,那么问题来了,怎么才能打开多个窗口呢?代码如下

① 打开和 w_edit 完全相同的一个窗口

w_edit lws_edit  //定义一个窗口变量
Open(lws_edit)   //创建窗口实例

②通过数组,打开多个实例窗口

w_edit lws_edit[3]
Int li_index
For li_index =1 To 3
	Open(lws_edit[li_index])
Next

5.2 close 函数

① 语法

Close ( Windowname )

② 参数

  • Windowname 是要关闭的窗口名称,是一个 Window 类型的变量
  • 成功返回 1,否则返回-1
  • 参数为 Null,则返回 Null

5.3 MessageBox 函数

① 简单模式

  • 语法
MessageBox(title,text)
  • 参数

    • title 为信息窗口标题
    • text 为提示信息
  • 举个栗子

    MessageBox(“错误提示” ,“数据保存错误! ” )
    

    PB从入坑到放弃(五)窗口使用技巧-LMLPHP

② 复杂模式

  • 语法

    MessageBox ( title, text {, icon {, button {, default } } } )
    
  • 参数

    • title 为信息窗口标题
    • text 为提示信息
    • icon 用来表示使用哪种图标
    • button 用来表示提供哪些按钮

图标icon取值如下

PB从入坑到放弃(五)窗口使用技巧-LMLPHP

按钮button取值如下

  • 举个栗子

    li_flag = MessageBox("提示","是否保存数据? ",Question!,YesNoCancel!,1)
    Choose Case li_flag
    Case 1 //用户选择 Yes,保存数据
    . . . . . . //处理语句
    Case 2 //用户选择 No,不保存
    . . . . . . //处理语句
    Case 3 //用户选择了 Cancel,不进行任何操作
    . . . . . . //处理语句
    End Choose
    

六、值传递与接收

6.1 字符串

① 打开一个窗口,并传递一个字符串

string ls_str
ls_str = '个人公众号:XiezhrSpace'
openwithparm( 窗口名,ls_str)

② 接收字符串

string ls_str
ls_str = message.stringparm

6.2 数值

① 打开一个窗口,并传递一个数值

openwithparm( 窗口名,1)

② 接收数值

long ll_row
ll_row = message.doubleparm

6.3 结构体

① 打开一个窗口,并传递一个结构体

st_parameter s_pm
s_pm.a = 1
openwithparm( 窗口名,s_pm)

② 接收结构体

st_parameter s_pm
s_pm = message.powerobjectparm
messagebox('提示',s_pm.a)

6.4 用户对象

① 打开一个窗口,并传递一个用户对象

//(1)、创建类用户对象u_parameter,并定义实例变量
//(2)、给用户对象赋值,并传递该用户对象
u_parameter u_pm
u_pm.a = '1'
openwithparm(窗口名,u_pm)

② 接收用户对象

u_parameter u_pm
u_pm = message.powerobjectparm
messagebox('提示',u_pm.a)

6.5 exe应用程序

① 打开一个exe,并传递参数

ls_exe = 'a.exe' + '|值1|' + '|值2|'
run(ls_exe)

② 接收exe传递的参数

string ls_parameter
ls_parameter = commandparm()

6.6 传递消息和接收消息

① 传递string消息

w_main.triggerevent('ue_open',0,'test')
//在用户自定义事件ue_open中接收消息:
string ls_msg
ls_msg = string(message.longparm,'address')

② 传递long消息

w_main.triggerevent('ue_open',100,0)
//在用户自定义事件ue_open中接收消息:
long ll_msg
ll_msg = message.wordparm

6.7 可视化类传值

u_customvisual u_cv
u_cv = create u_customvisual
openuserobjectwithparm(u_cv,1)

6.8 关闭窗口传递数据

① 语法

CloseWithReturn ( windowname, Returnvalue )

② 参数

  • windowname 是要关闭的窗口的名称
  • Returnvalue 要返回的数值

注:只有被关闭的窗口是 response 类型才能有效地获取返回参数

七、触发事件

7.1 立即触发

obj.triggerevent(clicked!)
obj.trigger event ue_init()
obj.trigger function wf_init()

7.2 在事件队列最后触发

obj.postevent(clicked!)
obj.post event ue_init()
obj.post function wf_init()

7.3 动态绑定触发

obj.dynamic event ue_init()
obj.dynamic function wf_init()
注:
动态调用和静态调用的区别
静态调用就是在编译代码时就对函数进行彻底编译
动态调用就是在程序执行的时候才回去查找和调用相应的函数

7.4 规定的时间内触发某事件

idle(60) //如果60秒没有操作的话就触发application对象的idle事件
timer(60) //每隔60秒就触发一次窗口的timer事件

八、窗口使用技巧

8.1 创建窗口实例

① 创建窗口实例

w_edit lws_edit
Open(lws_edit)

② 打开多个窗口实例

w_edit lws_edit[3]
Int li_index
For li_index =1 To 3
	Open(lws_edit[li_index])
Next

8.2 使用窗口属性编程

根据 tag 的取值对各个控件进行初始化

Int li_index,li_total
DataWindow ldw_temp
DropDownListbox lddlb_temp
RadioButton lrb_temp
li_total = Upperbound(Parent.Control[])
For li_index = 1 To li_total
	Choose Case Lower(Parent.Control[li_index].Tag)
	Case "DataWindow"
		ldw_temp = Parent.Control[li_index]
		ldw_temp.Reset()
	Case "DropDownListbox"
        lddlb_temp = Parent.Control[li_index]
        lddlb_temp.SelectItem(0)
	Case "radiobutton"
        lrb_temp = Parent.Control[li_index]
        lrb_temp.Checked = False
	Case Else
	…
	End Choose
Next

8.3 窗口最小化时设置动态图标

当程序最小化时打开 timer(在 deactive 中加入 timer(1)语句),并在 timer 事件中编写

程序激活时关闭 Timer 事件(在 Active 事件中加入 timer(0)语句)

If This.Icon = "appico.ico" Then
	This.Icon = "reverse.ico"
Else
	This.Icon = "appico.ico"
End If

8.4 放置闪烁文字

以闪烁文字显示重要信息可以吸引用户的注意力,避免这些重要信息被忽略。通过周期性修改 visible 属性,可以实现闪烁效果

在窗口中,假设放置一个静态文本 st_1,在窗口的 Open 事件中定义 Timer 事件的间隔:Timer(1)

Timer 事件 中代码如下

If Mod(Second(Now()),2) = 1 Then
	st_1.visible = False
Else
	st_1.Visible = True
End If

PB从入坑到放弃(五)窗口使用技巧-LMLPHP

8.5 提高窗口的打开速度

窗口的 Open 事件中经常编写脚本来进行初始处理工作,如果这些工作花费的时间比较长,在窗口显示之前用户就得等待很长的时间

这时,可以如下脚本优化

第一种方案:

open事件中添加代码

PostEvent("ue_openpost")

ue_openpost 事件中添加代码

SetPoInter(HourGlass!)
dw_1.SetTransObject(SQLCA)
dw_1.Retrieve()
SetPoInter(Arrow!)

第二种方案:

open事件中添加如下代码

dw_1.SetRedraw(False)
TriggerEvent("ue_openpost")
Dw_1.SetRedraw(True)

8.6 移动不带标题栏的窗口

在开发应用程序中,可能要用到不带标题栏的窗口,而带有标题栏的窗口可以通过拖放
标题栏来移动窗口,如何移动没有标题栏窗口呢?

在要拖放窗口的 MouseDown 事件中编写代码,代码如下

Send(handle(this),274,61458,0)

8.7 给窗口添加自动滚动条功能

窗口的 Resize 事件中编写脚本,根据当前窗口的大小来设置是否显示滚动条

① 声明函数

Subroutine GetScrollRange(Uint hWindow,Int nScrollBarFlag,ref Int nMin,ref Int nMax) Library "user.exe"
Function Int GetScrollPos(Uint hWindow,Int nScrollBarFlag) Library "user.exe"

② 定义实例变量

Int ii_width,ii_height

open事件中添加代码

ii_width = This.Width
ii_height = This.Height

Resize 事件中实现

Uint hwindow
Int nScrollPos,nMinPos,nMaxPos
If This.WindowState = Minimized! Then //如果正在进行最小化,则直接返回
	Return
End If
HWindow = Handle(This) //获取当前窗口的句柄
//下面开始处理水平滚动条
If This.Width < i_Width Then //如果小于打开时的宽度
	This.HscrollBar = True //则显示水平滚动条
Elseif This.HscrollBar Then //如果大于或等于打开时的宽度,并且已经有滚动条
    NScrollPos = GetScrollPos(hwindow,0) //使用 API 函数获取当前滚动条位置
    GetScrollRange(hwindow,0,nMinPos,nMaxPos) //使用 API 函数获取滚动范围
    If nScrollPos > nMinPos Then //如果用户滚动了滚动条并且此时不需要显示滚动条
    	Post(hwindow,276,6,0) //则在水平方向调整窗口中的内容到原来的位置
    End If
	This.HscrollBar = False //取消滚动条特性
End If
//下面开始处理垂直滚动条
If This.Height < i_Height Then //如果小于打开时的高度
	This.VscrollBar = True //则显示垂直滚动条
Elseif This.VscrollBar Then //如果大于或等于打开时的高度,并且已经有滚动条
    NScrollPos = GetScrollPos(hWindow,1) //使用 API 函数获取当前滚动条位置
    GetScrollRange(hwindow,1,nMinpos,nMaxPos) //使用 API 函数获取滚动范围
    If nScrollPos > nMinPos Then //如果用户滚动了垂直滚动条且不需再显示
    	Post(hwindow,277,6,0) //则垂直调整窗口中的内容到原来的位置
    End If
	This.VscrollBar = False //取消滚动条特性
End If

8.8 自动调整窗口

实现窗口居中

//***************************************************************
//* 功能: 将窗口移到屏幕的中央
//* 参数 1: aw_window 要处理的窗口
//* 返回值: (none)
//* 调用举例: gf_window_center(w_pay_mode) //将窗口置于屏幕的中央
//***************************************************************
Environment le_env
Int li_ScreenHeight, li_ScreenWidth
Long ll_posx,ll_posy
GetEnvironment(le_env)
li_ScreenHeight = PixelsToUnits(le_env.ScreenHeight,YPixelsToUnits!)
li_screenwidth = PixelsToUnits(le_env.ScreenWidth,XPixelsToUnits!)
If aw_window.width > li_ScreenWidth Then //如果窗口超宽
	ll_posx = 1
Else
	ll_posx = (li_ScreenWidth - aw_window.Width) / 2
End If
If aw_window.height > li_ScreenHeight Then //如果窗口超高
	ll_posy = 1
Else
	ll_posy = (li_ScreenHeight - aw_window.Height) / 2
End If

aw_window.Move(ll_posx ,ll_posy)

以上就是本期内容的全部,希望对你有所帮助。我们下期再见 (●'◡'●)

07-20 22:02