Page 1 of 2

Tooltip change too fast, stack overflow and crash

Posted: Tue Dec 18, 2007 5:01 am
by Fangbeast
Just revisited some code of a few years ago and was trying to narrow down a particular error.

I can set and change tooltips on any gadgets without problems most of the time.

In a listicongadget that I have, I get the current line being clicked on and change the tooltip text to the contents of that line.

It seems to randomly crash the compiler with a "ERROR: Stack Overflow" and it doesn't seem to matter whether I click fast or slow on each line. It also doesn't matter what sorts of gadgets I use. Start clicking and random stack overflow crashes occur.

Anyone else have experience with this?

Code: Select all

;============================================================================================================================
; Personal balloon tooltip window, colourful and not boring at all
;============================================================================================================================

Procedure MyBalloonToolTips(btWindow.l, btGadget.l, btText.s)
  ForEach tooltips()                                                  ; Exit this routine if tool tip for control exists
    If tooltips()\window = btWindow And tooltips()\gadget = btGadget
      ProcedureReturn
    EndIf
  Next
  ;--------------------------------------------------------------------------------------------------------------------
  ToolTipControl = CreateWindowEx_(0, "ToolTips_Class32", "", #WS_POPUP | #TTS_NOPREFIX | #TTS_BALLOON, 0, 0, 0, 0, WindowID(btWindow), 0, GetModuleHandle_(0), 0)
  SetWindowPos_(ToolTipControl,#HWND_TOPMOST, 0, 0, 0, 0, #SWP_NOMOVE | #SWP_NOSIZE)
  SendMessage_(ToolTipControl, #TTM_SETTIPTEXTCOLOR, 0, 0)
  SendMessage_(ToolTipControl, #TTM_SETTIPBKCOLOR, $F58C0A, 0)
  SendMessage_(ToolTipControl, #TTM_SETMAXTIPWIDTH, 0, 380)
  Button.TOOLINFO\cbSize  = SizeOf(TOOLINFO)
  Button\uFlags           = #TTF_IDISHWND | #TTF_SUBCLASS
  Button\hwnd             = WindowID(btWindow)
  Button\uID              = GadgetID(btGadget)
  Button\hInst            = 0
  Button\lpszText         = @btText
  SendMessage_(ToolTipControl, #TTM_ADDTOOL, 0, Button)
  SendMessage_(ToolTipControl, #TTM_UPDATE, 0, 0)
  ;--------------------------------------------------------------------------------------------------------------------
  AddElement(tooltips())                                              ; Add the newly created tool tip details to the linked list
    tooltips()\window = btWindow
    tooltips()\gadget = btGadget
    tooltips()\handle = ToolTipControl
EndProcedure


; MyBalloonToolTips(#MyMainWindow, #MyListIconGadget, "This will be the primary tool tip text")

;============================================================================================================================
; With this routine, I can change the tool tip text at any time. I do this throughout the program as I have a default too
; tip and then a dynamically changing tool tip on some gadgets depending on their fields.
;============================================================================================================================

;============================================================================================================================
; The routine allows you to change the tool tip text for a specific gadget
;============================================================================================================================

Procedure.l ChangeToolTip(ttGadget.l, btText.s)
  ForEach tooltips()                                                   ; Check each tooltip entry
    If tooltips()\gadget = ttGadget.l And IsGadget(ttGadget.l)         ; If there is an entry in the list for this window
      btHandle.l = tooltips()\handle                                    ; Get the current tooltip handle
      btWindow.l = tooltips()\window                                    ; Get the current window handle
      btGadget.l = tooltips()\gadget                                    ; Get the current gadget handle
      ttChange.TOOLINFO\cbSize  = SizeOf(TOOLINFO)
      ttChange\hwnd             = WindowID(btWindow.l)
      ttChange\uId              = GadgetID(btGadget.l)
      ttChange\lpszText         = @btText.s
      SendMessage_(btHandle.l, #TTM_UPDATETIPTEXT, 0, ttChange)
    EndIf
  Next tooltips()
EndProcedure

; ChangeToolTip(#MyListIconGadget, "This is the new tool tip text")

;============================================================================================================================
; Remove previously set tool tips for an entire window. Xombie
;============================================================================================================================

Procedure.l RemoveToolTipW(TtWindow.l)
  ForEach tooltips()                                         ; Check each tooltip entry
    If tooltips()\window = TtWindow.l                         ; If there is an entry in the list for this window
      btHandle.l = tooltips()\handle                          ; Get the current tooltip handle
      btWindow.l = tooltips()\window                          ; Get the current window handle
      btGadget.l = tooltips()\gadget                          ; Get the current gadget handle
      DeleteElement(tooltips())                               ; Delete the current element from the list
      Button.TOOLINFO\cbSize  = SizeOf(TOOLINFO)              ; Get tooltip info size
      Button\hwnd             = WindowID(btWindow)            ; Get the windows id for this element
      Button\uID              = GadgetID(btGadget)            ; Get the gadget id for this element
      SendMessage_(btHandle, #TTM_DELTOOL, 0, Button)         ; Delete the tooltip for this window from the list and gadget
    EndIf                                                    ; End conditional test
  Next                                                       ; Next iteration
EndProcedure 
**EDIT** Added the full routine to show the linked list handling

Posted: Tue Dec 18, 2007 5:23 am
by netmaestro
I notice in your MyBalloonToolTips() procedure, you're not doing a ProcedureReturn of the ToolTipControl variable, which is the handle of the tooltip window itself. So, later when you're doing btHandle.l = tooltips()\handle I'm wondering how the handle has found its way into the linkedlist? Sending such a message to the wrong hwnd could cause the problem you're seeing. I'm not identifying it as necessarily the problem, I'm just curious as to how the correct hwnd is getting into the linkedlist if it isn't returned from the creation proc.

Posted: Tue Dec 18, 2007 5:42 am
by Fangbeast
netmaestro wrote:I notice in your MyBalloonToolTips() procedure, you're not doing a ProcedureReturn of the ToolTipControl variable, which is the handle of the tooltip window itself. So, later when you're doing btHandle.l = tooltips()\handle I'm wondering how the handle has found its way into the linkedlist? Sending such a message to the wrong hwnd could cause the problem you're seeing. I'm not identifying it as necessarily the problem, I'm just curious as to how the correct hwnd is getting into the linkedlist if it isn't returned from the creation proc.
I forgot to strip the linked list stuff out of the examples (blame the head). :):):)

In my full program, I used linked lists to check if the the tip exists already in the linked list and it not, adds all the necessary details to the list.

Posted: Tue Dec 18, 2007 6:37 am
by Fangbeast
Edited the above examples with the linked list stuff.

Also did more experiments. I clicked on 10 entries, counting 10 seconds between each click and the compiler crashed on the tenth click.

I restarted the program, clicked the first entry and it crashed.

I restarted the program, clicked 20 entries fast and it crashed on the 20'th.

I restarted the program keeping 2 seconds between each click and it crashed on the fifth.

Posted: Tue Dec 18, 2007 9:06 am
by ABBKlaus
i´m not shure, but i think the procedurereturn in the foreach loop mixes the stack up :

Code: Select all

  ForEach tooltips()
    If tooltips()\window = btWindow And tooltips()\gadget = btGadget 
      ProcedureReturn ; <- this could mix up the stack ?
    EndIf 
  Next 
better use this :

Code: Select all

  quit=0
  ForEach tooltips()
    If tooltips()\window = btWindow And tooltips()\gadget = btGadget 
      quit=1
      Break
    EndIf 
  Next 
  If quit
    ProcedureReturn
  EndIf

Posted: Tue Dec 18, 2007 9:15 am
by Fangbeast
Thanks AbbKlaus but it only crashes in the

ChangeToolTip(ttGadget.l, btText.s)

procedure and specifically at this point below


SendMessage_(btHandle.l, #TTM_UPDATETIPTEXT, 0, ttChange)

Posted: Tue Dec 18, 2007 11:18 am
by srod
Fangs, first without code I can run, then like everyone else here, it's a bit of a shot in the dark. However, one unrelated question - why create a separate tooltip control for each gadget? Why not use just a single tooltip control?

Posted: Tue Dec 18, 2007 1:05 pm
by Fangbeast
srod, it was a simple, quick question, not an attempt at someone asking to get a 29,000 line program fixed. There are plenty of alternatives that I can try apart from this stupendously elegant tooltip solution.

As for the answer to your question, I have no idea why. I'm tired, it's hot every day, my sister's husband is in hospital and might die, this is the best and quickest question I could come up with in the circumstances.

When I have time, I drop the idea and try something else until I have time and am not cooked around the edges. But as for code, I don't have time to write a mini program to illustrate the point at this time as I am in danger of being thoroughly carbonised.

Who will blow up first? me or my computer? Make a poll.

Posted: Tue Dec 18, 2007 2:31 pm
by srod
Right, now that we have fixed the problem fangles I expect an extra large Xmas pressie this year - not that block of mouldy cheese you sent me last year. Mind you, that did save me buying my brother a birthday present later that year! :wink:

For those who have followed this thread, the problem was a repeated calling of the same procedure - it just had to be! A common problem with callbacks which themselves send extra messages to the underlying window etc.

Specifically, the SendMessage_() which fangles pointed to above just had to be causing a repeated calling of the same procedure through some callback message. It turned out to be the #TTN_POP notification which was being used to insitigate the changes to the tooltip text. This change caused another #TTN_POP message to be sent which then updated the text which caused another #TTN_POP... and so on. :)
Now, you may ask where is the #TTN_POP message in the code originally posted by fangles? A good question indeed! :wink:

Next time fangles, post the full program - I don't care if it is 29000 lines long. And while you're at it, post me that enormous cheque I deserve for the spot of srod bashing undertaken in your previous post! :twisted:

hehe.

Posted: Tue Dec 18, 2007 2:42 pm
by Fangbeast
Right, now that we have fixed the problem fangles
Who's we hamster breath? I had nothing to do with it!!
I expect an extra large Xmas pressie this year
Okay, no problem. 480 pounds, semi naked, wearing a fetid, decaying, steaming g-string, no morals and hasn't washed in years and constantly craves dwarves.
- not that block of mouldy cheese you sent me last year.
That's gratitude for you. I set it in the loo for years just for you and no you tell me you refused it??? Indian taker!!!
Mind you, that did save me buying my brother a birthday present later that year! :wink:
Why did your brother ask me to hold a conference on assasination methods and not want to invite you?
Now, you may ask where is the #TTN_POP message in the code originally posted by fangles? A good question indeed! :wink:
it's sad when hairy little cave trolls expect me to put things in when I don't know about their existence. But then hairy little cave trolls who can code like this always think that us subservient serfs actually know something.

Now shaddap while I bang my brainspace up against the wall!!
Next time fangles, post the full program - I don't care if it is 29000 lines long.
No!! I won't. And you can't make me! Eat my shorts and bite me good!!!
And while you're at it, post me that enormous cheque I deserve for the spot of srod bashing undertaken in your previous post! :twisted:
I've sent you the cheque by express snail but you forgot to mention that I was actually supposed to write something in it apart from "Bite me doh boy". See what happens when you entrust idiots with cheques???

/me wonders when that Dare fellow will arrive with his smiley for this terrific repartee.

Posted: Tue Dec 18, 2007 3:01 pm
by Dare
Enter stage left ..
:D
Exit stage right ..



Renter stage left .. to cries of 'encore, encore'

Use the SendMessage_() to fire off the cheque and send srod into a #TTN_POPping frenzy spiraling into infinite ecstasy.

srod wrote:Now, you may ask where is the #TTN_POP message in the code originally posted by fangles? A good question indeed! :wink:
And the answer is?

* Goes into a #TTN_POPped frenzy of unfulfilled curiosity *

Bows to standing ovation

Posted: Tue Dec 18, 2007 3:04 pm
by srod
:lol:

15 minutes to reply, you're slowing down in your old age dare!

Posted: Tue Dec 18, 2007 3:09 pm
by Dare
srod wrote::lol:

15 minutes to reply, you're slowing down in your old age dare!
:D

The computer in the dunny is on the blink!

Sheesh. Give a guy a break!!

Posted: Tue Dec 18, 2007 3:11 pm
by Fangbeast
That last curry you had must have overheated the cpu again. Told you not to let go until you faced away from the 15 Mhz BogBox!!!!

Posted: Tue Dec 18, 2007 3:12 pm
by srod
I'm considering breaking fangles' legs if that is what you mean? I'll leave his arms so that he can still type.

:)