Different way to do buttons

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
phishguy
Posts: 1201
Joined: May 05, 2006 16:12
Location: West Richland, Wa

Different way to do buttons

Post by phishguy »

I realize this is still a crude example. However, I thought that I would show a fairly easy way to create and detect buttons that doesn't require testing the button location to determine which button is pressed. Basically each button has another hidden button with a unique color on another graphics page. So, to find out what button the mouse is over you just need to test for the color at the current mouse position.

Code: Select all

dim as integer x,y,button,v

Screen 18,8,4,1
 screenset 1,0
Line  (140, 80)-(180, 120), 1, bf
line (190,80)-(200,90),2,bf
screenset 0,0
line (140,80)-(180,120),15,bf
line (190,80)-(200,90),15 ,bf
screenset 1,0
do
    screenset 1,0
    getmouse  x,y,,button
    v=point(x,y)
     screenset 0,0
     if v >0 then
        locate 10,10
        if button <> 0 then
        print "button "; v;" pressed"
    else
        print "                           "
        end if
        'print x;y;v;button
     end if
    sleep 1,1
    loop until inkey$<>""
Sleep  
1000101
Posts: 2556
Joined: Jun 13, 2005 23:14
Location: SK, Canada

Post by 1000101 »

This is a horribly slow and memory wasteful way of doing button hover detection.

If you are in fullscreen, then your pages are in VRAM and VRAM is extremely slow to read from. Not to mention it doesn't take into account z ordering or visibility.

No, I give this "tip" an F.
phishguy
Posts: 1201
Joined: May 05, 2006 16:12
Location: West Richland, Wa

Post by phishguy »

I guess that I don't quite understand why it would be horribly slow. I'm only testing the color of a point on a non-displayed page. True enough it's memory wastefull due to using a second page. But, if your not concerned about memory usage it works OK.

Sorry for asking, I'm not a graphics expert, but what do you mean by z ordering and visibility?
DrV
Site Admin
Posts: 2116
Joined: May 27, 2005 18:39
Location: Midwestern USA
Contact:

Post by DrV »

If you are using the FB gfxlib, then the pages you can read/write with screeptr are *never* in vram, regardless of fullscreen/windowed.
Dr_D
Posts: 2453
Joined: May 27, 2005 4:59
Contact:

Post by Dr_D »

It *is* good to experiment though. There is definetly more than one way to skin a horse. ;)

What he means by z-ordering is... Imagine when you have two programs open in Windows. The program that is active will have a higher z value than the program that is inactive. You can think of it like layering, in a sense.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Post by MichaelW »

phishguy,

Basically, z-order and visibility apply when you have multiple windows that can be overlapped, sized, or hidden.

http://en.wikipedia.org/wiki/Z-order

For simple applications that have only one window, of a fixed size, z-order and visibility do not matter. Compared to methods that use the button coordinates your method would be slow and wasteful of memory, but not to the point of it actually mattering for most simple applications. Your method is easier to implement for buttons, and I think the general method might be much easier to implement for certain specialized applications. Thanks for posting.
phishguy
Posts: 1201
Joined: May 05, 2006 16:12
Location: West Richland, Wa

Post by phishguy »

Thanks for the feedback. I still like this method for simple menus and I've written a simple menu front end for a program I'm currently working on. I've done several improvements. I know there are still some people who think this wastes memory and is slow. Here's my new version

Code: Select all

 
dim as string parameter(0 to 7) = {"","Off","On","PC","Off","9600"}
dim as integer x,y,button,v ,ov,baudrate,oldbaudrate,ts,oldts,dcolor
dim as integer xpos(7),ypos(7),bheight(7),bwidth(7)
dim as string text(0 to 7) = {"","Unique:","Count:","Time/Date:","Temp:","Baud:","Extra:","Start"}
dim as string baud(1 to 8) = {"1200","2400","4800","9600","19200","38400","57600","115200"}
dim as string timestamp(1 to 3) = {"Off","PC","Reader"}

