Jump to content

Tooltips hitting max. number of GUI controls?


james3mg
 Share

Recommended Posts

james3mg,

This is as good as I can get it. It is pretty fast as I have limited the WinList search to tooltips_class32 windows and reduced the _Array* functions to a minimum.

[...awesome example...]

Never would've thought of that! :evil:

Since my script is already making extensive use of SQLite, I may be able to take advantage of that instead of the _Array* functions for just a little more efficiency, but all in all, this may be as good as it gets. At least my script has very specific times it creates/destroys the GUIs, so it shouldn't be too hard to keep the burden of all this to a minimum.

I'll take a closer look in a few hours when I have a little more time.

THANK YOU for your awesome assistance! And to everyone who helped me in this topic! ;)

Edit: just had another thought I'll look into as well; my example of trying to delete the tooltip control by number before may have failed because I thought they were controls...your script implies they're actually GUIs unto themselves. Maybe I'll have more luck if I check for the numerical value of GUIs created before and after tooltips- I may be able to use GUIDelete() instead of GUICtrlDelete, since I'm not sure if WinKill() will actually free the resources/address reservation in the AutoIt table...

I'll let you know what I discover.

Edited by james3mg
"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

  • Moderators

james3mg.

Maybe I'll have more luck if I check for the numerical value of GUIs created before and after tooltips

I would not put too much hope in that. Windows is forever creating and deleting handles so the chances of them being in numerical order are minimal in my experience.

Glad I could help - it was fun. ;)

M23

Edit: A final thought as to why the OS falls over when you do not delete the tooltips. They are not part of the AutoIt control table (because they do not have ControlIDs), just normal Windows handles and Windows has a limit on how many an application can have open at any one time. So busting the limit is very likely to crash Windows rather than AutoIt. Anyway, it is moot now! :evil:

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

I don't think it will- IF I understand the way it should work (take my thoughts on this matter with a grain of salt ;) ), I think you're updating a single tooltip control/window rather than creating a new tooltip every time you update the text. My issue is that I'm creating NEW tooltips for NEW controls every time I recreate the children GUIs in my script.

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

  • Moderators

Thanubis,

As TraySetToolTip only sets/resets a single tip for the app's tray icon, I would imagine that the actual tooltip remains in existence and it is only the text in it which changes. So the "cannot delete" problem does not arise. However, as with much in IT, common sense does not always apply! ;)

Certainly I have often changed the text in a script's traytip multiple times without problem - although I have never got as far as 65532 alterations.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Most of my scripts don't deal with tons and tons of GUIs like this, as I'm sure you've gathered, so I'm still learning and re-learning all this stuff- thanks for your patience! ;)

I had indeed forgotten that GUI handles aren't like control handles, but are "global" for all of Windows, so yeah, finding the numerical value of the GUIs and guessing at the tooltips isn't going to be a good idea. So I ran with what you gave me. I think I improved on the method just a little, to make sure I don't grab tooltips that I shouldn't :evil:

$GUI1=GUICreate("test",480,480)
For $i=1 To 100
    GUICtrlCreateLabel($i,0,0,30,20)
    GUICtrlSetTip(-1,"tip "&$i)
Next
GUISetState()

$timer=TimerInit()
$aTips=_ListTips()
ConsoleWrite(TimerDiff($timer)&"ms to find "&UBound($aTips)-1&" tooltips" & @CRLF)

$timer=TimerInit()
For $i=1 To UBound($aTips)-1
    WinKill($aTips[$i])
Next
$aTips=0
ConsoleWrite(TimerDiff($timer)&"ms to delete all tooltips" & @CRLF)

While 1
    If GUIGetMsg()=-3 Then Exit
    Sleep(50)
WEnd

Func _ListTips()
    Local $aList1=WinList("[CLASS:tooltips_class32]")
    Local $aList2[1]
    For $i=1 To $aList1[0][0]
        If WinGetProcess($aList1[$i][1])=@AutoItPID Then
            ReDim $aList2[UBound($aList2)+1]
            $aList2[UBound($aList2)-1] = $aList1[$i][1]
        EndIf
    Next
    Return $aList2
EndFunc

Looks like the tooltips are indeed deleted- thank you! :)

The problem is, though it only takes my machine about 7ms to find 100 tooltips, it takes about 25 seconds to delete them, and the script really bogs down while it's doing it (mouse over the label to see the tooltip, and you see it kind of "pulse" in and out of existence- each pulse represents the time it takes to WinKill() just ONE tooltip.

So I'm afraid that, though this is the "answer" I was looking for, it's way too slow to use :idea: Slow enough, I haven't run any tests in the 65000 range to see if they no longer count against Windows' "per-process" window limit or not.

I tried using GUIDelete(), but it kept returning errors- I'm guessing that tooltips are a GUI belonging to Windows (Explorer?), and not the AutoIt script after all, so that won't be an option.

