So, the time has come for my first post in the "Tips & Tricks" section (it was about time, eh?), where I'll be writing about making a custom tooltip skin.
- all the visual and/or functional capabilities that a Rainmeter skin provides (e.g. fonts, alignments, fades, even short animations, histograms, etc.)
- no more "regular" flickering from the tooltip
- no more flickering due to the update rate of the OS tooltip being tied up to the parent skin's update rate (such as the flickering tooltips of animated skins)
- no more overriding the content of the meter that triggers the tooltip on hover (since the OS tooltip's top-left corner is the mouse position)
- more lines of text (wrapped or not) for the tooltip title
- more image types (or more than one image) that could be displayed as the "tooltip icon"
- no more "unexpected results" (as per the manual) when the maximum tooltip width is less than the width of the (unwrappable) tooltip title
- and the list could go on ...
For all these (justified or not) concerns and wishes, my custom tooltip skin is the solution. It's basically just another (very simple) Rainmeter skin that behaves like an OS tooltip would. It will always display within the usable screen area (actually called "work area" in Rainmeter) and its position would be adjusted to circumstances, while still displaying "aligned" to the position of its parent skin (it can be made to align to a particular meter in the parent skin though, if needed - it's a matter of adjusting the PX, PY, PW and PH variables below to the coordinates and dimensions of that particular meter). Its only disadvantage (yes, there is one) is that when another skin has its Stay Topmost activated and the custom tooltip is shown in the same area, they will both "fight to stay on top", resulting in some flickering between them - but then, this is also true regarding the OS tooltips or regular Rainmeter skins staying topmost, so nothing special. Also, not exactly a disadvantage but a practical impossibility at the moment is that it can't be displayed according to the mouse position (rather than the position of the skin or meter the mouse is hovered on) - this, unless the Rainmeter developers add the possibility to get the $MouseX$ and $MouseY$ variables not only on click or scroll, but also on hover, will continue to remain an impossible task (although maybe there could be a plugin who does just that).
Enough with the introduction, let's get to business (I'm assuming the same root config folder for these, i.e. "Custom Tooltip Skin" in the main Skins directory):
Skin.ini (the parent skin, i.e. the skin that triggers the tooltip skin - located in Custom Tooltip Skin\Skin folder)
Code: Select all
[Variables]
TS=0
[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
---Measures---
[MeasureSomethingChanging]
Measure=Calc
Formula=(MeasureSomethingChanging>=9?1:MeasureSomethingChanging+1)
---Measures Tooltip---
[MeasurePopulateTooltip]
Measure=Calc
IfCondition=(#TS#=1)
IfTrueAction=[!SetOption MeterTooltipIcon ImageName "#@##CURRENTFILE#.png" "#ROOTCONFIG#\Tooltip"][!SetOption MeterTooltipTitle Text "Tooltip Title" "#ROOTCONFIG#\Tooltip"][!SetOption MeterTooltipText Text "Tooltip Content - Row 1: [MeasureSomethingChanging]#CRLF#Tooltip Content - Row 2: [MeasureSomethingChanging]#CRLF#Tooltip Content - Row 3: [MeasureSomethingChanging]#CRLF#Tooltip Content - Row 4: [MeasureSomethingChanging]#CRLF#Tooltip Content - Row 5: [MeasureSomethingChanging]" "#ROOTCONFIG#\Tooltip"][!UpdateMeterGroup TooltipGroup "#ROOTCONFIG#\Tooltip"][!Redraw "#ROOTCONFIG#\Tooltip"][!SetVariable PP 1 "#ROOTCONFIG#\Tooltip"][!SetVariable PX #CURRENTCONFIGX# "#ROOTCONFIG#\Tooltip"][!SetVariable PY #CURRENTCONFIGY# "#ROOTCONFIG#\Tooltip"][!SetVariable PW #CURRENTCONFIGWIDTH# "#ROOTCONFIG#\Tooltip"][!SetVariable PH #CURRENTCONFIGHEIGHT# "#ROOTCONFIG#\Tooltip"][!UpdateMeasureGroup TooltipGroup "#ROOTCONFIG#\Tooltip"]
IfConditionMode=1
DynamicVariables=1
---Meters---
[MeterHoverHere]
Meter=String
FontFace=Consolas
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
FontWeight=700
AntiAlias=1
Text="HOVER HERE"
MouseOverAction=[!SetVariable TS 1][!WriteKeyValue "#ROOTCONFIG#\Tooltip" StartHidden 1 "#SETTINGSPATH#Rainmeter.ini"][!ActivateConfig "#ROOTCONFIG#\Tooltip"][!ZPos "2" "#ROOTCONFIG#\Tooltip"][!UpdateMeasure "MeasurePopulateTooltip"]
MouseLeaveAction=[!SetVariable TS 0][!DeactivateConfig "#ROOTCONFIG#\Tooltip"]
LeftMouseUpAction=[!SetVariable SomeIrrelevantStuffToDoHereToTriggerMouseHand 0]
DynamicVariables=1
[MeterSomethingChangingToShow]
Meter=String
FontFace=Consolas
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
X=0R
MeasureName=MeasureSomethingChanging
Text="to show the custom tooltip (%1)"
DynamicVariables=1
Code: Select all
[Variables]
MS=24
PP=0
PX=0
PY=0
PW=0
PH=0
[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
BackgroundMode=2
SolidColor=47,47,47,255
---Measures Rainmeter---
[MeasureMoveTooltip]
Group=TooltipGroup
Measure=Calc
UpdateDivider=-1
IfCondition=(#PP#=1)
IfTrueAction=[!Move "(((#PX#+#CURRENTCONFIGWIDTH#)>(#WORKAREAX#+#WORKAREAWIDTH#))?(#PX#-(#CURRENTCONFIGWIDTH#-#PW#)):(#PX#))" "(((#PY#+#PH#+#MS#+#CURRENTCONFIGHEIGHT#)>(#WORKAREAY#+#WORKAREAHEIGHT#))?(#PY#-#MS#-#CURRENTCONFIGHEIGHT#):(#PY#+#PH#+#MS#))"][!Show]
IfConditionMode=1
DynamicVariables=1
---Meters---
[MeterTooltipIcon]
Group=TooltipGroup
Meter=Image
X=5
Y=5
ImageName=
UpdateDivider=-1
DynamicVariables=1
[MeterTooltipTitle]
Group=TooltipGroup
Meter=STRING
FontFace=Consolas
StringStyle=Bold
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
X=0R
Y=0r
Text=
UpdateDivider=-1
DynamicVariables=1
[MeterTooltipText]
Group=TooltipGroup
Meter=STRING
FontFace=Consolas
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
X=0r
Y=0R
Text=
UpdateDivider=-1
DynamicVariables=1
- on mouse over the 1st meter in the parent skin, the tooltip skin will be loaded hidden and staying topmost, then populated in the similarly named measure
- that measure then checks if the tooltip is loaded and proceeds to "fill" the (previously empty) options of the tooltip skin's meters, updating those meters
- the same measure then redraws the (still hidden) tooltip skin - this is needed to get the values used to position the tooltip within the usable screen area
- the measure then sets the tooltip skin's populated status and the variables holding the parent skin's position / dimensions, updating the tooltip skin measures
- meanwhile, after being set up and getting the needed variables from the parent skin, the (populated) tooltip skin moves to the correct position and shows itself
What those variables are
TS = acronym for Tooltip Status (0 = Hidden; 1 = Shown)
MS = acronym for Mouse Cursor Size (i.e. one mouse "hand cursor" away from the parent skin, in pixels)
PP = acronym for Populated (i.e. whether or not the tooltip was populated already - used to trigger tooltip movement; 0 = No; 1 = Yes)
PX = acronym for Parent X (i.e. the left coordinates of the parent skin, in pixels; can refer to any meter, if the code is further refined to do so)
PY = acronym for Parent Y (i.e. the top coordinates of the parent skin, in pixels; can refer to any meter, if the code is further refined to do so)
PW = acronym for Parent W (i.e. the width of the parent skin, in pixels; can refer to any meter, if the code is further refined to do so)
PH = acronym for Parent H (i.e. the height of the parent skin, in pixels; can refer to any meter, if the code is further refined to do so)
The base code above can obviously be modified and tweaked in endless ways. It can be changed to react to meters in the parent skin (passing the [Meter:X], [Meter:Y], [Meter:W] and [Meter:H] as PX, PY, PW and PH), it can be made into a "custom menu" that shows and hides on mouse hover (like here), it can be colored using the same colors as an OS tooltip (like here), and so on. Have fun using it, if you need more from a tooltip than usual.
Hint
1) If you have small and very close to each other skins that use either the same or different variations of this custom tooltip skin (like I do), you may notice that sometimes when you mouse hover over them in succession, the tooltip doesn't appear for the last parent skin using it. This is not a malfunction, but a perfectly logical behavior in the world of milliseconds: there isn't sufficient time to deactivate (i.e. unload) the tooltip used by the preceding parent skin and activate (i.e. load) the one used by the skin the mouse hovers on. In this case (but you can apply it in all cases, if you want), add a [!Delay N] bang (where N is a suitable number of milliseconds) after the [!SetVariable TS 1] bang from the [MeterHoverHere] equivalent in your parent skin(s), and it will solve the inconvenience.
2) For some reason, when you right click on the hovered meter that triggers the appearance of the custom tooltip skin and choose Refresh from the parent skin's context menu, the MouseLeave event doesn't occur - although it does occur for every other choice from the said context menu. As a result, the active / loaded custom tooltip skin doesn't unload / deactivate after choosing to refresh the parent skin from its context menu. This can be solved by adding OnRefreshAction=[!SetVariable TS 0][!DeactivateConfig "#ROOTCONFIG#\Tooltip"] in the parent skin's [Rainmeter] section. A harmless warning that the tooltip skin is "not active" will be generated in the log when this action happens and the tooltip isn't loaded already, but other than that, no drawback from it.
Note: Do not add padding to the tooltip "icon" in the Tooltip skin if the other meters in the skin are positioned relative to it, DynamicVariables=1 is set on the tooltip icon meter and the dimensions of the image (i.e. W, H or both, depending on how you set the relative positioning) are not explicitly set. According to this thread, there can be "unexpected behavior" when that happens. The solution for this is either add the "icon" padding to the other meters instead, "simulate" the relative positioning by absolute positioning using the icon meter's W and H, or wait for the developers to fix this issue, if they think it's feasible and doesn't interfere with other "normal" behavior in Rainmeter.