Class ToolTipOptions - 2024-03-27

Post your working scripts, libraries and tools.
User avatar
kunkel321
Posts: 1107
Joined: 30 Nov 2015, 21:19

Re: Class ToolTipOptions - 2024-03-27

24 Apr 2024, 07:32

Bobak wrote:
24 Apr 2024, 06:14
If I change the color and title it is not consistent.
I use the same text, namely the col[ix] in both the title and in the Tooltip, but if I press NumLock several times the title is not the same as the text every time.
Adding static here

Code: Select all

static ix := random(1, col.Length)
seems to lock the text in place...
ste(phen|ve) kunkel
Bobak
Posts: 12
Joined: 22 Oct 2023, 06:12

Re: Class ToolTipOptions - 2024-03-27

24 Apr 2024, 09:15

Thanks for the reply and fast too.
It gives the strange effect that ix is locked and thus it is always the same. The idea is that the color, text and title should change with each press of one of the two hotkeys. In the example here I chose the same text in the title and text, but note that they are not the same in the two places each time, the title does not change, the text does.

An updated script a little closer to the right one, here the title and line 1 must always be the same as each other, but vary after state of Num- and CapsLock and the color changes according to the status of NumLock, but the title and color do not change?

Code: Select all

#Requires AutoHotkey v2.0+
#SingleInstance Force
Persistent

#Include <ToolTipOptions>
ToolTipOptions.Init()

<^>!Esc:: ExitApp()
!Esc:: Reload()

~CapsLock::
~NumLock::
{
	KeyWait("NumLock")
	nl := GetKeyState("NumLock", "T")
	cl :=  GetKeyState("CapsLock", "T")

	ix := nl + 1
	col := ["RED", "GREEN", "BLUE", "YELLOW", "WHITE"]

	ToolTipOptions.SetFont("s10", "courier")
	ToolTipOptions.SetColors(col[ix])
	str := ("Numlock: " . (nl ? "ON" : "OFF") . " Capslock: " . (cl ? "ON" : "OFF"))
	ToolTipOptions.settitle(str)
	tooltip(str " `n" ix " " col[ix])
}
User avatar
boiler
Posts: 17123
Joined: 21 Dec 2014, 02:44

Re: Class ToolTipOptions - 2024-03-27

24 Apr 2024, 09:37

Bobak wrote: It gives the strange effect that ix is locked and thus it is always the same. The idea is that the color, text and title should change with each press of one of the two hotkeys.
Yes, using static like that would be expected to produce the same result each time because it will only assign ix the first time the function is called and it won't change with subsequent hotkey presses. It seems like it should work the way you have it set up, but there seems to be some issue with the ToolTipOptions class where calling the various methods a second time isn't properly updating the options correctly. I would think just me would be in the best position to troubleshoot what's causing it.
Bobak
Posts: 12
Joined: 22 Oct 2023, 06:12

Re: Class ToolTipOptions - 2024-03-27

24 Apr 2024, 10:13

Ups, the code disappeared

Code: Select all

#Requires AutoHotkey v2.0+
#SingleInstance Force
Persistent

#Include <ToolTipOptions>
ToolTipOptions.Init()

<^>!Esc:: ExitApp()
!Esc:: Reload()

~CapsLock::
~NumLock::
{

	KeyWait("NumLock")
	nl := GetKeyState("NumLock", "T")+1
	cl :=  (GetKeyState("CapsLock", "T")+1)*2
0 1
2 4
	
	ix := nl + 1
	col := ["RED", "GREEN", "BLUE", "YELLOW", "WHITE"]

	ToolTipOptions.SetFont("s10", "courier")
	ToolTipOptions.SetColors(col[ix])
	str := ("Numlock: " . (nl ? "ON" : "OFF") . " Capslock: " . (cl ? "ON" : "OFF"))
	ToolTipOptions.settitle(str)
	tooltip(str " `n" ix " " col[ix])
}
just me
Posts: 9507
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class ToolTipOptions - 2024-03-27

24 Apr 2024, 11:14

@Bobak:
How to use:
  • You must call ToolTipOptions.Init() to initialize the subclassing before you can set options.
  • Now you can call any of the other methods to set the options you want to be used by newly created tooltips. You'll find the descriptions within the class code.
  • All changes will be applied only to newly created tooltips.
  • ...
Bobak
Posts: 12
Joined: 22 Oct 2023, 06:12

Re: Class ToolTipOptions - 2024-03-27

