“为应用程序在任务栏通知区域加个图标,按最小化控制菜单后隐藏窗口,单击通知区域内的图标恢复并显示窗口,右击通知区域内的图标弹出快捷方式菜单”,已成为时下程序设计上的一个时髦主题,有不少文章介绍了如何实现,但在 PowerBuilder 下由于调用 Win32 API 函数和消息处理不很方便,因而很少有人去涉及。本文将讨论如何在 PowerBuilder 下使用任务栏通知区域。
1.相关的 Win32 API 函数
Win32 API 函数 Shell_NotifyIconA 是本文所涉 Win32 API 函数中最为关键者,通过它可以添删通知区域图标,其 Powersoft 原型为:
Function Boolean Shell_NotifyIconA(ULong dwMessage,stc_notifyicondata pnid) Library "Shell32.dll"
其中 stc_notifyicondata 是一个结构,其成员有:
Ulong cbSize // 结构大小为 88 字节
Ulong hWnd // 接受通知消息的窗口句柄
Ulong uID // 通知区域图标的标识号
Ulong uFlags // 指示哪些成员是有效的
Ulong uCallbackMessage // 通知消息的标识号
Ulong hIcon // 图标的句柄
Char szTip[64] // 图标提示
Ulong dwState // 图标状态 (IE5)
Ulong dwStateMask // 状态掩码 (IE5)
Char szInfo[256] // balloon tooltip (IE5)
Ulong uTimeout // balloon tooltip 显示时间 (IE5)
Char szInfoTitle[64] // balloon tooltip 标题 (IE5)
Ulong dwInfoFlags // balloon tooltip 标志 (IE5)
uFlags 可以是 NIF_MESSAGE(1)、NIF_ICON(2)、NIF_TIP(4)、NIF_STATE(8) 和 NIF_INFO(16) 的组合。如 uFlags = 7 表示结构的 uCallbackMessage、hIcon 和 szTip 是有效的,其他的一些成员的值将被忽略。
由于此处涉及回调消息和图标,所以要用到另三个 Win32 API 函数,他们的 Powersoft 原型为:
Function UINT RegisterWindowMessageA(String lpString) Library "User32.dll"
Function ULong LoadIconA(ULong hInstance,ULong lpIconName) Library "User32.dll"
Function Boolean DestroyIcon(ULong hIcon) Library "User32.dll"
函数 RegisterWindowMessageA 用来定义一个唯一的窗口消息,他的返回值被赋给 uCallbackMessage;函数 LoadIconA 用来加载一个图标,由于此处要加载 OEM 图标,所以声明 lpIconName 的类型为 Ulong 而不是String;函数 DestroyIcon 释放图标所占内存。
2.添删通知区域图标
为了便于演示,笔者将在 w_main 的 Open 事件中添加通知区域图标,在 Close 事件中删除状态区图标,最小化 w_main 时隐藏 w_main,单击通知区域内的图标时恢复并显示 w_main,右击通知区域内的图标时显示快捷方式菜单,即在整个程序运行过程中通知区域的图标始终存在。
笔者先声明一个实例变量:
stc_notifyicondata istc_nid
添加通知区域图标
定义窗口 w_main 的 Open 事件脚本为:
w_main.Event Open( ) returns long
istc_nid.cbSize = 88 // 结构大小
istc_nid.hWnd = Handle(this) // w_main 句柄
istc_nid.uFlags = 7 // uCallbackMessage、hIcon 和 szTip 有效
istc_nid.uID = 0 // 通知区域图标的标识号
istc_nid.uCallbackMessage = RegisterWindowMessageA("Demo") // 定义消息
istc_nid.hIcon = LoadIconA(0, 32517) // 加载 Windows Logo 图标
istc_nid.szTip = "Demostration Application" // 提示
Shell_NotifyIconA(0, istc_nid) // 添加图标
删除通知区域图标
定义窗口 w_main 的 Close 事件脚本为:
w_main.Event Close( ) returns long
Shell_NotifyIconA(2, istc_nid) // 删除通知区域图标
DestroyIcon(istc_nid.hIcon) // 释放内存
最小化窗口时隐藏窗口
定义窗口 w_main 的 Resize 事件脚本为:
w_main.Event Resize( ) returns long
if SizeType = 1 then Hide()
3.处理通知消息
当用户在通知区域内的图标上移动鼠标、单击、双击或右击时,Shell 会用 uCallbackMessage 所指示的标识号向 hWnd 指定的窗口发送通知消息。一般来说通知消息的参数 lparam 是个指向结构的指针,不过幸好如果我们象示例一样只用到较早版本 Shell 的行为的话,lparam 就只是个鼠标事件的标识号而已。处理这样的消息只要用 w_main 窗口的 Other 事件即可,可定义脚本为:
w_main.Event Other(Ulong wParam, Long lParam ) returns long
// 参数 wParam 指示对应的通知区域图标的标识号;
// 参数 lParam 指示对应的消息类型(消息标识号)。
if Message.Number = istc_nid.uCallbackMessage and wParam = istc_nid.uID then // 判断消息是否是待处理的消息
choose case lParam
case 512 // 鼠标移动
case 513 // 单击
Show()
WindowState=Normal!
case 515 //双击
case 516 //右击
ShowSCMenu()
end choose
end if