数据库

img balloonman2002

浅谈如何利用PB实现树型列表动态半透明提示(原创)

发表于2004/6/28 17:35:00  5277人阅读

分类: PowerBuilder专题

作者: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

//通过对当前NODE发送TVM_GETITEM消息,将当前NODE结点信息保存到结构变量 TV当中

    astr = space(1024)

//注:此处一定要分配足够空间,否则易非法操作

    CopyMemory(astr, hStr, 1024)

    //bstr = Left(astr, (pos(astr, Char(0)) - 1))

    ret = GlobalFree(hStr)

    ids_ds.setfilter("")

    ids_ds.filter()

    ret = ids_ds.find("name_gn = '" + astr + "'",1,ids_ds.rowcount())

    if ret > 0 then

        ls_help = ids_ds.getitemstring(ret,"help")

        if (isnull(ls_help) or trim(ls_help) = "")  then

            timer(0)

            iuo_tips.hide()

        else

            if is_help = ls_help then

                return

            end if

            iuo_tips.hide()

            iuo_tips.uf_set_text(ls_help,astr)

            ib_tipshow = false

            Timer(1)

        end if

        is_help = ls_help

    else

        timer(0)

        iuo_tips.hide()

    end if

else

    timer(0)

    iuo_tips.hide()

end if

三、半透明效果实现

1、创建一个可视USER OBJECT对象,并在主窗口中创建该UO的实例变量。

2、声明本地外部函数:

Function ulong GetDC(ulong hwnd) LIBRARY "user32.dll"

Function ulong BitBlt(ulong hDestDC,ulong x,ulong y,ulong nWidth,ulong nHeight,ulong hSrcDC,ulong xSrc,ulong ySrc,ulong dwRop) LIBRARY "gdi32.dll"

Function ulong ReleaseDC(ulong hwnd,ulong hdc) LIBRARY "user32.dll"

Function ulong CreateCompatibleDC(ulong hdc) LIBRARY "gdi32.dll"

Function ulong CreateCompatibleBitmap(ulong hdc,ulong nWidth,ulong nHeight) LIBRARY "gdi32.dll"

SUBROUTINE Sleep(ulong dwMilliseconds) LIBRARY "kernel32.dll"

Function ulong SelectObject(ulong hdc,ulong hObject) LIBRARY "gdi32.dll"

Function ulong AlphaBlend(long hDestDC , long X, long Y , long nWidth , long nHeight, long hSrcDC,long xSrc,long ySrc, long WidthSrc, long HeightSrc ,long dreamAKA ) LIBRARY "msimg32"

Function ulong DeleteDC(ulong hdc) LIBRARY "gdi32.dll"

Function ulong GetSystemMetrics(ulong nIndex) LIBRARY "user32.dll"

SUBROUTINE  CopyMemory2  (ref long Destination , blendfunction Source, long Length)  LIBRARY "kernel32"  Alias for "RtlMoveMemory"

Function ulong DeleteObject(ulong hObject) LIBRARY "gdi32.dll"

3、处理主窗口的TIMER事件,用于定期触发提示信息:

long ll_x,ll_y

if ii_tip > 0 then

    if ib_tipshow then

        ib_tipshow = false

        iuo_tips.hide()

        timer(0)

    else

        ib_tipshow = true

   

        ll_x = w_main.pointerx() + 50

        ll_y = w_main.pointery()  - iuo_tips.height - 5

       

        if ll_y < 2 then

            ll_y = 2

        end if

   

        //wf_maketrans(iuo_tips,iuo_tips.mle_1,il_x,il_y,50)

        wf_maketrans(iuo_tips,iuo_tips.mle_1,ll_x,ll_y,40)

//上述函数是用于实现半透明效果的函数

        timer(6)

    end if

end if

4、创建用户函数wf_maketrans,用于实现半透明效果:

Long hDCscr,bhandle,hdest,frmdc,BlendLng,copywidth,copyheight,copyleft,copytop,ret

long copywidth2,copyheight2,copyleft2,copytop2,mledc

Long xDeviation,yDeviation

blendfunction Blend

Window lw_tmp

 

//BlendLng = 11796480

Blend.SourceConstantAlpha = char(trans)

CopyMemory2(BlendLng, Blend, 4)

 

lw_tmp=frm.getparent()

//lw_tmp.setredraw(true)

copywidth = UnitsToPixels(frm.Width, XUnitsToPixels!)

copyheight = UnitsToPixels(frm.Height, YUnitsToPixels!)

copywidth2 = UnitsToPixels(mle.Width, XUnitsToPixels!)

copyheight2 = UnitsToPixels(mle.Height, YUnitsToPixels!)

//上述代码用于坐标体系转换

 

frm.x = xpos

frm.y = ypos

 

If lw_tmp.Border <> false Then

    yDeviation = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME)

    xDeviation = GetSystemMetrics(SM_CXFRAME)

Else

    yDeviation = 0

    xDeviation = 0

End If

 

if trim(lw_tmp.menuname) <> "" then

    yDeviation = yDeviation + GetSystemMetrics(SM_CYMENU)

end if

 

//也可以用CLIENTTOSCREEN进行转换

copyleft = UnitsToPixels((lw_tmp.x + xpos), XUnitsToPixels!) + xDeviation

copytop = UnitsToPixels((lw_tmp.y + ypos), YUnitsToPixels!) + yDeviation

copyleft2 = UnitsToPixels(mle.x, XUnitsToPixels!)