Any chance you know of a quicker way to kill windows? lol

P.S. you are the :evil: Thanks again.

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

  • Moderators

james3mg,

I like the WinGetProcess idea. ;) Just shows why this forum is useful - ideas sparking off each other.

I cannot, alas, offer a faster WinKill, but I can halve the short time to find the tips. :evil:

Your code used ReDim every pass - and that is very slow as ReDim rewrites the array each time. It is better to do something like the following when you fill an array of unknown size:

$GUI1 = GUICreate("test", 480, 480)
For $i = 1 To 100
    GUICtrlCreateLabel($i, $i * 5, $i * 5, 30, 20)
    GUICtrlSetTip(-1, "tip " & $i)
Next
GUISetState()

$timer = TimerInit()
$aTips = _ListTips()
ConsoleWrite(TimerDiff($timer) & "ms to find " & UBound($aTips) - 1 & " tooltips" & @CRLF)

$timer = TimerInit()
For $i = 1 To $aTips[0]
    WinKill($aTips[$i])
Next
$aTips = 0
ConsoleWrite(TimerDiff($timer) & "ms to delete all tooltips" & @CRLF)

While 1
    If GUIGetMsg() = -3 Then Exit
WEnd

Func _ListTips()
    Local $aList1 = WinList("[CLASS:tooltips_class32]")
    Local $aList2[2] = [0]
    For $i = 1 To $aList1[0][0]
        If WinGetProcess($aList1[$i][1]) = @AutoItPID Then
            ; Increase count element
            $aList2[0] += 1
            ; Double array size if too small (fewer ReDim needed)
            If UBound($aList2) <= $aList2[0] + 1 Then ReDim $aList2[UBound($aList2) * 2]
            ; Add to list
            $aList2[$aList2[0]] = $aList1[$i][1]
        EndIf
    Next
    ReDim $aList2[$aList2[0] + 1]
    Return $aList2
EndFunc   ;==>_ListTips

The saving when you deal with seriously big arrays is quite something - and you can always presize the array when declaring to something bigger than 2 to get an even greater effect. I hope it is obvious how it works, but please ask if not. :evil:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Yep, I get it, and it's a good point.

If I end up doing this in my script, I'll probably start with an initial size equal to that of $aList1, since there's no way the shorter list will ever be longer than the longer list! lol. Then only one ReDim is needed :evil:

However, as it stands right now, my script just isn't going to have any tooltips, since they're too limiting if they remain, and too slow if I delete them. :evil:

...I wonder which of the devs might have an idea on either using the straight Windows API for my own tooltips I can destroy or a faster way of killing windows... ;)

Edit: down to about 4ms to find all tips, still at 25000 to delete 'em

$GUI1=GUICreate("test",480,480)
For $i=1 To 100
    GUICtrlCreateLabel($i,0,0,30,20)
    GUICtrlSetTip(-1,"tip "&$i)
Next
GUISetState()

$timer=TimerInit()
$aTips=_ListTips()
ConsoleWrite(TimerDiff($timer)&"ms to find "&UBound($aTips)-1&" tooltips" & @CRLF)

$timer=TimerInit()
For $i=1 To UBound($aTips)-1
    WinKill($aTips[$i])
Next
$aTips=0
ConsoleWrite(TimerDiff($timer)&"ms to delete all tooltips" & @CRLF)

While 1
    If GUIGetMsg()=-3 Then Exit
    Sleep(50)
WEnd

Func _ListTips()
    Local $aList1=WinList("[CLASS:tooltips_class32]")
    Local $aList2[UBound($aList1)]=[0]
    For $i=1 To $aList1[0][0]
        If WinGetProcess($aList1[$i][1])=@AutoItPID Then
            $aList2[0]+=1
            $aList2[$aList2[0]]=$aList1[$i][1]
        EndIf
    Next
    ReDim $aList2[$aList2[0]+1]
    Return $aList2
EndFunc

Edited by james3mg
"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

  • Moderators

james3mg,

Last idea - use Adlib to keep your script active while deleting the tooltips. You need to adjust the timer for the Adlib carefully - on my machine I need to call it at not less than 300ms, any shorter backs up the Adlib function and the whole script stalls.

However, if you get the timing right you can keep the script active while the deletion proceeds - for me the deletion takes about 30secs (not much more than a straight loop which was around 25secs) and the ConsoleWrite shows that the script still has some processing power left. If you increased the Adlib time parameter, you could trade deletion time for script responsiveness. The only problem would be that you could not use the same array name again before the deletion process ended.

Have a look and see what you think:

#include <GUIConstantsEx.au3>

Global $iBegin, $fFinished = False

$GUI1 = GUICreate("test", 480, 480)
For $i = 1 To 100
    GUICtrlCreateLabel($i, $i * 5, $i * 5, 30, 20)
    GUICtrlSetTip(-1, "tip " & $i)
