【PB】Windows 状态条控件在 PB 中的运用

PB在窗口中实现实时帮助条 在窗口中实现实时帮助条 一.Midhelp!窗口实时帮助 W_Main是Midhelp!窗口,Ready部分是显示帮助信息 在窗口和各个控对象的Tag属性,简单说明帮助信息 在W-main窗口定义一个实例函数show_help,参数myhelp,sttring.代码:this.setmicrohelp(myhelp) 在窗口对象和控件对象定义一个用户事件,事件名称如:mousecomin... 阅读详情

Powerbuilder 所提供的 MDIHelp! 窗口类型带有一个 Sybase 自制的类似状态条的控件(严格说它并非是控件),用户可以通过调用 SetMicroHelp( ) 函数修改该控件的显示文本,即该窗口的标题。但与 Windows 的状态条控件相比,它还是缺少了些重要的功能,因此本文将就如何在 Powerbuilder 中使用 Windows 状态条控件展开讨论。在讨论前笔者假设读者对如何在 Powerbuilder 中使用 Windows 公共控件已有所了解,如果读者不了解的话,可以参考笔者的《用 Windows 公共控件增强 PB 应用的界面》。

初始化控件

为演示 Windows 状态条控件的功能,笔者先创建一个类型为 Main 的窗口对象,并命名为 w_frame。然后创建一个外部可视用户对象,将

属性 LibraryName 设为:%System%/ COMCTL32.DLL;

属性 ClassName 设为:msctls_statusbar32;

属性 Style 设为:256。

这里 Style 属性有宏 CCS_TOP 和 SBARS_SIZEGRIP 供组合,CCS_TOP(1) 表示控件将显示在父窗口的顶部而非底部,SBARS_SIZEGRIP(256) 表示控件将显示 Sizing Grip,如图1和图2所示。

图1图1

图2图2

正如笔者在《用 Windows 公共控件增强 PB 应用的界面》中所说的,状态条控件不必调用 InitCommonControls( )、CreateWindowsEx( ) 和 ShowWindow( ) 函数。因此修改上述的属性后,状态条控件即显示出来了。将该用户对象命名为 ctrl_status_bar,并将继承自该用户对象的用户对象 ctrl_sbar 布置于 w_frame 上。

动态调整大小

当调整父窗口的大小时,需要相应调整状态条和 MDIClient 的大小,在父窗口的 resize 事件中,修改控件的宽及 MDIClient 的坐标和长宽:

w_frame.Event Resize(ulong sizetype,  int  newwidth,  int  newheight) returns  long
    stc_rect    lstc_rect
    
    ctrl_sbar.width 
=  newWidth
    GetClientRect(Handle(this), lstc_rect)
    lstc_rect.bottom 
=  PixelsToUnits(lstc_rect.bottom, YPixelsToUnits!)
    mdi_1.y 
=  lstc_rect.bottom  -  WorkSpaceHeight()
    mdi_1.width 
=  WorkSpaceWidth()
    mdi_1.height 
=  WorkSpaceHeight() –  80

同样工具栏的移动会修改 WorkSpace 的大小,故需要进行调整:

w_frame.Event ToolbarMoved() returns  long
    stc_rect lstc_rect

    GetClientRect(Handle(this), lstc_rect)
    lstc_rect.bottom 
=  PixelsToUnits(lstc_rect.bottom, YPixelsToUnits!)
    mdi_1.y 
=  lstc_rect.bottom  -  WorkSpaceHeight()
    mdi_1.width 
=  WorkSpaceWidth()
    mdi_1.height 
=  WorkSpaceHeight() –  80

简单模式状态条

如图1和图2所示的由单一部分构成的状态条称为简单模式状态条,形式与 Powerbuilder 的 MDIHelp! 的状态条极相似,只要修改 Text 属性就可改变状态条的文字。

多部分状态条

多部分状态条由多个部分构成,如图3所示。要实现从缺省的简单模式向多部分状态条的转换,需要向控件发生 SB_SETPARTS 消息。

图3图3

一般在 Powerbuilder 中发送消息要用 Send( ) 函数,但 SB_SETPARTS 消息的参数为:

wParam  =  (WPARAM) nParts;  // 部分数
lParam  =  (LPARAM) (LPINT) aWidths;     // 各部分宽度

aWidths 是一个长整型数组,在此要说明的是 32 位 C 编译器所用的 int 是 32 位的,而 Powerbuilder 中的 int 是 16 位,long 是 32 位,所以说 aWidths 是长整型的数组。