24 Apr 2024, 12:33

I did that right after the #include.
I have now tried to move it down in the function but to no avail, just before use of setfont and it is working first time.
The text, title and color is set with first run, but title and color is not changed by subsequent calls in my example
Bobak
Posts: 12
Joined: 22 Oct 2023, 06:12

Re: Class ToolTipOptions - 2024-03-27

24 Apr 2024, 13:00

Sorry put wrong version up, I playing around

Code: Select all

#Requires AutoHotkey v2.0+
#SingleInstance Force
Persistent

#Include <ToolTipOptions>
ToolTipOptions.Init()

<^>!Esc:: ExitApp()
!Esc:: Reload()

~CapsLock::
~NumLock::
{

	KeyWait("NumLock")
	nl := GetKeyState("NumLock", "T")
	cl :=  GetKeyState("CapsLock", "T")
	ix:=nl+1
	col := ["RED", "GREEN", "BLUE", "YELLOW", "WHITE"]

	ToolTipOptions.SetFont("s10", "courier")
	ToolTipOptions.SetColors(col[ix])
	str := ("Numlock: " . (nl ? "ON" : "OFF") . " Capslock: " . (cl ? "ON" : "OFF"))
	ToolTipOptions.settitle(str)
	tooltip(str " `n" ix " " col[ix])
}
User avatar
boiler
Posts: 17123
Joined: 21 Dec 2014, 02:44

Re: Class ToolTipOptions - 2024-03-27

24 Apr 2024, 13:10

@Bobak -- With some trial and error, I have found that you can't just change the options once they're set. You have to .Reset() and then .Init() again in order to have it recognize the new options, as this code demonstrates:

Code: Select all

#Requires AutoHotkey v2.0
#Include <ToolTipOptions>

; use first set of options:
ToolTipOptions.Init()
ToolTipOptions.SetTitle('First')
ToolTipOptions.SetColors('Red')
ToolTip 'This is the FIRST tooltip that should have the title "First" and be in red'
Sleep 5000

; prepare for new options:
ToolTipOptions.Reset()
ToolTipOptions.Init()

; use second set of options:
ToolTipOptions.SetTitle('Second')
ToolTipOptions.SetColors('Green')
ToolTip 'This is the SECOND tooltip that should have the title "second" and be in green'
Sleep 5000
ExitApp

So here's the fix for your code:

Code: Select all

#Requires AutoHotkey v2.0+
#SingleInstance Force
Persistent

#Include <ToolTipOptions>

^Esc:: ExitApp()
!Esc:: Reload()

~CapsLock::
~NumLock::
{
	KeyWait("NumLock")
	tipOn := GetKeyState("NumLock", "T")
	anon := GetKeyState("CapsLock", "T")
	col := ["RED", "GREEN", "BLUE", "YELLOW", "WHITE"]
	ix := random(1, col.Length)

	ToolTipOptions.Reset()
	ToolTipOptions.Init()
	ToolTipOptions.SetFont("s10", "courier")
	ToolTipOptions.SetTitle(col[ix], 1)
	ToolTipOptions.SetColors(col[ix])
	tooltip(col[ix])
}
Bobak
Posts: 12
Joined: 22 Oct 2023, 06:12

Re: Class ToolTipOptions - 2024-03-27

24 Apr 2024, 14:33

I have also messed around and found out that with the same Tooltip id without "deleting" first, the title and color is saved, but with a Tooltip(,,,id) before subsequent calls it works, but it gives a lot of unnecessary blinking. Actually same result as reset()
just me
Posts: 9507
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class ToolTipOptions - 2024-03-27

25 Apr 2024, 04:12

Bobak wrote:... but it gives a lot of unnecessary blinking.
If you need to update the options of existing ToolTip controls frequently, you should consider whether a ToolTip is the best solution for the task.
Bobak
Posts: 12
Joined: 22 Oct 2023, 06:12

Re: Class ToolTipOptions - 2024-03-27

01 May 2024, 02:08

just me wrote:
25 Apr 2024, 04:12
Bobak wrote:... but it gives a lot of unnecessary blinking.
If you need to update the options of existing ToolTip controls frequently, you should consider whether a ToolTip is the best solution for the task.
First, thank you for helping!

It's by no means optimal, but I want this info (caps and numlock status) on the screen while I'm on a certain site with chrome, but without chrome losing focus, and I haven't been able to think of anything other than the tooltip . I have now chosen to omit color and title as indicators but only the text, it works.
It would still be smart if you could change the title and color without having to reset first.