ts=2
oldts=2
ov=0
baudrate=4
oldbaudrate=4
xpos(1)=100
ypos(1)=80

Screenres 190,400,8,2
Paint (160, 100), 30, 15
for x = 1 to 7
bheight(x)=30
bwidth(x)=150
xpos(x)=20
ypos(x)=(x*40)+40

 ' draw hidden buttons with unique color assignments
 screenset 1,0
Line  (xpos(x), ypos(x))-(xpos(x)+bwidth(x),ypos(x)+bheight(x)), x, bf

' draw visible buttons with same dimensions as hidden buttons
screenset 0,0
Line  (xpos(x), ypos(x))-(xpos(x)+bwidth(x),ypos(x)+bheight(x)), 15, bf
Line  (xpos(x)+2, ypos(x)+2)-(xpos(x)+bwidth(x)-2,ypos(x)+bheight(x)-2), 7, bf
draw string (xpos(x)+13,ypos(x)+10),  text(x),1
draw string (xpos(x)+96,ypos(x)+10), parameter(x),0
next x

do
    screenset 1,0
    getmouse  x,y,,button
     
   if button <> 1 then
       screenset 0,0
        draw string (40,20), text(ov) & " pressed",30 
        
        
       select case as const ov
       case 1,2,4
          if parameter(ov)="OFF" then
              draw string (xpos(ov)+96,ypos(ov)+10),parameter(OV),7
              parameter(ov)="ON"
              
              draw string (xpos(ov)+96,ypos(ov)+10),parameter(ov),2
          else 
              draw string (xpos(ov)+96,ypos(ov)+10),parameter(ov),7
              parameter(ov)="OFF"
              
              draw string (xpos(ov)+96,ypos(ov)+10),parameter(ov),4
              end if
            
                     
       case 3
           ts=ts+1
           if ts=4 then
               ts=1
           end if
            if ts = 1 then 
                dcolor = 4
            else 
                dcolor = 0
                end if
           draw string (xpos(ov)+96,ypos(ov)+10),timestamp(oldts),7
          draw string (xpos(ov)+96,ypos(ov)+10),timestamp(ts),dcolor
           oldts = ts
           
           
       case 5
          baudrate = baudrate +1
          if baudrate = 9 then
              baudrate = 1
          end if
          draw string (xpos(ov)+96,ypos(ov)+10),baud(oldbaudrate),7
          draw string (xpos(ov)+96,ypos(ov)+10),baud(baudrate),0
          oldbaudrate = baudrate
           
       case 6
         'to be defined   
           
       case 7
            'code to start main program
       end select
       ov=0
        screenset 1,0
     end if
    ' get color of hidden screen at mouse coordinate 
    if button = 1 then
     v=point(x,y)
     screenset 0,0 
       
     if v <>0  then
             draw string (40,20), text(v) & " pressed",1  
             ov=v
           end if
           
     end if
     
    sleep 1,1
    loop until inkey$<>""
  
Halifax
Posts: 65
Joined: Nov 04, 2005 1:30

Post by Halifax »

It seems to me that using colors to define a button is not really required. Why not just do this?

Code: Select all

Dim ButtonSpace(0 to 639, 0 to 479) as integer

GetMouse MouseX,MouseY,,MouseButtons

if MouseButtons then

if ButtonSpace(MouseX,MouseY) > 0 then

'// check buttons using ButtonSpace(MouseX,MouseY) as the identifier

end if

end if

Unless, of course, using Point(x,y) is faster than accessing an array of integers.

Edit: Now that I think about it, I may implement this into my own program. It would be easy to have irregular sized buttons without complicating area checking for the button. In fact, you could make a button that is the exact shape as your sprite, to take my situation as an example. Simply make a mask of the sprite, overlay it onto the ButtonSpace. It would require multiple layers, however, in order to support button precedence. Either that or specific ranges of integers to seperate button identities.
phishguy
Posts: 1201
Joined: May 05, 2006 16:12
Location: West Richland, Wa