由上可知 aWidths 不能作为 Send( ) 的参数,只能用 SendMessageA( ) Win32 API 函数来实现,考虑函数的多态性,可以声明 Powersoft 原型为:

Function ULong SendMessageA(ULong hWnd,ULong Msg,UInt wParam,ref ULong lParam[]) Library "User32.DLL"

 需要注意的是 wParam 不可以被 Ref 修饰,lParam 的类型必须是 Ulong 或 Long,否则控件将视所发 SB_SETPARTS 为无效消息。

基于面向对象的封装原则,定义对象方法 SetParts( ) 为:

ctrl_status_bar.Function SetParts(Uint nParts, Ulong aWidths[]) returns Boolean
    
return  ( 0   <>  SendMessageA(Handle( this ),  1028 , nParts, aWidths))

其中,1028 是 SB_SETPARTS 消息的标识号。

在生成多部分的状态条后,我们需要实现类似 SetMicroHelp( ) 函数的功能,即修改状态条各部分的显示文本。对于第一部分往往只要修改用户对象的 Text 属性,就可修改它的文本;对于其他部分,我们可以通过发送 SB_SETTEXT 消息修改各部分的文本,当然第一部分也可以这样修改。但 SB_SETTEXT 消息的参数为:

wParam  =  (WPARAM) iPart  |  uType;  // 部分索引号 | 类型
lParam  =  (LPARAM) (LPSTR) szText;   // 待显示的文本

由于 lParam 是字符串,不能利用 Send( ) 和先前声明的 SendMessageA( ),但 Powerbuilder 支持多态性原则,所以可以再声明一个 SendMessageA( ) 函数。其 Powersoft 原型为:

Function ULong SendMessageA(ULong hWnd,ULong Msg,UInt wParam,String szText) Library "User32.DLL"

同样定义方法 SetText( ) 为:

ctrl_status_bar.Function SetText(Uint iPart, Uint uType, String szText) returns Boolean
    
return  ( 0   <>  SendMessageA(Handle( this ),  1025 , iPart  +  uType, szText))

其中,1025 是 SB_SETTEXT 消息的标识号,iPart 是基于 0 的索引值,iPart + uType 表示逻辑或,uType 的取值可以参考 MSDN Library 和 commctrl.h。

模式间的切换

状态条控件可以在 SB_SIMPLE 消息的控制下进行简单模式与多部分间的切换,定义方法 Simple( ) 为:

ctrl_status_bar.Function Simple(Boolean fSimple)
    
int  iSimple  =   0
    
if  fSimple then iSimple  =   1
    Send(Handle(
this ),  1033 , iSimple,  0 )

如果 fSimple = True,状态条切换为简单模式;反之亦然。

Owner-Drawn窗口部分

到目前为止所讨论的只限于在状态条上显示文本,那么如何绘制图形或显示不同字体的文本呢?我们可以通过定义指定的窗口部分为 Owner-Drawn 窗口部分来实现。为定义一个窗口部分为 Owner-Drawn 的,要发送 SB_SETTEXT 消息给状态条,并指定 iPart 为该窗口部分对应的值及 uType 设为 SBT_OWNERDRAW (4096)。此时参数 lParam 可以是一个字体句柄、位图句柄或字符串地址等。

当状态条需要绘制一个 Owner-Drawn 部分时,会发送 WM_DRAWITME 消息给父窗口。消息的 wParam 参数是状态条的控件标识号,lParam 参数是 DRAWITEMSTRUCT 结构的地址。父窗口利用该结构绘制 wParam 指定的窗口部分。但由于 pbm_drawitem 事件所传递的 lParam 参数是长整型的,所以我们不能直接利用该结构,只能通过状态条控件的句柄来间接获得结构成员所带的信息。

现举一在状态条的第二部分 (iPart = 1) 显示一个小图标的例子:

定义全局结构 strc_rect 为:

structure strc_rect
    Long left 
    Long top 
    Long right 
    Long bottom

依据多态性原则,定义 ctrl_status_bar 的方法 SetText( ) 为:

ctrl_status_bar.Function SetText(Uint iPart, Uint uType, ULong handle) returns Boolean
    
return  ( 0   <>  Send (Handle( this ),  1025 , iPart  +  uType, handle))

获取指定的窗口部分的坐标值,向状态条控件发送 SB_GETRECT 消息,同样是 lParam 参数类型的关系,需利用多态性声明 SendMessageA( ) 为:

