Author Topic: A Quick ToolTip Example  (Read 3049 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
A Quick ToolTip Example
« on: November 11, 2020, 09:53:49 am »
Since someone posted somewhere here the other day asking about a ToolTip type library, I thought I'd go ahead and take a moment to play around with something along those lines, as I way to get my mind distracted from the "bad handle" issue my other project keeps tossing me.   Sometimes the brain just needs to switch gears and reset, so I thought I'd pass it something completely different to work on for a little bit.  :)

Code: QB64: [Select]
  1. TYPE ToolTipInfo
  2.     text AS STRING
  3.     x AS INTEGER
  4.     y AS INTEGER
  5.  
  6. DIM SHARED RegisteredTips(100) AS ToolTipInfo
  7.  
  8. SCREEN _NEWIMAGE(800, 600, 32)
  9.  
  10. RegisterToolTip "Cheese is tasty and made from moo moo cows!", 245, 100
  11. RegisterToolTip "A fridge is the cold thing which folks hold their cheeses in!", 380, 100
  12.     CLS
  13.     _PRINTSTRING (100, 100), "People like cheese  in their fridge ."
  14.     DisplayToolTips
  15.     _LIMIT 30 'don't melt my damn CPU
  16.     _DISPLAY
  17.  
  18.  
  19.  
  20.  
  21.  
  22. SUB RegisterToolTip (what$, x, y)
  23.     IF what$ = "" THEN EXIT SUB 'can't register nothing
  24.     IF x < 0 OR y < 0 THEN EXIT SUB 'don't put your tooltip off the damn screen!
  25.     IF x > _WIDTH - _FONTWIDTH OR y > _HEIGHT - _FONTHEIGHT THEN EXIT SUB 'honestly, I say, don't put your tooltip off the damn screen!
  26.     FOR i = 1 TO 100
  27.         IF RegisteredTips(i).text = "" THEN 'it's a free tooltip spot
  28.             RegisteredTips(i).text = what$
  29.             RegisteredTips(i).x = x
  30.             RegisteredTips(i).y = y
  31.             EXIT SUB 'We're done.  We've registered!
  32.         END IF
  33.     NEXT
  34.     'If we make it to here, we failed.  Some dummy probably has more than 100 tooltips, or else they registered them inside a loop, or such.
  35.     '(Note, this dummy could be your's truly...)
  36.  
  37. SUB FreeToolTip (x, y)
  38.     FOR i = 1 TO 100
  39.         IF RegisteredTips(i).x = x AND RegisteredTips(i).y = y THEN 'it's a free tooltip spot
  40.             RegisteredTips(i).text = ""
  41.             RegisteredTips(i).x = -1
  42.             RegisteredTips(i).y = -1
  43.             EXIT SUB 'We're done.  We've registered!
  44.         END IF
  45.     NEXT
  46.  
  47. SUB DisplayToolTips
  48.     STATIC Qbox AS LONG
  49.     d = _DEST
  50.  
  51.     IF Qbox = 0 THEN
  52.         Qbox = _NEWIMAGE(_FONTWIDTH, _FONTHEIGHT, 32)
  53.         _DEST Qbox
  54.         COLOR _RGB32(255, 255, 0), _RGB32(0, 0, 128) 'Yellow on blue
  55.         _PRINTSTRING (0, 0), "?"
  56.     END IF
  57.     FOR i = 1 TO 100
  58.         IF RegisteredTips(i).text <> "" THEN
  59.             _PUTIMAGE (RegisteredTips(i).x, RegisteredTips(i).y), Qbox
  60.             IF _MOUSEX >= RegisteredTips(i).x AND _MOUSEX < RegisteredTips(i).x + _FONTWIDTH THEN 'in right spot
  61.                 IF _MOUSEY >= RegisteredTips(i).y AND _MOUSEY < RegisteredTips(i).y + _FONTHEIGHT THEN 'we're REALLY in the right spot
  62.                     'show that damn tool tip
  63.  
  64.                     temp = _PRINTWIDTH(RegisteredTips(i).text)
  65.                     h = (temp \ (_WIDTH \ 2) + 3) * _FONTHEIGHT
  66.                     temp = _NEWIMAGE(_WIDTH \ 2, h, 32)
  67.                     _DEST temp
  68.                     CLS , _RGB32(255, 255, 255) 'white background
  69.                     COLOR _RGB32(0, 0, 0), 0
  70.                     LOCATE 2, 1: PRINT RegisteredTips(i).text;
  71.                     _DEST d
  72.                     _PUTIMAGE (RegisteredTips(i).x, RegisteredTips(i).y - h), temp
  73.                     _FREEIMAGE temp
  74.                 END IF
  75.             END IF
  76.         END IF
  77.     NEXT
  78.     _DEST d

