- Table of contents
- Xtooltip - v1.1.1
- AutoHotkey.com link
- Reddit.com link
- Quick start
- Related libraries
- Options
- Themes
- Theme groups
- XttPool
- Constants
- Output precision
- Clip precision
- Quality
- Pitch
- Charset (character set)
- Font script (character set)
- Font family
- Font weight
- Font type
- Collections
- Changelog
- Table of contents generated by Headers2ToC.ahk
Xtooltip is a class that implements most of the Windows API tools regarding tooltip controls,
allowing developers to create and use highly customizable and responsive tooltip windows with as
little as two lines of code.
A tooltip is a popup window that displays information. Tooltips are often designed to appear when the user hovers the mouse over a control or specific area for a short period of time, displaying information related to that particular control / area.
The AHK ToolTip function can be used to
display text in a tooltip window, and that window can be
manipulated like other windows using WinGetPos and the other
Win... functions. However, ToolTip
does not provide tools for customizing the window or its behavior.
Xtooltip bridges the gap between our AHK code and the Windows API, providing the following tools:
- Associate a tooltip with a control or window so the tooltip appears when the mouse hovers over the window.
- Associate a tooltip with a rectangular area so the tooltip appears when the mouse hovers over the area.
- Create a "tracking" tooltip that can be displayed at any position at-will.
- Create customizable themes to quickly swap all customizable attributes.
- Create theme groups to group together tooltips and themes to keep your code organized.
- Customize all available attributes:
- Background color
- Corner preference (rounded corners)
- Font
- Escapement
- Face name
- Font size
- Italic
- Quality
- Strikeout
- Underline
- Weight
- Icon
- Margins
- Maximum width
- Text color
- Title
Learning to use Xtooltip is easy and brief. Read the Quick start guide (< 5 mins)
and you'll be ready to go.
Be sure to check out the sandbox script test\sandbox.ahk that allows you to adjust the options and see what they look like immediately, and the demo script test\demo.ahk which runs the snippets in Quick start section.
This is the sandbox.
Join the discussion on AutoHotkey.com: https://www.autohotkey.com/boards/viewtopic.php?f=83&t=139315
Join the discussion on Reddit: https://www.reddit.com/r/AutoHotkey/comments/1ob8knu/xtooltip_a_library_that_provides_functions_for/
The following is a brief introduction intended to share enough information for you to make use of this library. Run this example with file test\demo.ahk.
- Clone the repository.
git clone https://github.com/Nich-Cebolla/AutoHotkey-Xtooltip- Copy Xtooltip.ahk to your lib folder.
xcopy C:\users\you\path\to\AutoHotkey-Xtooltip\src\Xtooltip.ahk C:\users\you\documents\AutoHotkey\lib\Xtooltip.ahk- Include the library in your script.
#include <Xtooltip>- Create a theme
theme := XttTheme({
BackColor: 0
, FaceName: "Segoe Ui"
, FontSize: 12
, Italic: true
, Quality: 5
, Margin: XttRect.Margin(3)
, MaxWidth: 250
, TextColor: XttRgb(0, 255, 255)
, Weight: 700
})- Create an Xtooltip, optionally passing an options object.
xtt := Xtooltip({ Theme: theme })- Associate one or more tools with the tooltip.
- Associate a control with the tooltip to cause the tooltip to appear when the user hovers
the mouse over the control.
g := Gui() g.SetFont("s11 q5") btn := g.Add("Button", "w125", "Click me") xtt.AddControl("Name1", "Click the button!", btn)
- Associate a control's client area to cause the tooltip to appear when
the user hovers the mouse over the area.
edt := g.Add("Edit", "w400 r5") xtt.AddControlRect("Name2", "Input the information!", edt)
- Associate a rectangular area within a window's client area to cause the tooltip to appear when
the user hovers the mouse over the area.
edt.GetPos(&x, &y, &w, &h) l := x t := y + h + g.MarginY r := w b := y + h + g.MarginY + 400 xtt.AddRect("Name3", "Blank area", g.Hwnd, l, t, r, b)
- Create a "tracking" tooltip that can be shown / hidden / moved at-will. Only one tooltip window
can be visible per tooltip object at a time, so if we want to be able to display both the tracking
and non-tracking tooltips, we need a new
Xtooltipobject.; Let's use a similar theme but with a new text color. themeRed := theme.Clone() themeRed.TextColor := XttRgb(255, 0, 0) xttTracking := Xtooltip({ Theme: themeRed }) g.GetPos(&gx, &gy, &gw, &gh) gx += gw - 40 gy += gh - 50 xttTracking.AddTracking("Name4", "Tracking tooltip information", , , true, gx, gy)
Don't forget to leave a ⭐ if you think Xtooltip is pretty awesome!
Below are some libraries that may pair well with Xtooltip.
Logfont: A full-featured font object.Xtooltiphas a built-inXttLogfontclass which encapsulates the core functionality necessary for adjusting the control's font, but does not include functionality related to enumerating a system's fonts and evaluating the fonts. If your application would benefit from being able to find the optimal font available on the system, check out Logfont.MsLlHookStruct: Create a lower-level mouse hook, perhaps to have a tooltip follow the mouse around the screen.WindowSubclass: Subclass the tooltip's parent window to intercept messages and customize behavior.FillStr: A simple text formatting class.
This is a list and description of the available options to pass to Xtooltip.Prototype.__New.
If there is a default value, the format for the option is:
- { Type } [
Options.<Name> = <default value>] - description
If there is not a default value, the format for the option is:
- { Type } [
Options.<Name>] - description
If Options.Theme or Options.ThemeGroup are set, all other customization options are ignored.
Options.Theme supercedes Options.ThemeGroup.
- { Integer } [
Options.AddExStyle] - Extended window style flags to use in addition to the defaultOptions.ExStyle. - { Integer } [
Options.AddStyle] - Window style flags to use in addition to the defaultOptions.Style. - { Boolean } [
Options.AlwaysOnTop = true] - If true, the WS_EX_TOPMOST flag is added to the extended style flags. - { Integer } [
Options.BackColor] - The COLORREF representing the background color. UseXttRgb(r, g, b)to convert RGB to COLORREF. - { Integer } [
Options.CornerPreference] - One of the following:- DWMWCP_DEFAULT = 0
- DWMWCP_DONOTROUND = 1
- DWMWCP_ROUND = 2
- DWMWCP_ROUNDSMALL = 3
- { Float } [
Options.Escapement = 0] - The font escapement. - { Integer } [
Options.ExStyle = WS_EX_NOACTIVATE] - Extended window style flags. - { String } [
Options.FaceName] - The font name to use. - { Float } [
Options.FontSize] - The font size in points (Round(LogfontObj.Height * -72 / LogfontObj.Dpi, 2)). - { Integer } [
Options.HwndParent = A_ScriptHwnd] - The parent window's handle. - { Integer } [
Options.Icon = 0] - The icon to display next to the title. - { Integer } [
Options.Instance = 0] - The value to pass tohInstanceparameter ofCreateWindowExW. Leave this 0. - { Integer } [
Options.Italic = 0] - Set to 1 to italicize the text. - { Integer } [
Options.MarginB] - The bottom margin padding in pixels. - { Integer } [
Options.MarginL] - The left margin padding in pixels. - { Integer } [
Options.MarginR] - The right margin padding in pixels. - { Integer } [
Options.Margins] - A single integer representing the number of pixels to apply to all four margins. Use this instead of setting each individually. If you include one or more of the individual margin options in addition to this one, the individual option will supervedeOptions.Marginsfor that attribute. - { Integer } [
Options.MarginT] - The top margin padding in pixels. - { Integer } [
Options.MaxWidth] - The value to set as the tooltip window's maximum width. See Microsoft's documentation about the maximum width. - { Integer } [
Options.Menu = 0] - The value to pass to thehMenuparameter ofCreateWindowExW. Leave this 0. - { String } [
Options.Name] - A name to associate with theXtooltipobject. See Collections. - { Integer } [
Options.Param = 0] - The value to pass to thelParamparameter ofCreateWindowExW. - { Integer } [
Options.Quality = 5] - The font quality. - { Integer } [
Options.Strikeout = 0] - Set to 1 to strikeout the text. - { Integer } [
Options.Style = WS_BORDER | WS_POPUP | TTS_NOPREFIX] - The window style flags. - { Integer } [
Options.TextColor] - The COLORREF representing the text color. UseXttRgb(r, g, b)to convert RGB to COLORREF. - { XttTheme } [
Options.Theme] - TheXttThemeobject to apply to the tooltip. See Themes. - { XttThemeGroup } [
Options.ThemeGroup] - TheXttThemeGroupobject to which to add theXtooltipobject. See Theme groups. - { String } [
Options.Title] - The title to display in the tooltip window. - { Integer } [
Options.Underline = 0] - Set to 1 to underline the text. - { Integer } [
Options.Weight = 400] - The font weight. - { Integer } [
Options.WindowName = 0] - The pointer to a null-terminated string that is passed tolpWindowNameparameter ofCreateWindowExW. Leave this 0.
Themes are the primary means of styling a tooltip window. The XttTheme object encapsulates all of
the logic needed to keep your code organized and concise.
- Create a theme
Pass an options object to the constructor to get a theme object.
theme := XttTheme({ ... })- Apply the theme to an existing tooltip
Applying the theme activates the theme's options. If any style options are absent from the theme object,
the Xtooltip object will retain its current values for those options.
xtt := Xtooltip()
theme := XttTheme()
xtt.Theme := theme- Apply the theme to a new tooltip
Pass the XttTheme object as Options.Theme.
theme := XttTheme()
xtt := Xtooltip({ Theme: theme })The options are also seen in the parameter hint above XttTheme.Prototype.__New.
The following are the available options.
- BackColor
- Font :
Options.Fontcan be anXttLogfontobject, or include any of the following properties onOptions.- Escapement
- FaceName
- FontSize
- Italic
- Quality
- Strikeout
- Underline
- Weight
- Icon
- Margin :
Options.Margincan be anXttRectobject, a Buffer object, or include any of the following properties onOptions.- MarginL
- MarginT
- MarginR
- MarginB
- MaxWidth
- Name : The name of the theme. This is used to retrieve the theme object from the collection.
- TextColor
- Title
Theme groups, facilitated by the XttThemeGroup class, are comprised of a collection of Xtooltip
objects and a collection of XttTheme objects. The purpose of a theme group is to group together
Xtooltip objects that will always use the same theme, and to group together XttTheme objects
so the entire group's active theme can be swapped to a new theme with one line of code.
The inspiration for the theme group concept was dark mode / light mode. By creating two themes
and associating the themes with a collection of Xtooltip objects, the entire group can be swapped
between dark / light mode by calling one line of code.
See Collections for information about the collections concept.
A theme group example is included in the demo test\demo.ahk.
- Create a theme group
; Register the collection
Xtooltip.RegisterAllCollections()
; Create two themes
darkMode := XttTheme("dark", {
BackColor: 0
, FaceName: "Segoe Ui"
, FontSize: 12
, Quality: 5
, Margin: XttRect.Margin(3)
, TextColor: XttRgb(255, 255, 230)
, Weight: 700
})
lightMode := XttTheme("light", {
BackColor: XttRgb(255, 255, 240)
, FaceName: "Segoe Ui"
, FontSize: 12
, Quality: 5
, Margin: XttRect.Margin(3)
, TextColor: 0
, Weight: 700
})
; Create a theme group object
themeGroup := XttThemeGroup("MyThemeGroup", [ darkMode, lightMode ])- Activate a theme
themeGroup.ThemeActivate("light")- Add an existing Xtooltip object to the theme group
themeGroup.XttAdd(xtt)- Associate a new Xtooltip object with the theme group
xtt := Xtooltip({ ThemeGroup: themeGroup })- Swap themes using the Xtooltip object as the subject. This assumes the collections have been registered.
xtt.ThemeGroup.ThemeActivate("dark")- Create light mode / dark mode schema
themeGroup.SetLightMode("light", "dark")
; Now we can toggle the themes
themeGroup.ToggleLightMode()XttPool was introduced v1.1.0. When using XttPool, displaying a tooltip at a specific location
requires only one line of code (after creating the object).
Here is how you create an XttPool object:
#include <Xtooltip>
; Create a theme
theme := XttTheme("MyTheme", {
BackColor: XttRgb(255, 255, 255)
, FaceName: 'Segoe Ui'
, FontSize: 12
, Quality: 5
, Margin: XttRect.Margin(3)
, MaxWidth: 400
, TextColor: XttRgb(255, 0, 235)
, Weight: 400})
; Create a theme group and activate the theme
themeGroup := XttThemeGroup("MyGroup", theme)
themeGroup.ThemeActivate("MyTheme")
; Create the `XttPool` object. The constructor requires an `XttThemeGroup` object
pool := XttPool(themeGroup)Once the object is created, your code simply calls its methods to display a tooltip.
You can call the methods multiple times to display any number of tooltip windows at the same time.
; Show a tooltip at 100, 100 indefinitely
ttItem := pool("Hello, world!", 100, 100)
; When the tooltip is no longer needed, just call the object
ttItem() ; this hides the tooltip window; Show a tooltip at 100, 100 for 2 seconds
pool("Hello, world!", 100, 100, 2000); Show a tooltip next to the mouse pointer for 3 seconds
pool.ShowByMouse("Hello, world!", 3000); Show a tooltip next to the currently active window for 3 seconds
pool.ShowByRect("Hello, world!", WinGetId("A"), 3000)XttPool inherits from Array, and itself is a collection of XttPool.Item objects. When
your code calls one of XttPool's methods, it checks if it has any XttPool.Item objects available,
and, if it does, it uses one to display the intended message at the intended location. If it does not,
it simply creates a new XttPool.Item object and uses that.
This allows you to display any number of tooltip windows at the same time, without the hassle of setting up each tracking tooltip individually.
There is a demo script "test\test-XttPool.ahk" that allows you to try out two methods:
XttPool.Prototype.ShowByMouse- Displays a tooltip window by the mouse pointer.XttPool.Prototype.ShowByRect- Displays a tooltip window adjacent to a window or rectangle.
The methods have a parameter Duration. If your code sets Duration, then the tooltip window
will be hidden after Duration elapses, and the XttPool.Item will automatically be added
back to the collection to be used again in the future. If your code does not set the Duration
parameter, then the tooltip window will be displayed indefinitely. The XttPool methods
return the XttPool.Item object; when your application is done with the tooltip window, you just
call the object and the tooltip window is hidden and the item is added back to the collection.
The following methods apply the XttThemeGroup's active theme to the tooltip:
XttPool.Prototype.CallXttPool.Prototype.ShowByMouseXttPool.Prototype.ShowByRect
The following methods have a parameter Theme which your code can set with a theme to specify
the theme to apply to the tooltip:
XttPool.Prototype.ShowExXttPool.Prototype.ShowByMouseExXttPool.Prototype.ShowByRectEx
To add more themes to the theme group use XttPool.Prototype.ThemeAdd.
To change the active theme use XttPool.Prototype.ThemeActivate.
The XttPool.Item object is returned by the XttPool instance methods. Your code
can cache a reference to the XttPool.Item object and use it to manipulate the tooltip
window at-will. XttPool.Item has the following methods:
XttPool.Item.Prototype.Call- Hides the tooltip window and returns theXttPool.Itemobject to its parent collection.XttPool.Item.Prototype.Move- Moves the tooltip window to X,Y coordinates.XttPool.Item.Prototype.MoveByMouse- Moves the tooltip window near the mouse pointer.XttPool.Item.Prototype.MoveByRect- Moves the tooltip window adjacent to a window or rectangle.XttPool.Item.Prototype.SetText- Changes the text displayed in the tooltip window.XttPool.Item.Prototype.SetTheme- Changes the tooltip's theme.
The following are some constant values related to fonts, to be used with the XttLogfont class.
| Name | Value |
|---|---|
| OUT_DEFAULT_PRECIS | 0 |
| OUT_STRING_PRECIS | 1 |
| OUT_CHARACTER_PRECIS | 2 |
| OUT_STROKE_PRECIS | 3 |
| OUT_TT_PRECIS | 4 |
| OUT_DEVICE_PRECIS | 5 |
| OUT_RASTER_PRECIS | 6 |
| OUT_TT_ONLY_PRECIS | 7 |
| OUT_OUTLINE_PRECIS | 8 |
| OUT_SCREEN_OUTLINE_PRECIS | 9 |
| OUT_PS_ONLY_PRECIS | 10 |
| Name | Value |
|---|---|
| CLIP_DEFAULT_PRECIS | 0 |
| CLIP_CHARACTER_PRECIS | 1 |
| CLIP_STROKE_PRECIS | 2 |
| CLIP_MASK | 15 |
| CLIP_LH_ANGLES | 16 |
| CLIP_TT_ALWAYS | 32 |
| CLIP_DFA_DISABLE | 64 |
| CLIP_EMBEDDED | 128 |
| Name | Value |
|---|---|
| DEFAULT_QUALITY | 0 |
| DRAFT_QUALITY | 1 |
| PROOF_QUALITY | 2 |
| NONANTIALIASED_QUALITY | 3 |
| ANTIALIASED_QUALITY | 4 |
| CLEARTYPE_QUALITY | 5 |
| CLEARTYPE_NATURAL_QUALITY | 6 |
| Name | Value |
|---|---|
| DEFAULT_PITCH | 0 |
| FIXED_PITCH | 1 |
| VARIABLE_PITCH | 2 |
| MONO_FONT | 8 |
| Name | Value |
|---|---|
| ANSI_CHARSET | 0 |
| DEFAULT_CHARSET | 1 |
| SYMBOL_CHARSET | 2 |
| SHIFTJIS_CHARSET | 128 |
| HANGEUL_CHARSET | 129 |
| HANGUL_CHARSET | 129 |
| GB2312_CHARSET | 134 |
| CHINESEBIG5_CHARSET | 136 |
| OEM_CHARSET | 255 |
| JOHAB_CHARSET | 130 |
| HEBREW_CHARSET | 177 |
| ARABIC_CHARSET | 178 |
| GREEK_CHARSET | 161 |
| TURKISH_CHARSET | 162 |
| VIETNAMESE_CHARSET | 163 |
| THAI_CHARSET | 222 |
| EASTEUROPE_CHARSET | 238 |
| RUSSIAN_CHARSET | 204 |
| MAC_CHARSET | 77 |
| BALTIC_CHARSET | 186 |
| Name | Value |
|---|---|
| FS_LATIN1 | 0x00000001 |
| FS_LATIN2 | 0x00000002 |
| FS_CYRILLIC | 0x00000004 |
| FS_GREEK | 0x00000008 |
| FS_TURKISH | 0x00000010 |
| FS_HEBREW | 0x00000020 |
| FS_ARABIC | 0x00000040 |
| FS_BALTIC | 0x00000080 |
| FS_VIETNAMESE | 0x00000100 |
| FS_THAI | 0x00010000 |
| FS_JISJAPAN | 0x00020000 |
| FS_CHINESESIMP | 0x00040000 |
| FS_WANSUNG | 0x00080000 |
| FS_CHINESETRAD | 0x00100000 |
| FS_JOHAB | 0x00200000 |
| FS_SYMBOL | 0x80000000 |
| Name | Value |
|---|---|
| FF_DONTCARE | 0 |
| FF_ROMAN | 16 |
| FF_SWISS | 32 |
| FF_MODERN | 48 |
| FF_SCRIPT | 64 |
| FF_DECORATIVE | 80 |
| Name | Value |
|---|---|
| FW_DONTCARE | 0 |
| FW_THIN | 100 |
| FW_EXTRALIGHT | 200 |
| FW_LIGHT | 300 |
| FW_NORMAL | 400 |
| FW_MEDIUM | 500 |
| FW_SEMIBOLD | 600 |
| FW_BOLD | 700 |
| FW_EXTRABOLD | 800 |
| FW_HEAVY | 900 |
See https://learn.microsoft.com/en-us/previous-versions/dd162618(v=vs.85)
| Name | Value |
|---|---|
| RASTER_FONTTYPE | 0x0001 |
| DEVICE_FONTTYPE | 0x0002 |
| TRUETYPE_FONTTYPE | 0x0004 |
There are three optional built-in collections that store references to Xtooltip, XttTheme,
and XttThemeGroup objects by name to make them accessible globally without polluting the
global namespace. You will want to use these when using theme groups in particular because
they are necessary to be able to access an Xtooltip's theme group from the "ThemeGroup" property.
To activate all three collections, call the static method Xtooltip.RegisterAllCollections.
You can also activate individual collections using the individual methods.
Xtooltip.RegisterAllCollections()Calling Xtooltip.Prototype.Dispose will delete the cached reference to itself, but not any themes
or theme groups to which it is associated.
You can free the resources by deregistering the collections.
Xtooltip.DeregisterAllCollections()Internally, registering a collection creates a map object set to a property on the Xtooltip class
object. The dynamic instance properties "ThemeCollection", "ThemeGroupCollection", and "XttCollection"
exist on Xtooltip.Base.Prototype and point to these map objects.
I implemented this concept using this design to enable the possibility to subclass Xtooltip and/or
its related classes without sacrificing the built-in collection design. By having the class instance
methods point to the objects set to properties on the class object, this makes it possible for a
class which inherits from Xtooltip to override those properties to implement its own collection
system, and also makes it possible for the inheritor to not do this to continue using the built-in
collection system.
For example, this is the code for Xtooltip.RegisterThemeGroupCollection:
class Xtooltip {
static RegisterThemeGroupCollection(ThemeGroupCollection?, CaseSense := false) {
return this.ThemeGroupCollection := ThemeGroupCollection ?? XttThemeGroupCollection(CaseSense)
}
}And this is the code for Xtooltip.Base:
class Xtooltip {
class Base {
ThemeCollection => Xtooltip.ThemeCollection
ThemeGroupCollection => Xtooltip.ThemeGroupCollection
XttCollection => Xtooltip.XttCollection
}
}I could write a class that extends Xtooltip and overrides the instance properties:
class XtooltipEx extends Xtooltip {
ThemeCollection {
; ... custom logic
}
ThemeGroupCollection {
; ... custom logic
}
XttCollection {
; ... custom logic
}
}Or I could write a class that extends Xtooltip and does not override the instance properties, to continue using the existing system.
To this end, I recommend you write your code to always access the collections via the instance properties instead of the class properties.
-
2026-03-14: v1.1.1
- Fix:
Xtooltip.Prototype.AddControlRectto calculate the correct rectangle using the control's position.
- Add:
XttPool.Prototype.ShowExXttPool.Prototype.ShowByMouseExXttPool.Prototype.ShowByRectExXttPool.Prototype.ThemeActivateXttPool.Prototype.ThemeAddXttPool.Item.Prototype.SetTheme- Script test\test-XttPool-1.1.1.ahk
- Change:
XttPool.Prototype.Call,XttPool.Prototype.ShowByMouse, andXttPool.Prototype.ShowByRectto apply theXttThemeGroup's active theme to the tooltip before displaying the tooltip.Xtooltip_SetConstantsto set global variables for each dll procedure call.- All
DllCallcalls to use the procedure address cached in a global variable.
- Fix:
-
2026-03-13: v1.1.0
- Fix:
Xtooltip.Prototype.GetToolInfoObjto not throw a property error due to code error.
- Add:
XttRectMoveAdjacent- A function that calculates the optimal position when moving one rectangle adjacent to another.Xtooltip.Prototype.TrackMoveByMouse- A method that callsXttRectMoveAdjacentto calculate the best position to move a tracking tooltip window by the mouse.Xtooltip.Prototype.TrackMoveByRect- A method that callsXttRectMoveAdjacentto calculate the best position to move a tracking tooltip window by a window or rectangle.XttPoolandXttPool.Item- New classes that make it easier to display tooltips at specific locations on the screen using coordinates. See documentation section XttPool.- Script test\test-XttPool.ahk
- Fix:
-
2026-01-27: v1.0.5
- Add:
Options.CornerPreference- Calls DwmSetWindowAttribute to modify the DWM_WINDOW_CORNER_PREFERENCE value. - Change: Thrown errors no longer pass
-1to thewhatparameter of theErrorobject constructor.
- Add:
-
2025-11-15: v1.0.4
XttThemeGroup.Prototype.ApplySelect, which callsXttThemeGroup.Prototype.ApplySelection. Added because I intended for the method to have the same name asXttTheme.Prototype.ApplySelect.
-
2025-11-15: v1.0.3
- Add:
XttTheme.Prototype.ApplySelection, which callsXttTheme.Prototype.ApplySelect. Added because I intended for the method to have the same name asXttThemeGroup.Prototype.ApplySelection.
- Add:
-
2025-10-24: v1.0.2
- Fix:
CWPRETSTRUCT, a class used only in test\sandbox.ahk, had a byte alignment error. This is fixed.
- Fix:
-
2025-10-22: v1.0.1
- Change:
Xtooltip.Prototype.ThemeGroup.Getnow includes an error message that is thrown when the property is accessed without first registering a collection.
- Change:
