作者:BALLOONMAN2002 2004年6月26日
本文拟结合POWERBUILDER语言,简述如何实现树型列表动态半透明提示,即鼠标移动到树型列表某一项ITEM时会动态提示,且为类似金山词霸的半透明提示效果。
效果图见:
http://blog.csdn.net/images/blog_csdn_net/balloonman2002/17312/r_BALLOON-1.JPG
本文拟分以下四部分论述分三次完成:
(一)基本思路
(二)如何获取当前鼠标坐标对应NODE结点信息
(三)半透明效果实现
(四)气泡形状效果实现
一、基本思路
(一)在POWERBUILDER语言中,TREEVIEW控件并不具备如VB等其他语言一样当鼠标未选中NODE时,直接获取当前鼠标对应X、Y坐标下所属NODE结点的方法,VB中可以直接利用HITTEST方法来获取对当前鼠标坐标对应的NODE结点。但可以通过调用API:SENDMESSAGE函数来向TREEVIEW控件发送一个TVM_HITTEST消息来间接实现上述效果。
(二)在POWERBUILDER语言中,并没有直接让控件实现半透明的方法,而目前WINDOWS2000/XP操作系统提供了一个API函数:SetLayeredWindowAttributes,但该API函数不支持WINDOWS98操作系统,考虑到系统的全面兼容性,必须同时考虑WINDOWS98下面应该如何实现半透明提示效果。因此我们必须放弃采用上述API,而采用模拟半透明的方式,即:处理WINDOW的MOUSEMOVE事件,当鼠标移动到某一位置后将鼠标附近区域用API函数BitBlt、AlphaBlend截图下来,并拷贝到气泡提示控件背景设备即可模拟实现半透明效果。
(三)如何实现微软的气泡形状控件?由于POWERBUILDER对一些控件支持并不好,而且此类控件难以寻找,我们就考虑自己动手编写。主要借助API函数:CreateRectRgn、CreateRoundRectRgn、CreatePolygonRgn、CombineRgn等。
二、如何获取当前鼠标坐标对应NODE结点信息
1、新建一窗口,内含一TREEVIEW控件;
2、声明本地外部函数:
Function ulong SendMessage1(ulong hwnd,ulong wMsg,ulong wParam,ref TVHITTESTINFO lParam) LIBRARY "user32.dll" ALIAS FOR "SendMessageA"
Function ulong SendMessage2(ulong hwnd,ulong wMsg,ulong wParam,ref TVITEM lParam) LIBRARY "user32.dll" ALIAS FOR "SendMessageA"
SUBROUTINE CopyMemory (ref string Destination , long Source, long Length) LIBRARY "kernel32" Alias for "RtlMoveMemory"
Function ulong GlobalFree(ulong hMem) LIBRARY "kernel32.dll"
Function ulong GlobalAlloc(ulong wFlags,ulong dwBytes) LIBRARY "kernel32.dll"注:上述API声明涉及到的结构请查阅MSDN或其他技术资料。
3、对于该TREEVIEW控件自定义用户事件UE_MOUSEMOVE(PBM_MOUSEMOVE),在此事件当中处理鼠标移动事件,发送TVM_HITTEST消息:
tpoint ptA
tvhittestinfo tf
TVITEM tv
ulong hItem,ll_1,ll_2,ll_3,hStr
long ret,ll_x,ll_y
string astr,bstr,ls_help
ptA.x = UnitsToPixels(xpos, XUnitsToPixels!)
ptA.y = UnitsToPixels(ypos, YUnitsToPixels!)
tf.pt = ptA
tf.flags = 4
hItem = SendMessage1(handle(tv_1),4369,0,tf)
//注:上述4369为TVM_HITTEST
//通过发送TVM_HITTEST消息来获取当前对应的NODE的句柄,,将当前NODE结点信息保存到结构变量 TF当中
If ((hItem <= 0) Or (hItem = hItemPrv)) Then return
hItemPrv = hItem
hStr = GlobalAlloc(0,1024)
If hStr > 0 Then
tv.mask = 1
tv.HTreeItem = hItem
tv.pszText = hStr
tv.cchTextMax = 1023
ret = SendMessage2(handle(tv_1), 4364, 0, tv)
//注:上述4364为TVM_GETITEM