Posted: 22nd Sep 2014 7:20
I was just looking through a bunch of old DBP code and I found this nice little library. It allows you to designate any rectangular or circular area of the screen to pop up a tooltip when the mouse is hovered over it for a small amount of time. Useful for providing information about buttons or other UI elements.

I don't think I ever did anything with it, but it seems fully functional, so I thought I'd share.

Library:
+ Code Snippet
remstart
`Mouseover Tip functions

`by BMacZero

`Use and modify as you wish!

These functions basically allow you to produce mouseover tips (the windows and
help descriptions you get when you hold your mouse over something for a while)
in your programs.

You create different zones - areas that will trigger a tip window - and just call
ZM_UpdateTips() every loop and the tips will appear, disappear, and generally take
care of themselves for you.

-----------------------------------------------------------------------------------
Functions : Summary List

ZM_InitiateMouseTips(AlphaSpeed,OverTimeReq)
    This command sets up the mouse tip functions.
    AlphaSpeed tells how fast the tip windows will fade in and out.
    OverTimeReq is how many milliseconds the user must hold the mouse still to display a tip.

ZM_EndMouseTips()
    This entirely clears the mouse tip arrays and resources.

ID = ZM_MakeTipZone_Box(X1,Y1,X2,Y2,String$,Font$,FontSize,FontColor as dword,BoxColor as dword)
    This will create a box-shaped tip zone.
    ID is an identification number for the tip that you will need if you want to delete it later.
    The top-left corner is at X1,Y1 and the bottom-right is at X2,Y2.
    String$ is the text that will be displayed in the tip window.
    Font$ and FontSize - Guess ;)
    FontColor - The color of both the text and the border of the tip window for this zone.
    BoxColor - The background color of the tip window.

ID = ZM_MakeTipZone_Circle(X,Y,R,String$,Font$,FontSize,FontColor as dword,BoxColor as dword)
    This will create a circle-shaped tip zone.
    ID is an identification number for the tip that you will need if you want to delete it later.
    It will be centered at X,Y and have a radius of R.
    The other properties are the same as for box zones.

ZM_DeleteTipZone(ID)
    This deletes the specified tip zone and its resources.
    ID is the ID returned when the zone was created.

ZM_UpdateTips()
    Call each loop - this automatically updates, shows, hides, and otherwise takes
    care of the tip windows.

The other functions simply support the above ones.    

remend



type ZM_BoxZone
    ImageNo as integer
    SpriteNo as integer
    X1 as integer
    Y1 as integer
    X2 as integer
    Y2 as integer
    OverTime as integer
    FadeState as byte
endtype

type ZM_CircleZone
    ImageNo as integer
    SpriteNo as integer
    X as integer
    Y as integer
    r as integer
    OverTime as integer
    FadeState as byte
endtype

type ZM_GlobalIndex
    ZoneType as byte
    ZoneID as integer
endtype



`===================================================================================
`================ ZM_InitiateMouseTips() ===========================================

`Sets up the mouse tip functions.
`   AlphaSpeed is how fast the tips fade in and out
`   OverTimeReq is how long the mouse must be held to activate the tip


function ZM_InitiateMouseTips(AlphaSpeed,OverTimeReq)

`FadeStates:
`0=Hidden
`1=Fade In
`2=Solid
`3=Fade Out

global ZM_AlphaSpeed as integer
ZM_AlphaSpeed=AlphaSpeed
global ZM_OverTime as integer
ZM_OverTime=OverTimeReq

global ZM_OldMouseX as integer
global ZM_OldMouseY as integer

global DIM ZM_BoxZones(0) as ZM_BoxZone
global DIM ZM_CircleZones(0) as ZM_CircleZone
global DIM ZM_GlobalIndex(0) as ZM_GlobalIndex

endfunction


`===================================================================================
`================ ZM_EndMouseTips() ================================================

`Clears all resources used by the mouse tips


function ZM_EndMouseTips()