Function Ulong SendMessageA(Ulong hWnd, Ulong Msg, Uint wParam,ref strc_rect lParam) Library "User32.DLL"

并定义 ctrl_status_bar 的方法 GetRect( ) 为:

ctrl_status_bar.Function GetRect(Uint iPart,  ref  strc_rect rc) returns boolean
    
return  ( 0   <>  SendMessageA(Handle( this ),  1034 , iPart, rc))

声明 w_frame 的 Local External Function 的 Powersoft 原型为:

Function ULong LoadImageA(Ulong hinst, String lpszName, UInt uType, int cxDesired, int cyDesired, UInt fuLoad) Library "User32.DLL"

Function Boolean DestroyIcon(ULong hIcon) Library "User32.DLL"

Function Int GetDlgCtrlID(Ulong hwndCtl) Library "User32.DLL"

Function ULong GetDC(ULong hWnd) Library "User32.DLL"

Function Int ReleaseDC(ULong hWnd,ULong hDC) Library "User32.DLL"

Function Boolean DrawIconEx(Ulong DC,int xLeft,int yTop,ULong Icon,int cxWidth,int cyWidth,UINT istepIfAniCur,ULong hbrFlickerFreeDraw,UINT diFlags) Library "User32.DLL"

声明 w_frame 的实例变量

Ulong  hIcon, hDC

定义 w_frame 的 Open 事件脚本为:

w_frame.Event Open( ) returns  long
    ULong aWidths[] 
=  { 350 ,  - 1 }
    ctrl_sbar.SetParts(
2 , aWidths)     // 显示 2个部分
    hDC  =  GetDC(Handle(ctrl_sbar))     // 获得 Device Context
    hIcon  =  LoadImageA( 0 ,  " .STATBAR.ICO " ,  1 ,  16 ,  16 ,  16 )     // 加载图标
    ctrl_sbar.SetText( 1 ,  4096 , hIcon)

定义 w_frame 的 Close 事件脚本为:

w_frame.Event Close( ) returns  long
    DestroyIcon(hIcon)
   ReleaseDC(Handle(ctrl_sbar), hDC)

定义 w_frame 的自定义事件 DrawItem 事件脚本为:

w_frame.Event DrawItem(Ulong ChildID, Long DrawItemStruct) returns  long  [pbm_drawitem]
    
if  childid <> GetDlgCtrlID(Handle(ctrl_sbar)) then  return       // 标识号是否一致
    ctrl_sbar.GetRect( 1 ,rc)     // 获得窗口部分的坐标值
    DrawIconEx(hDC, rc.Left, rc.Top, hIcon,  0 ,  16 ,  16 ,  0 ,  3 )     // 绘制图标

图4图4

图4 所示即为调试结果。

处理通知消息

如果单击状态条上的打印机图标能打开“打印队列管理器”,对最终用户来说是很有吸引力的。如何实现呢?理论上,当单击状态条时,状态条控件会向父窗口发送 WM_NOTIFY 消息,只要处理该消息即可;但实际上,状态条的 NM_CLICK、NM_DBLCLK、NM_RCLICK 和 NM_RDBLCLK 消息的 lParam 参数是 NMMOUSE 结构变量,很难处理,所以得用 ctrl_status_bar 的 WM_LBUTTONDOWN 消息来代替它。下面以 Clicked 事件为例加以说明:

首先定义 ctrl_status_bar 的 Clicked 事件为:

ctrl_status_bar.Event Clicked(Ulong flags,  int  xpos,  int  ypos) returns  long  [pbm_lbuttondown]

然后定义 ctrl_sbar 的 Clicked 事件脚本 (继承自 ctrl_status_bar) 为:

ctrl_sbar.Event Clicked(Ulong flags,  int  xpos,  int  ypos) returns  long
    strc_rect    rc
    GetRect(
1 , rc)
    
if  UnitsToPixels(xpos, XUnitsToPixels ! )  >=  rc.left  &
        and UnitsToPixels(xpos, XUnitsToPixels
! )  <=  rc.left  +   16   &
        and UnitsToPixels(ypos, YUnitsToPixels
! )  >=  rc.top  &
        and UnitsToPixels(ypos, YUnitsToPixels
! )  <=  rc.top  +   16  then
        MessageBox(
" Clicked " ,  " Event Triggered! " )
    end 
if

同理处理其他鼠标消息也是如此。

显示菜单的 MicroHelp 信息