Next
GUISetState()

$timer = TimerInit()
$aTips = _ListTips()
ConsoleWrite(TimerDiff($timer) & "ms to find " & UBound($aTips) - 1 & " tooltips" & @CRLF)

; Start killing tooltips
Global $iIndex = 0
AdlibRegister("KillTips", 300)


While 1
    If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit

    ConsoleWrite("Still running at " & @MSEC & @CRLF)

    If $fFinished = True Then
        ConsoleWrite("All Done" & @CRLF)
        ConsoleWrite(TimerDiff($iBegin) & @CRLF)
        Exit
    EndIf

WEnd

Func _ListTips()
    Local $aList1 = WinList("[CLASS:tooltips_class32]")
    Local $aList2[2] = [0]
    For $i = 1 To $aList1[0][0]
        If WinGetProcess($aList1[$i][1]) = @AutoItPID Then
            ; Increase count element
            $aList2[0] += 1
            ; Double array size if too small (fewer ReDim needed)
            If UBound($aList2) <= $aList2[0] + 1 Then ReDim $aList2[UBound($aList2) * 2]
            ; Add to list
            $aList2[$aList2[0]] = $aList1[$i][1]
        EndIf
    Next
    ReDim $aList2[$aList2[0] + 1]
    Return $aList2
EndFunc   ;==>_ListTips

Func KillTips()

    $iIndex += 1
    ConsoleWrite($iIndex & @CRLF)
    If $iIndex = 1 Then $iBegin = TimerInit()
    WinKill($aTips[$iIndex])
    If $iIndex = $aTips[0] Then
        AdlibUnRegister("KillTips")
        $fFinished = True
    EndIf

EndFunc

Anyway, I will bow out now - have fun with the rest of it. ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Thought about that, but I'm not a huge fan of that solution. I'd rather make a second .exe launched from my main script that received the IDs as messages (_SendMessage()) from my main script and put them into a queue, deleting them as quickly as it could and otherwise idling around if there's nothing in the queue. That way, the processes are fully separate, and the main script wouldn't get bogged down unless the whole computer was so underpowered that the "cleanup" exe slowed all of Windows down.

But I still consider that a last resort- maybe even behind not having tooltips ;)

Thanks for your heap-and-a-half of help!

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

I use tool tips often myself and I found that I developed a tendency of adding more of them to lead the blind through the dark. In the end I had to make the decision to only use the ones that mattered the most. In some situations you may be better off to add a status bar and then place the text of the tool tip in there. That way it's only one control.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

Hey, thanks for giving me another chance :evil:

A status bar is a great idea- may be just the ticket I was looking for. The reason I was using tooltips is that most of my controls (primarily clickable labels), by necessity, are too small to display the entire text they contain. So I was using the tooltips to "expand" the missing labels so I'd know what I was clicking on. But a status bar is kind of an innate behavior in this day and age, so maybe that's enough.

Thanks for the idea! ;)

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

If Thats the case then you may even be better using ToolTip() instead of GUICtrlSetTip()

$Frm = GUICreate("Test")
$Lbl1 = GUICtrlCreateLabel("This is some string of text to read", 10, 10, 30, 20)
$Lbl2 = GUICtrlCreateLabel("This is an even longer string of text to read", 10, 30, 30, 20)
$Lbl3 = GUICtrlCreateLabel("This is the what will be the longest string of text to read", 10, 50, 30, 20)
GUISetState()
While 1
    $Msg = GUIGetMsg()
    Switch $Msg
        Case -3
            Exit
        Case $Lbl1 To $Lbl3
            ToolTip(GUICtrlRead($Msg))
                Case Else
                        ToolTip("")
    EndSwitch
WEnd

Or even look in one Example scripts for one of the hover functions.

Edited by GEOSoft

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

More great suggestions, thanks!

I was already having other things happen if the labels are clicked, but following your advice I found this topic, and found that by adding just the following lines to my script:

#include <GUICtrlSetOnHover_UDF.au3>

Func LabelHover($iCtrlID)
    ToolTip(GUICtrlRead($iCtrlId))
EndFunc

Func LabelMouseOut($iCtrlID)
    ToolTip("")
EndFunc
and replacing GUICtrlSetTip(-1,[control-specific_text]) with
_GUICtrl_SetOnHover(-1,"LabelHover","LabelMouseOut")
I get basically the same effect, but without the byproducts of creating and having to destroy control-specific tooltips.

So, I think that solves all my issues, though it's good to have this topic now, so others can be aware of the hazards of using thousands of GUICtrlSetTip() 's ;)

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

This is all so very good to know! I've fallen into a similar state as GEOsoft, whereby I'm adding tooltips to pretty much everything. It's good to see why this is bad, and to see better ways of doing similar functionality.

Thanks everyone! :D

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...