for c=1 to array count(ZM_BoxZones(0))
    if image exist(ZM_BoxZones(c).ImageNo) then delete image ZM_BoxZones(c).ImageNo
    if sprite exist(ZM_BoxZones(c).SpriteNo) then delete sprite ZM_BoxZones(c).SpriteNo
next c
for c=1 to array count(ZM_CircleZones(0))
    if image exist(ZM_CircleZones(c).ImageNo) then delete image ZM_CircleZones(c).ImageNo
    if sprite exist(ZM_CircleZones(c).SpriteNo) then delete sprite ZM_CircleZones(c).SpriteNo
next c

UNDIM ZM_BoxZones(0)
UNDIM ZM_CircleZones(0)
UNDIM ZM_GlobalIndex(0)

endfunction


`===================================================================================
`================ ZM_MakeTipZone_Box() =============================================

`Creates a box-shaped tip zone


function ZM_MakeTipZone_Box(X1,Y1,X2,Y2,String$,Font$,FontSize,FontColor as dword,BoxColor as dword)

array insert at bottom ZM_BoxZones(0)
zmtemp=array count(ZM_BoxZones(0))

array insert at bottom ZM_GlobalIndex(0)
zmtemp2=array count(ZM_GlobalIndex(0))
ZM_GlobalIndex(zmtemp2).ZoneType=1
ZM_GlobalIndex(zmtemp2).ZoneID=zmtemp

ZM_BoxZones(zmtemp).SpriteNo=ZM_FreeSprite()
ZM_BoxZones(zmtemp).ImageNo=ZM_FreeImage()

ZM_BoxZones(zmtemp).X1=X1
ZM_BoxZones(zmtemp).Y1=Y1
ZM_BoxZones(zmtemp).X2=X2
ZM_BoxZones(zmtemp).Y2=Y2

ZM_DrawTextImage(ZM_BoxZones(zmtemp).ImageNo,String$,Font$,FontSize,FontColor,BoxColor)

sprite ZM_BoxZones(zmtemp).SpriteNo,0,0,ZM_BoxZones(zmtemp).ImageNo
set sprite alpha ZM_BoxZones(zmtemp).SpriteNo,0
set sprite priority ZM_BoxZones(zmtemp).SpriteNo,30

endfunction zmtemp2

`===================================================================================
`================ ZM_MakeTipZone_Circle() ==========================================

`Creates a circle-shaped tip zone


function ZM_MakeTipZone_Circle(X,Y,R,String$,Font$,FontSize,FontColor as dword,BoxColor as dword)

array insert at bottom ZM_CircleZones(0)
zmtemp=array count(ZM_CircleZones(0))

array insert at bottom ZM_GlobalIndex(0)
zmtemp2=array count(ZM_GlobalIndex(0))
ZM_GlobalIndex(zmtemp2).ZoneType=2
ZM_GlobalIndex(zmtemp2).ZoneID=zmtemp

ZM_CircleZones(zmtemp).SpriteNo=ZM_FreeSprite()
ZM_CircleZones(zmtemp).ImageNo=ZM_FreeImage()

ZM_CircleZones(zmtemp).X=X
ZM_CircleZones(zmtemp).Y=Y
ZM_CircleZones(zmtemp).R=R

ZM_DrawTextImage(ZM_CircleZones(zmtemp).ImageNo,String$,Font$,FontSize,FontColor,BoxColor)

sprite ZM_CircleZones(zmtemp).SpriteNo,0,0,ZM_CircleZones(zmtemp).ImageNo
set sprite alpha ZM_CircleZones(zmtemp).SpriteNo,0
set sprite priority ZM_CircleZones(zmtemp).SpriteNo,30

endfunction zmtemp2


`===================================================================================
`================ ZM_DeleteTipZone(ID) =============================================