p.s. should I mark my question as "solved"? If so, how?
just me
Posts: 9507
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class ToolTipOptions - 2024-03-27

01 May 2024, 05:37

Hi @Bobak,
you didn't create a new topic in "Ask for Help" for your question, so you cannot mark anything as solved. ;)

Would you please test the following:

Code: Select all

; ======================================================================================================================
; ToolTipOptions        -  additional options for ToolTips
;
; Tooltip control       -> https://learn.microsoft.com/en-us/windows/win32/controls/tooltip-control-reference
; TTM_SETMARGIN         = 1050
; TTM_SETTIPBKCOLOR     = 1043
; TTM_SETTIPTEXTCOLOR   = 1044
; TTM_SETTITLEW         = 1057
; TTM_UPDATETIPTEXTW    = 1081
; WM_SETFONT            = 0x30
; SetClassLong()        -> https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclasslongw
; ======================================================================================================================
Class ToolTipOptions {
   ; -------------------------------------------------------------------------------------------------------------------
   Static HTT := DllCall("User32.dll\CreateWindowEx", "UInt", 8, "Str", "tooltips_class32", "Ptr", 0, "UInt", 3
                       , "Int", 0, "Int", 0, "Int", 0, "Int", 0, "Ptr", A_ScriptHwnd, "Ptr", 0, "Ptr", 0, "Ptr", 0)
   Static SWP := CallbackCreate(ObjBindMethod(ToolTipOptions, "_WNDPROC_"), , 4) ; subclass window proc
   Static OWP := 0                                                               ; original window proc
   Static ToolTips := Map()
   ; -------------------------------------------------------------------------------------------------------------------
   Static BkgColor := ""
   Static TxtColor := ""
   Static Icon := ""
   Static Title := ""
   Static HFONT := 0
   Static Margins := ""
   ; -------------------------------------------------------------------------------------------------------------------
   Static Call(*) => False ; do not create instances
   ; -------------------------------------------------------------------------------------------------------------------
   ; Init()          -  Initialize some class variables and subclass the tooltip control.
   ; -------------------------------------------------------------------------------------------------------------------
   Static Init() {
      If (This.OWP = 0) {
         This.BkgColor := ""
         This.TxtColor := ""
         This.Icon := ""
         This.Title := ""
         This.Margins := ""
         If (A_PtrSize = 8)
            This.OWP := DllCall("User32.dll\SetClassLongPtr", "Ptr", This.HTT, "Int", -24, "Ptr", This.SWP, "UPtr")
         Else
            This.OWP := DllCall("User32.dll\SetClassLongW", "Ptr", This.HTT, "Int", -24, "Int", This.SWP, "UInt")
         OnExit(ToolTipOptions._EXIT_, -1)
         Return This.OWP
      }
      Else
         Return False
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ;  Reset()        -  Close all existing tooltips, delete the font object, and remove the tooltip's subclass.
   ; -------------------------------------------------------------------------------------------------------------------
   Static Reset() {
      If (This.OWP != 0) {
         For HWND In This.ToolTips.Clone()
            DllCall("DestroyWindow", "Ptr", HWND)
         This.ToolTips.Clear()
         If This.HFONT
            DllCall("DeleteObject", "Ptr", This.HFONT)
         This.HFONT := 0
         If (A_PtrSize = 8)
            DllCall("User32.dll\SetClassLongPtrW", "Ptr", This.HTT, "Int", -24, "Ptr", This.OWP, "UPtr")
         Else
            DllCall("User32.dll\SetClassLongW", "Ptr", This.HTT, "Int", -24, "Int", This.OWP, "UInt")
         This.OWP := 0
         Return True
      }
      Else
         Return False
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; SetColors()     -  Set or remove the text and/or the background color for the tooltip.
   ; Parameters:
   ;     BkgColor    -  color value like used in Gui.BackColor(...)
   ;     TxtColor    -  see above.
   ; -------------------------------------------------------------------------------------------------------------------
   Static SetColors(BkgColor := "", TxtColor := "") {
      This.BkgColor := BkgColor = "" ? "" : BGR(BkgColor)
      This.TxtColor := TxtColor = "" ? "" : BGR(TxtColor)
      BGR(Color, Default := "") { ; converts colors to BGR
         ; HTML Colors (BGR)
         Static HTML := {AQUA:   0xFFFF00, BLACK: 0x000000, BLUE:   0xFF0000, FUCHSIA: 0xFF00FF, GRAY:  0x808080,
                         GREEN:  0x008000, LIME:  0x00FF00, MAROON: 0x000080, NAVY:    0x800000, OLIVE: 0x008080,
                         PURPLE: 0x800080, RED:   0x0000FF, SILVER: 0xC0C0C0, TEAL:    0x808000, WHITE: 0xFFFFFF,
                         YELLOW: 0x00FFFF}
         If HTML.HasProp(Color)
            Return HTML.%Color%
         If (Color Is String) && IsXDigit(Color) && (StrLen(Color) = 6)
            Color := Integer("0x" . Color)
         If IsInteger(Color)
            Return ((Color >> 16) & 0xFF) | (Color & 0x00FF00) | ((Color & 0xFF) << 16)
         Return Default
      }
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; SetFont()       -  Set or remove the font used by the tooltip.
   ; Parameters:
   ;     FntOpts     -  font options like Gui.SetFont(Options, ...)
   ;     FntName     -  font name like Gui.SetFont(..., Name)
   ; -------------------------------------------------------------------------------------------------------------------
   Static SetFont(FntOpts := "", FntName := "") {
      Static HDEF := DllCall("GetStockObject", "Int", 17, "UPtr") ; DEFAULT_GUI_FONT
      Static LOGFONTW := 0
      If (FntOpts = "") && (FntName = "") {
         If This.HFONT
            DllCall("DeleteObject", "Ptr", This.HFONT)
         This.HFONT := 0
         LOGFONTW := 0
      }
      Else {
         If (LOGFONTW = 0) {
            LOGFONTW := Buffer(92, 0)
            DllCall("GetObject", "Ptr", HDEF, "Int", 92, "Ptr", LOGFONTW)
         }
         HDC := DllCall("GetDC", "Ptr", 0, "UPtr")
         LOGPIXELSY := DllCall("GetDeviceCaps", "Ptr", HDC, "Int", 90, "Int")
         DllCall("ReleaseDC", "Ptr", HDC, "Ptr", 0)
         If (FntOpts != "") {
            For Opt In StrSplit(RegExReplace(Trim(FntOpts), "\s+", " "), " ") {
               Switch StrUpper(Opt) {
                  Case "BOLD":      NumPut("Int", 700, LOGFONTW, 16)
                  Case "ITALIC":    NumPut("Char",  1, LOGFONTW, 20)
                  Case "UNDERLINE": NumPut("Char",  1, LOGFONTW, 21)
                  Case "STRIKE":    NumPut("Char",  1, LOGFONTW, 22)
                  Case "NORM":      NumPut("Int", 400, "Char", 0, "Char", 0, "Char", 0, LOGFONTW, 16)
                  Default:
                     O := StrUpper(SubStr(Opt, 1, 1))
                     V := SubStr(Opt, 2)
                     Switch O {
                        Case "C":
                           Continue ; ignore the color option
                        Case "Q":
                           If !IsInteger(V) || (Integer(V) < 0) || (Integer(V) > 5)
                              Throw ValueError("Option Q must be an integer between 0 and 5!", -1, V)
                           NumPut("Char", Integer(V), LOGFONTW, 26)
                        Case "S":
                           If !IsNumber(V) || (Number(V) < 1) || (Integer(V) > 255)
                              Throw ValueError("Option S must be a number between 1 and 255!", -1, V)
                           NumPut("Int", -Round(Integer(V + 0.5) * LOGPIXELSY / 72), LOGFONTW)
                        Case "W":
                           If !IsInteger(V) || (Integer(V) < 1) || (Integer(V) > 1000)
                              Throw ValueError("Option W must be an integer between 1 and 1000!", -1, V)
                           NumPut("Int", Integer(V), LOGFONTW, 16)
                        Default:
                           Throw ValueError("Invalid font option!", -1, Opt)
                     }
                  }
               }
            }
         NumPut("Char", 1, "Char", 4, "Char", 0, LOGFONTW, 23) ; DEFAULT_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS
         NumPut("Char", 0, LOGFONTW, 27) ; FF_DONTCARE
         If (FntName != "")
            StrPut(FntName, LOGFONTW.Ptr + 28, 32)
         If !(HFONT := DllCall("CreateFontIndirectW", "Ptr", LOGFONTW, "UPtr"))
            Throw OSError()
         If This.HFONT
            DllCall("DeleteObject", "Ptr", This.HFONT)
         This.HFONT := HFONT
      }
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; SetMargins()    -  Set or remove the margins used by the tooltip
   ; Parameters:
   ;     L, T, R, B  -  left, top, right, and bottom margin in pixels.
   ; -------------------------------------------------------------------------------------------------------------------
   Static SetMargins(L := 0, T := 0, R := 0, B := 0) {
      If ((L + T + R + B) = 0)
         This.Margins := 0
      Else {
         This.Margins := Buffer(16, 0)
         NumPut("Int", L, "Int", T, "Int", R, "Int", B, This.Margins)
      }
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; SetTitle()      -  Set or remove the title and/or the icon displayed on the tooltip.
   ; Parameters:
   ;     Title       -  string to be used as title.
   ;     Icon        -  icon to be shown in the ToolTip.
   ;                    This can be the number of a predefined icon (1 = info, 2 = warning, 3 = error
   ;                    (add 3 to display large icons on Vista+) or a HICON handle.
   ; -------------------------------------------------------------------------------------------------------------------
   Static SetTitle(Title := "", Icon := "") {
      Switch {
         Case (Title = "") && (Icon != ""):
            This.Icon := Icon
            This.Title := " "
         Case (Title != "") && (Icon = ""):
            This.Icon := 0
            This.Title := Title
         Default:
            This.Icon := Icon
            This.Title := Title
      }
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; For internal use only!
   ; -------------------------------------------------------------------------------------------------------------------
   Static _WNDPROC_(hWnd, uMsg, wParam, lParam) {
      ; WNDPROC -> https://learn.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-wndproc
      Switch uMsg {
         Case 0x0411: ; TTM_TRACKACTIVATE - just handle the first message after the control has been created
            ; If This.ToolTips.Has(hWnd) && (This.ToolTips[hWnd] = 0) {
               If (This.BkgColor != "")
                  SendMessage(1043, This.BkgColor, 0, hWnd)                ; TTM_SETTIPBKCOLOR
               If (This.TxtColor != "")
                  SendMessage(1044, This.TxtColor, 0, hWnd)                ; TTM_SETTIPTEXTCOLOR
               If This.HFONT
                  SendMessage(0x30, This.HFONT, 0, hWnd)                   ; WM_SETFONT
               If (Type(This.Margins) = "Buffer")
                  SendMessage(1050, 0, This.Margins.Ptr, hWnd)             ; TTM_SETMARGIN
               If (This.Icon != "") || (This.Title != "")
                  SendMessage(1057, This.Icon, StrPtr(This.Title), hWnd)   ; TTM_SETTITLE
               This.ToolTips[hWnd] := 1
            ; }
         Case 0x0001: ; WM_CREATE
            DllCall("UxTheme.dll\SetWindowTheme", "Ptr", hWnd, "Ptr", 0, "Ptr", StrPtr(""))
            This.ToolTips[hWnd] := 0
         Case 0x0002: ; WM_DESTROY
            This.ToolTips.Delete(hWnd)
      }
      Return DllCall(This.OWP, "Ptr", hWnd, "UInt", uMsg, "Ptr", wParam, "Ptr", lParam, "UInt")
   }
   ; -------------------------------------------------------------------------------------------------------------------
   Static _EXIT_(*) {
      If (ToolTipOptions.OWP != 0)
         ToolTipOptions.Reset()
   }
}

; ----------------------------------------------------------------------------------------------------------------------
ToolTipOptions.Init()
; ----------------------------------------------------------------------------------------------------------------------
ToolTipOptions.SetFont("s48 underline italic", "Consolas")
ToolTipOptions.SetMargins(12, 12, 12, 12)
ToolTipOptions.SetTitle("All right!" , 4)
ToolTipOptions.SetColors("008000", "0xFFFFFF")
TTHWND := ToolTip("Hello world!")
Loop {
   Sleep(1000)
   ToolTipOptions.SetTitle("Maybe not!" , 5)
   ToolTipOptions.SetColors("0xFFFFFF", "008000")
   ToolTip("Hello world!")
   Sleep(1000)
   ToolTipOptions.SetTitle("All right!" , 4)
   ToolTipOptions.SetColors("008000", "0xFFFFFF")
   ToolTip("Hello world!")
}
; ----------------------------------------------------------------------------------------------------------------------
Esc::ExitApp
If you are satisfied I'll update the class code in the OP.

Return to “Scripts and Functions (v2)”

Who is online

Users browsing this forum: songdg and 23 guests