使用 MDI with Help 类型窗口的 Powerbuilder 应用程序,在用户选择菜单项或对应的工具条图标时,会在状态条上显示菜单项的 MicroHelp 属性值。如图5 所示。但我们所使用的外部控件是无此功能的,不过我们可以利用 WM_MENUSELECT 消息来实现该功能。

图5图5

首先定义与菜单有关的 Local External Function 为:

Function ULong GetMenu(ULong hWnd) Library "User32.DLL"

Function ULong GetSubMenu(ULong hMenu,int nPos) Library "User32.DLL"

Function UINT GetMenuItemID(Ulong hMenu,int nPos) Library "User32.dll"

定义菜单 m_frame 的用户函数 GetMicroHelp 为:

m_frame.Function GetMicroHelp(Long hMenu, Uint ItemID) returns String
    
int  li_Count
    
int  li_SubCount

    
for  li_Count  =   1  to UpperBound(Item)
        
if  GetSubMenu(GetMenu(Handle(ParentWindow)), li_Count  -   1 )  =  hMenu then  // 判断 hMenu 是否是当前菜单的句柄
             for  li_SubCount  =   1  to UpperBound(Item[li_Count].Item)
                
if  GetMenuItemID(hMenu, li_SubCount  -   1 )  =  ItemID then  // 判别当前菜单项是否是所期望的菜单项
                     return  Item[li_Count].Item[li_SubCount].MicroHelp
                end 
if
            next    
        end 
if
    next

    
return  GetApplication().MicroHelpDefault  // 返回缺省的 MicroHelp

 定义窗口 w_frame 的自定义事件 MenuSelected 为: 

w_frame.Event MenuSelected(Uint ItemID, Uint Flags, Long hMenu) returns  long  [pbm_menuselect]
    ctrl_status_bar.Text 
=  m_frame.GetMicroHelp(hMenu,ItemID)

 这样就实现了所要求的 MicroHelp 功能。

PB中TreeView控件使用技巧 阅读详情

相关推荐

解决PB的mdi窗口添加控件不能显示窗口的问题

PBMDI窗口添加控件后,打开窗户后,会被主窗口控件覆盖,使得子窗口显示存在问题。很好的解决PB的mdi窗口添加控件不能显示窗口的问题(PB9.03和PB11.5都验证通过)

怎样在pb里实现无标题栏