`Removes a tip zone


function ZM_DeleteTipZone(ID)

temp=ZM_GlobalIndex(ID).ZoneID
select ZM_GlobalIndex(ID).ZoneType
    case 1
        delete image ZM_BoxZones(temp).ImageNo
        delete sprite ZM_BoxZones(temp).SpriteNo
        array delete element ZM_BoxZones(0),temp
        for c=1 to array count(ZM_GlobalIndex(0))
            if ZM_GlobalIndex(c).ZoneType=1 and ZM_GlobalIndex(c).ZoneID>temp
                dec ZM_GlobalIndex(c).ZoneID
            endif
        next c
    endcase
    case 2
        delete image ZM_CircleZones(temp).ImageNo
        delete sprite ZM_CircleZones(temp).SpriteNo
        array delete element ZM_CircleZones(0),temp
        for c=1 to array count(ZM_GlobalIndex(0))
            if ZM_GlobalIndex(c).ZoneType=2 and ZM_GlobalIndex(c).ZoneID>temp
                dec ZM_GlobalIndex(c).ZoneID
            endif
        next c
    endcase
endselect

array delete element ZM_GlobalIndex(0),ID

endfunction

`===================================================================================
`================ ZM_UpdateTips() ==================================================

`Call every loop


function ZM_UpdateTips()

if ZM_OldMouseX<>mousex() or ZM_OldMouseY<>mousey() or mouseclick()>0 then zm_moved=1

for c=1 to array count(ZM_BoxZones(0))
    if ZM_MouseInBox(ZM_BoxZones(c).X1,ZM_BoxZones(c).Y1,ZM_BoxZones(c).X2,ZM_BoxZones(c).Y2) and zm_moved=0 and (ZM_BoxZones(c).FadeState=0 or ZM_BoxZones(c).FadeState=3)
        if ZM_BoxZones(c).OverTime=0
            ZM_BoxZones(c).OverTime=timer()
            else
            if timer()-ZM_BoxZones(c).OverTime>=ZM_OverTime then ZM_BoxZones(c).FadeState=1
        endif
    endif
    if zm_moved=1
        if ZM_BoxZones(c).FadeState=1 or ZM_BoxZones(c).FadeState=2 then ZM_BoxZones(c).FadeState=3
        ZM_BoxZones(c).OverTime=0
    endif
    if ZM_BoxZones(c).FadeState=1
        temp=sprite alpha(ZM_BoxZones(c).SpriteNo)+ZM_AlphaSpeed
        if temp>255 then temp=255 : ZM_BoxZones(c).FadeState=2
        set sprite alpha ZM_BoxZones(c).SpriteNo,temp
    endif
    if ZM_BoxZones(c).FadeState=3
        temp=sprite alpha(ZM_BoxZones(c).SpriteNo)-ZM_AlphaSpeed
        if temp<0 then temp=0 : ZM_BoxZones(c).FadeState=0
        set sprite alpha ZM_BoxZones(c).SpriteNo,temp
    endif
    if ZM_BoxZones(c).FadeState=0 then sprite ZM_BoxZones(c).SpriteNo,mousex(),mousey()+16,ZM_BoxZones(c).ImageNo
next c