There's a million different ways to do one of these, but I chose one of the simplest just to kinda highlight the process behind them.  At their heart, they're nothing more than a little routine which "designates proper coordinate for the mouse to be at to generate a pop up", "check to see if the mouse is in those coordinates", "if so, then pop up something!"

For this to be a proper little routine, it needs some work on positioning of the tooltip (right now, you can pop it up with portions -- or even the whole thing -- completely offscreen), but it's basically the process one would use for this type of job. 

It could also use a slightly smarter detection method, and background storage/replacement, but those are "advanced" features, and just complicate the basics which is what I really wanted to show here.  ;)

Anywho, it is what it is.  Maybe it'll be enough for a start to help someone sort out how they'd want to implement something similar in their own programs.  :)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: A Quick ToolTip Example
« Reply #1 on: November 11, 2020, 11:19:16 am »
And here's a slightly more advanced version which runs off a timer, stores its own background, and processes the mouse input for us automatically (if we want it to).

Code: QB64: [Select]
  1. TYPE ToolTipInfo
  2.     text AS STRING
  3.     x AS INTEGER
  4.     y AS INTEGER
  5.  
  6. DIM SHARED RegisteredTips(100) AS ToolTipInfo, t1
  7. CONST True = -1, False = 0
  8.  
  9. t1 = _FREETIMER 'get a timer number from _FREETIMER ONLY!
  10. ON TIMER(t1, .001) DisplayToolTips
  11.  
  12.  
  13.  
  14.  
  15. SCREEN _NEWIMAGE(800, 600, 32)
  16. CLS , _RGB32(128, 128, 0)
  17. FOR i = 1 TO 100 'just a background to get and restore
  18.     LINE (RND * 800, RND * 600)-(RND * 800, RND * 600), _RGB32(RND * 255, RND * 255, RND * 255), BF
  19.  
  20. RegisterToolTip "Cheese is tasty and made from moo moo cows!", 245, 100
  21. RegisterToolTip "A fridge is the cold thing which folks hold their cheeses in!", 380, 100
  22.  
  23. PowerToolTips True, True 'This tells us to turn tool tips ON (first true), and to have it process the mouse (second true)
  24.  
  25. _PRINTSTRING (100, 100), "People like cheese  in their fridge ." 'Notice we're printing once and not rebuilding the display each cycle?
  26.  
  27.     _LIMIT 30 'don't melt my damn CPU
  28.     _DISPLAY
  29.  
  30.  
  31. SUB PowerToolTips (OnOff, MouseNoMouse)
  32.     IF OnOff THEN
  33.         TIMER(t1) ON
  34.     ELSE
  35.         TIMER(t1) OFF
  36.     END IF
  37.     RegisteredTips(0).y = MouseNoMouse
  38.  
  39.  
  40. SUB RegisterToolTip (what$, x, y)
  41.     IF what$ = "" THEN EXIT SUB 'can't register nothing
  42.     IF x < 0 OR y < 0 THEN EXIT SUB 'don't put your tooltip off the damn screen!
  43.     IF x > _WIDTH - _FONTWIDTH OR y > _HEIGHT - _FONTHEIGHT THEN EXIT SUB 'honestly, I say, don't put your tooltip off the damn screen!
  44.     FOR i = 1 TO 100
  45.         IF RegisteredTips(i).text = "" THEN 'it's a free tooltip spot
  46.             RegisteredTips(i).text = what$
  47.             RegisteredTips(i).x = x
  48.             RegisteredTips(i).y = y
  49.             EXIT SUB 'We're done.  We've registered!
  50.         END IF
  51.     NEXT
  52.     'If we make it to here, we failed.  Some dummy probably has more than 100 tooltips, or else they registered them inside a loop, or such.
  53.     '(Note, this dummy could be your's truly...)
  54.  
  55. SUB FreeToolTip (x, y)
  56.     FOR i = 1 TO 100
  57.         IF RegisteredTips(i).x = x AND RegisteredTips(i).y = y THEN 'it's a free tooltip spot
  58.             RegisteredTips(i).text = ""
  59.             RegisteredTips(i).x = -1
  60.             RegisteredTips(i).y = -1
  61.             EXIT SUB 'We're done.  We've registered!
  62.         END IF
  63.     NEXT
  64.  
  65. SUB DisplayToolTips
  66.     STATIC Qbox AS LONG, Background AS LONG, Bx, By
  67.     d = _DEST
  68.  
  69.     IF Qbox = 0 THEN
  70.         Qbox = _NEWIMAGE(_FONTWIDTH, _FONTHEIGHT, 32)
  71.         _DEST Qbox
  72.         COLOR _RGB32(255, 255, 0), _RGB32(0, 0, 128) 'Yellow on blue
  73.         _PRINTSTRING (0, 0), "?"
  74.     END IF
  75.  
  76.     IF RegisteredTips(i).y THEN WHILE _MOUSEINPUT: WEND 'If required, then read/update the mouse
  77.  
  78.     FOR i = 1 TO 100
  79.         IF RegisteredTips(i).text <> "" THEN _PUTIMAGE (RegisteredTips(i).x, RegisteredTips(i).y), Qbox
  80.     NEXT
  81.  
  82.  
  83.     FOR i = 1 TO 100
  84.         IF RegisteredTips(i).text <> "" THEN
  85.             IF _MOUSEX >= RegisteredTips(i).x AND _MOUSEX < RegisteredTips(i).x + _FONTWIDTH AND _MOUSEY >= RegisteredTips(i).y AND _MOUSEY < RegisteredTips(i).y + _FONTHEIGHT THEN 'we're in the right spot
  86.                 'show that damn tool tip
  87.                 IF Background THEN
  88.                     _PUTIMAGE (Bx, By), Background, d
  89.                     _FREEIMAGE Background
  90.                     Background = 0
  91.                 END IF
  92.                 temp = _PRINTWIDTH(RegisteredTips(i).text)
  93.                 h = (temp \ (_WIDTH \ 2) + 3) * _FONTHEIGHT
  94.                 temp = _NEWIMAGE(_WIDTH \ 2, h, 32)
  95.                 Background = _NEWIMAGE(_WIDTH \ 2, h, 32)
  96.                 _DEST temp
  97.                 CLS , _RGB32(255, 255, 255) 'white background
  98.                 COLOR _RGB32(0, 0, 0), 0
  99.                 LOCATE 2, 1: PRINT RegisteredTips(i).text;
  100.                 _DEST d
  101.                 Bx = RegisteredTips(i).x: By = RegisteredTips(i).y - h
  102.                 _PUTIMAGE , d, Background, (Bx, By)-STEP(_WIDTH \ 2 - 1, h - 1)
  103.                 _PUTIMAGE (Bx, By), temp
  104.                 _FREEIMAGE temp
  105.                 _DEST d
  106.                 EXIT SUB
  107.             END IF
  108.         END IF
  109.     NEXT
  110.     IF Background THEN
  111.         _PUTIMAGE (Bx, By), Background, d
  112.         _FREEIMAGE Background
  113.         Background = 0
  114.     END IF
  115.     _DEST d

If you notice, my main program loop is just this:

DO
    _LIMIT 30 'don't melt my damn CPU
    _DISPLAY
LOOP UNTIL _KEYDOWN(27)

Everything is handled by the timer and our sub routines, which we call with these few lines:

RegisterToolTip "Cheese is tasty and made from moo moo cows!", 245, 100
RegisterToolTip "A fridge is the cold thing which folks hold their cheeses in!", 380, 100

PowerToolTips True, True 'This tells us to turn tool tips ON (first true), and to have it process the mouse (second true)


It really is that simple.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!