Post by phishguy »

@ Halifax
Yes, that makes sense. Use an array instead of the screen memory is a little easier. I have modified to use your suggestion.

Code: Select all

windowtitle "XLWedge 1.0"
 
Dim As String parameter(0 To 7) = {"","Off","On","PC","Off","9600"}
Dim As Integer x,y,button,v ,ov,baudrate,oldbaudrate,ts,oldts,dcolor,x1 
Dim As Integer xpos(7),ypos(7),bheight(7),bwidth(7)
Dim As String text(0 To 7) = {"","Unique:","Count:","Date/Time:","Temp:","Baud:","Extra:","Start"}
Dim As String baud(1 To 8) = {"1200","2400","4800","9600","19200","38400","57600","115200"}
Dim As String timestamp(1 To 3) = {"Off","PC","Reader"}
dim buttonspace(0 to 639,0 to 479) as byte
ts=2
oldts=2
ov=0
baudrate=4
oldbaudrate=4
xpos(1)=100
ypos(1)=80

Screenres 190,400,8,2
Paint (160, 100), 30, 15
 
For x = 1 To 7
bheight(x)=30
bwidth(x)=150
xpos(x)=20
ypos(x)=(x*40)+40

 
for x1 = xpos(x) to xpos(x)+bwidth(x)
    for y= ypos(x) to ypos(x)+bheight(x)
        buttonspace (x1,y) = x
    next
next

 
Line  (xpos(x), ypos(x))-(xpos(x)+bwidth(x),ypos(x)+bheight(x)), 15, bf
Line  (xpos(x)+2, ypos(x)+2)-(xpos(x)+bwidth(x)-2,ypos(x)+bheight(x)-2), 7, bf
Draw String (xpos(x)+13,ypos(x)+10),  text(x),1
Draw String (xpos(x)+96,ypos(x)+10), parameter(x),0
Next x

Do
 
    getmouse  x,y,,button
     
   If button <> 1 Then
        
        Draw String (40,20), text(ov) & " pressed",30 
        
        
       Select Case As Const ov
       Case 1,2,4
          If parameter(ov)="OFF" Then
              Draw String (xpos(ov)+96,ypos(ov)+10),parameter(OV),7
              parameter(ov)="ON"
              
              Draw String (xpos(ov)+96,ypos(ov)+10),parameter(ov),2
          Else 
              Draw String (xpos(ov)+96,ypos(ov)+10),parameter(ov),7
              parameter(ov)="OFF"
              
              Draw String (xpos(ov)+96,ypos(ov)+10),parameter(ov),4
              End If
            
                     
       Case 3
           ts=ts+1
           If ts=4 Then
               ts=1
           End If
            If ts = 1 Then 
                dcolor = 4
            Else 
                dcolor = 0
                End If
           Draw String (xpos(ov)+96,ypos(ov)+10),timestamp(oldts),7
          Draw String (xpos(ov)+96,ypos(ov)+10),timestamp(ts),dcolor
           oldts = ts
           
           
       Case 5
          baudrate = baudrate +1
          If baudrate = 9 Then
              baudrate = 1
          End If
          Draw String (xpos(ov)+96,ypos(ov)+10),baud(oldbaudrate),7
          Draw String (xpos(ov)+96,ypos(ov)+10),baud(baudrate),0
          oldbaudrate = baudrate
           
       Case 6
         'to be defined   
           
       Case 7
            'code to start main program
       End Select
       ov=0
        
     End If
     
    If button = 1 Then
     v=buttonspace(x,y)
  
       
     If v <>0  Then
             Draw String (40,20), text(v) & " pressed",1  
             ov=v
           End If
           
     End If
     
    Sleep 1,1
    Loop Until Inkey$<>""
  
 
Post Reply