api解决: SetWindowLong(Handle,                  // 当前窗体句柄                 GWL_STYLE,                // 表示当前是要设置新的窗体(普通)样式                 // 得到指定窗体信息                 GetWindowLong(Handle, GWL_STYLE)    ...

SSSU的专栏 482

3GPP Release与UE Category:无线通信标准演进与终端能力分级全解析

在蜂窝移动通信领域,技术标准的演进与终端设备的能力分级是理解整个产业发展的核心框架。其基本原理由国际标准组织3GPP通过周期性发布的技术规范版本(Release)来定义,每个Release都像一份阶段性的技术蓝图,规定了网络与终端应支持的新功能与性能基线。这种标准化机制的技术价值在于确保了全球设备的互联互通与网络的平滑升级,为从4G LTE到5G NR乃至未来的演进提供了清晰路径。在这一框架下,终端能力分级(如LTE时代的UE Category)是将标准转化为具体设备性能的关键环节,它直接定义了终端在射频和

weixin_34098209的博客 330

【PB】pb菜单详解和MDI

菜单条-MenuBar、菜单项-MenuItem、级联菜单(子菜单)-SubMenu 菜单项(MenuItem)是菜单中最基本的元素,只要有文字内容的就是菜单项。菜单条(MenuBar)是菜单中级别最高的菜单项的总称,也叫做菜单标题。菜单条的内容总是显示出来,对菜单的操作也是首先从这里开始的。在菜单条上移动鼠标或者点击其中的项目可以显示对应的内容,称为下拉菜单,包括很多的菜单项,它们大多数都执行

1万+

新手避坑指南:用镭神C32和KVH 1750 IMU做标定,为什么直接上lidar_align会失败?

本文详细解析了使用镭神C32激光雷达和KVH 1750 IMU进行标定时常见的失败原因及解决方案。从IMU的微分传感器特性到Lidar-IMU标定的数学本质,再到可行的标定方案和实操注意事项,帮助新手避开认知陷阱,掌握正确的标定方法。

weixin_30162121的博客 327

EV1527 vs HS1527:固定码芯片的STM32解码避坑指南

本文深入解析EV1527与HS1527固定码芯片的技术差异,提供基于STM32的完整解码方案与稳定性优化策略。通过硬件接口配置、状态机实现及示波器诊断,解决工业遥控、安防报警等场景中的解码难题,特别针对时序差异和干扰问题给出实用解决方案。

o0p1q2r3的博客 329

OLE控件注册修改工具:助PB开发者解决崩溃难题

OLE控件注册修改工具:助PB开发者解决崩溃难题 【下载地址】OLE控件注册修改工具 OLE控件注册修改工具专为PB(PowerBuilder)开发者打造,旨在解决开发过程中常见的OLE控件插入错误问题。长时间的系统使用和频繁的安装卸载可能导致DLL文件关联错误,进而引发程序崩溃。本工具通过检测COM组件状态,快速定位问...

gitblog_06771的博客 847

家庭网络中,路由器和交换机的连接顺序

它的目的是给路由器增加端口,用户访问互联网的速度比情况一要快,常用于办公网络、家庭成员多的场景。光纤入户首先连接的肯定是光猫,而在光猫的后面,是先连接交换机?还是应该接路由器呢?家庭网络中路由器和交换机的先后连接顺序。它目的是让更多的用户访问互联网。常用于一些超大型机房、网吧等。至于路由器和交换机的区别。两者之间很多功能都有兼容。但用户上网速度相对较慢。在技术日益迭代的今天。

m0_74075744的博客 1万+

pb TreeView控件

pb TreeView控件 PowerBuilder中的TreeView 控件为树状游览,类似于WINDOWS的资源管理器,其特点是信息项呈树状层次结构,能更清晰地表现主、细目关系 ,操作非常方便。在应用中可将其与DataWindow 配合使用, 一个提供信息的分类体系,一个提供具体信息,达到珠连碧合的奇妙效果。它特别适用于多级信息的分类检索, 是多级菜单所无法比似的,它的表现形式深受程序设

sunfor的专栏 2406

Transformer论文解读

Transformer有多牛逼不用多说,时隔7年我们再来看看论文原文,看看这篇深刻改变世界的文章都说了什么。当然逐字逐句解读已经意义不大,我们只列考点。

xian0710830114的专栏 4405

EtherCAT FOE从站开发实战:SSC工具包实现固件在线升级与文件传输

EtherCAT从站开发中,固件在线升级与文件传输是常见需求。FOE(File Access over EtherCAT)作为邮箱通信协议,在实时总线上提供可靠的文件读写通道,与PDO、DC同步共存。其原理基于SM邮箱和状态机,通过SSC工具包可快速启用。技术价值在于无需拆机即可更新固件、导出日志,提升产线效率。应用场景包括伺服驱动器、IO模块等从站的固件升级与参数配置。本文深入讲解从站侧FOE读写实现、主站调用及工程化建议,助力嵌入式工程师高效开发。

weixin_29169899的博客 127

pb串口编程

powerbuilder串口编程的实现 因公司软件产品需要和POS机进行通信,所以笔者研究了一下PB串口编程的实现方式。   PB是一个非常好的数据库管理系统的开发工具,但在web和计算机接口通信等方面PB就不是很好用了。幸好我们有ole和com这些很牛的技术,可以让我们非常容易的使用一些组件的功能,而不用自己去开发去关心底层的业务逻辑。使用PB进行串口编程有两种途径,一种是使用微软提...

深未来技术 544

C#串口通信从入门到精通(21)——一个串口多线程发送数据

本文详细介绍了串口通信中采用多线程发送串口数据的解决方案,由多年实战经验总结,绝对干货!

qq_34059233的博客 3688

PB中自定义事件ID含义

单选或多选按钮消息(前缀:pbm_bm) pbm_bmgetcheck 单选按钮或多选按钮是否被选。 pbm_bmgetstate 按钮是否加亮。 pbm_bmsetcheck 将无线按钮或确认框的选中状态改为未选中状态,反之亦然。 pbm_bmsetstate 加亮或不加亮按钮。 pbm_bmchange 改变按钮的风格,例如,改为单选按钮或组合框。 单选或多选按钮通知消息(前缀:pbm_bn)

键者天行 8170

【数据集】中国陆地生态系统通量观测网 ChinaFLUX

【数据集】中国陆地生态系统通量观测网 ChinaFLUX

WW、forever的博客 187

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

上一篇: 【PB】调用 Win32 公共控件的改进方案
下一篇: 【PB】也谈数据窗口自动换行
keyssoft
博客等级 码龄25年 8粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值