copytop2 = UnitsToPixels(mle.y, YUnitsToPixels!)

//上述代码用于坐标体系转换

 

hDCscr = GetDC(0)

//获取屏幕的设备句柄

hdest = CreateCompatibleDC(hDCscr)

bhandle = CreateCompatibleBitmap(hDCscr, copywidth, copyheight)

ret = SelectObject(hdest,bhandle)

frmdc = getdc(handle(frm))

mledc = getdc(handle(mle))

 

//此句可加可不加,主要是起清除原来图象目的,防止图象重叠,VB中此处必须要.cls,因为它具有AUTOREDRAW能力

//frm.setredraw(true)

//mle.setredraw(true)

 

//'此处一定要等待一段时间,否则窗体来不及hide,就已经被重新抓屏了

Sleep(100)

 

ret = BitBlt(hdest, 0, 0, copywidth, copyheight, hDCscr, copyleft , copytop , 13369376)

//上述代码即将屏幕的截图拷贝到内存缓存区域

 

//VB中FORM具有AUTOREDRAW的属性可以自动重画,PB无此能力,只好在此处就得显示出来

if ib_first then

    wf_setrgn(frm)

end if

frm.Visible = True

if ib_first then

    wf_setrgn(frm)

    ib_first = false

end if

ret = AlphaBlend(frmdc, 0, 0, copywidth, copyheight, hdest, 0, 0, copywidth, copyheight, BlendLng)

ret = AlphaBlend(mledc, 0, 0, copywidth2, copyheight2, hdest, copyleft2 , copytop2, copywidth2, copyheight2, BlendLng)

//上述代码将内存缓存区域中的截图拷贝到气泡UO和其上的MLE_1控件的HDC

 

//setnewrgn frm

wf_setrgn(frm)

 

ret = ReleaseDC(0, hDCscr)

ret = ReleaseDC(handle(frm), frmdc)

ret = ReleaseDC(handle(mle), mledc)

ret = DeleteDC(hdest)

ret = DeleteObject(bhandle)

//最后释放或删除获取的内存对象

四、气泡形状效果实现

1、声明本地外部函数:

Function ulong CreateRectRgn(ulong X1,ulong Y1,ulong X2,ulong Y2) LIBRARY "gdi32.dll"

Function ulong CreateRoundRectRgn(ulong X1,ulong Y1,ulong X2,ulong Y2,ulong X3,ulong Y3) LIBRARY "gdi32.dll"

Function ulong CreatePolygonRgn(ref POINTAPI lpPoint[],ulong nCount,ulong nPolyFillMode) LIBRARY "gdi32.dll"

Function ulong CombineRgn(ulong hDestRgn,ulong hSrcRgn1,ulong hSrcRgn2,ulong nCombineMode) LIBRARY "gdi32.dll"

Function ulong CreateSolidBrush(ulong crColor) LIBRARY "gdi32.dll"

Function ulong FrameRgn(ulong hdc,ulong hRgn,ulong hBrush,ulong nWidth,ulong nHeight) LIBRARY "gdi32.dll"

Function ulong SetWindowRgn(ulong hWnd,ulong hRgn,boolean bRedraw) LIBRARY "user32.dll"

2、创建用户函数wf_setrgn,用于创建气泡形状控件,该函数在上一小节的用户函数wf_maketrans中予以调用:

long rgn_1,rgn_2,myrgn,hhbr,w,h,ret

POINTAPI shapev[]

   

    //初始化长、宽边距

    w = UnitsToPixels(frm.Width, XUnitsToPixels!)

    h = UnitsToPixels(frm.Height, YUnitsToPixels!)

   

    //初始化右下脚三角顶点坐标

    shapev[1].X = w * (1 / 8)

    shapev[1].Y = h - 30

    shapev[2].X = 0

    shapev[2].Y = h

    shapev[3].X = w * (3 / 8)

    shapev[3].Y = h - 30

     

    //开始创建指定图形区域

    myrgn = CreateRectRgn(0, 0, 0, 0)

    rgn_1 = CreateRoundRectRgn(0, 0, w, h - 20, 20, 20)

//创建椭圆角矩形区域

    rgn_2 = CreatePolygonRgn(shapev[],3,1)

    //创建任意多边形区域

 

    //合并最终图形

    ret = CombineRgn(myrgn, rgn_1, rgn_2, 2)

   

    // 创建用户自定义颜色刷子

    hhbr = CreateSolidBrush(16479614)

//对最终图形画边框

    ret = FrameRgn(getdc(handle(frm)), myrgn, hhbr, 1, 1)

   

    //设置当前窗体使用此区域

    ret = SetWindowRgn(handle(frm), myrgn, True)

     

    //释放各对象

    ret = DeleteObject(myrgn)

    ret = DeleteObject(rgn_1)

    ret = DeleteObject(rgn_2)

    ret = DeleteObject(hhbr)

2、利用上述代码可以轻松实现任务栏右下脚提示效果,如图:

http://blog.csdn.net/images/blog_csdn_net/balloonman2002/17312/r_BALLOON-2.JPG

 

至此,树型列表动态半透明效果提示全部完成,效果图见:

http://blog.csdn.net/images/blog_csdn_net/balloonman2002/17312/r_BALLOON-1.JPG

如需要进一步资料,请联系QQ:27855043,MSN:WEIYIN2001@MSN.COM

如有不当之处,敬盼您的指点。

阅读全文
0 0

相关文章推荐

img
取 消
img