for c=1 to array count(ZM_CircleZones(0))
    if ZM_MouseInCircle(ZM_CircleZones(c).X,ZM_CircleZones(c).Y,ZM_CircleZones(c).R) and zm_moved=0 and (ZM_CircleZones(c).FadeState=0 or ZM_CircleZones(c).FadeState=3)
        if ZM_CircleZones(c).OverTime=0
            ZM_CircleZones(c).OverTime=timer()
            else
            if timer()-ZM_CircleZones(c).OverTime>=ZM_OverTime then ZM_CircleZones(c).FadeState=1
        endif
    endif
    if zm_moved=1
        if ZM_CircleZones(c).FadeState=1 or ZM_CircleZones(c).FadeState=2 then ZM_CircleZones(c).FadeState=3
        ZM_CircleZones(c).OverTime=0
    endif
    if ZM_CircleZones(c).FadeState=1
        temp=sprite alpha(ZM_CircleZones(c).SpriteNo)+ZM_AlphaSpeed
        if temp>255 then temp=255 : ZM_CircleZones(c).FadeState=2
        set sprite alpha ZM_CircleZones(c).SpriteNo,temp
    endif
    if ZM_CircleZones(c).FadeState=3
        temp=sprite alpha(ZM_CircleZones(c).SpriteNo)-ZM_AlphaSpeed
        if temp<0 then temp=0 : ZM_CircleZones(c).FadeState=0
        set sprite alpha ZM_CircleZones(c).SpriteNo,temp
    endif
    if ZM_CircleZones(c).FadeState=0 then sprite ZM_CircleZones(c).SpriteNo,mousex(),mousey()+16,ZM_CircleZones(c).ImageNo
next c

zm_moved=0
ZM_OldMouseX=mousex()
ZM_OldMouseY=mousey()

endfunction

`===================================================================================
`================ AUXILIARY FUNCTIONS ===============================================


function ZM_DrawTextImage(ImageNo,strg$,fnt$,fntsize,fntcolor as dword,bxcolor as dword)

oldfont$=text font$()
oldsize=text size()

set text font fnt$
set text size fntsize

temp=ZM_FreeBMP()

create bitmap temp,text width(strg$)+10,text height(strg$)+10
set current bitmap temp
cls bxcolor
ink fntcolor,0

text 5,5,strg$

ZM_HollowBox(0,0,bitmap width(temp)-1,bitmap height(temp)-1)

get image ImageNo,0,0,bitmap width(temp),bitmap height(temp),1

delete bitmap temp
set current bitmap 0

set text font oldfont$
set text size oldsize

endfunction


function ZM_MouseInBox(X1,Y1,X2,Y2)

temp=0
if mousex()>=X1 and mousex()<=X2 and mousey()>=Y1 and mousey()<=Y2 then temp=1

endfunction temp


function ZM_MouseInCircle(X,Y,R)

temp=0
tempno=(mousex()-X)*(mousex()-X)+(mousey()-Y)*(mousey()-Y)
if tempno<=R*R then temp=1

endfunction temp


function ZM_HollowBox(X1,Y1,X2,Y2)

line X1,Y1,X2+1,Y1
line X1,Y1,X1,Y2+1
line X2,Y2,X2,Y1
line X2,Y2,X1,Y2

endfunction


function ZM_FreeSprite()

repeat
inc zmtempno
until sprite exist(zmtempno)=0

endfunction zmtempno


function ZM_FreeImage()

repeat
inc zmtempno
until image exist(zmtempno)=0

endfunction zmtempno


function ZM_FreeBMP()

repeat
inc zmtempno
until bitmap exist(zmtempno)=0

endfunction zmtempno


Example program:
+ Code Snippet
sync on : sync rate 0

load image "Buttons.png",1
sprite 1,0,0,1

ZM_InitiateMouseTips(1,1000)

TipZone1=ZM_MakeTipZone_Box(150,120,417,300,"This is a blue box.","comic sans ms",20,rgb(1,1,1),rgb(255,255,150))
TipZone2=ZM_MakeTipZone_Box(640,207,725,300,"Look, a green box!","century gothic",12,rgb(1,1,1),rgb(200,255,200))

TipZone3=ZM_MakeTipZone_Circle(360,540,75,"It's a red circle.","times new roman",16,rgb(255,255,255),rgb(100,100,100))
TipZone4=ZM_MakeTipZone_Circle(747,540,85,"Another red circle.","arial",12,rgb(1,1,1),rgb(255,255,150))

ink rgb(255,255,255),0

`==================================
`MAIN LOOP

do

text 10,10,str$(mousex())
text 10,20,str$(mousey())
text 10,40,"FPS: "+str$(screen fps())

ZM_UpdateTips()

sync
loop

`==================================