It is currently March 29th, 2024, 8:59 am

Advanced custom skin context menus

Tips and Tricks from the Rainmeter Community
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Advanced custom skin context menus

Post by jsmorley »

Custom skin context menus

Rainmeter has the capability to add custom skin Context Menus, which allows you to add functionality to the standard skin context menu when you right-click the skin.

In addition, you can use the !SkinCustomMenu bang to have your custom context menu appear at the current mouse position, independent of the normal skin context menu. Just your "custom" menu entries will appear.

Example:

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
ContextTitle=My Actions
ContextAction=[]
ContextTitle2=---
ContextAction2=[]
ContextTitle3=Refresh Skin
ContextAction3=[!Refresh "#CURRENTCONFIG#"]
ContextTitle4=Refresh All
ContextAction4=[!Refresh "*"]
ContextTitle5=Refresh Rainmeter
ContextAction5=[!RefreshApp]

[MeterSkinDemo]
Meter=String
FontSize=11
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=RIGHT-Click Me#CRLF#Full Skin Context Menu

[MeterSkinBangDemo]
Meter=String
Y=5R
FontSize=11
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=LEFT-Click Me#CRLF#Full Skin Context Menu
LeftMouseUpAction=[!SkinMenu]

[MeterSkinCustomDemo]
Meter=String
Y=5R
FontSize=11
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=LEFT-Click Me#CRLF#Custom Skin Context Menu
LeftMouseUpAction=[!SkinCustomMenu]
1.jpg
Some limitations

There is a limit of 15 sets of ContextTitle / ContextAction in a single skin. So in one [Rainmeter] section of a skin, you can only define up to 15 context menu items, including any "separators" you define.

Some limit needed to be set, so a context menu isn't defined that runs off the screen. The current limit is 15 items per skin.

If you are using the !SkinCustomMenu bang multiple times on different meters, you may want to have different custom context menus appear depending on which meter you click. With a skin with all items defined in the [Rainmeter] section of that skin, that isn't possible. All items (up to the 15 maximum) you define are part of a single context menu for the skin.

An advanced solution

The solution for creating more robust context menu functionality involves using multiple skins. One will be the main or "parent" skin the user sees and interacts with, and then you can have an unlimited number of what I call "context skins" that are simply meant to provide different custom skin context menus for that "parent" skin. These context skins don't measure or display anything, other than a context menu associated with them.

The best way to explain is to just give you an example skin and a little animation of how it might work and look. Then I will describe a couple of tricks I used to make it work.
ContextDemo_1.0.rmskin
Click to animate
test.gif
So you have no custom context menu in the "parent' (ContextDemo.ini) skin at all. (although you certainly could) Instead you have LeftMouseUpAction options on the meters, to load (!ActivateConfig) a particular "context skin" (Context1.ini, Context2.ini, Context3.ini) that are contained in sub-folders of that parent skin. That way they can be loaded at the same time the parent is.

In each of the small context skins, You simply have the context items you want defined (again up to 15 in each) and an OnRefreshAction that automatically fires the context menu at the mouse location when the context skin is loaded.

Then when the user selects one of the context items, the actions are fired, and the little skin context menu closes itself.

Note that you specify a config parameter on your bangs, as the intent is to have the context items in each context skin cause changes to the "parent" skin.

One last little housekeeping trick is to have each of the context skins in a group, and then have the parent skin !DeactivateConfigGroup this group when it is refreshed or obtains mouse focus. This is to ensure that if the user selects a context menu, but doesn't select an item from it (which means the little context skin may not be "unloaded") the parent skin makes sure all the little context skins are always unloaded as they should be.

The folders
2.jpg
The code

ContextDemo.ini

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
OnRefreshAction=[!DeactivateConfigGroup "ContextMenus"]
OnFocusAction=[!DeactivateConfigGroup "ContextMenus"]

[Metadata]
Name=ContextDemo
Author=JSMorley
Version=Jan 9, 2015
License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0
Information=Demonstration of Rainmeter skin context menus

[Variables]
FontSize=11
FontColor=255,255,255,255
FontFace=Arial

[MeterExample]
Meter=String
FontFace=#FontFace#
FontSize=#FontSize#
FontColor=#FontColor#
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=abcdefghijkl#CRLF#ABCDEFGHIJKL#CRLF#0123456789
DynamicVariables=1

[MeterContext1]
Meter=String
Y=10R
FontFace=#FontFace#
FontSize=#FontSize#
FontColor=#FontColor#
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=Change FontSize
DynamicVariables=1
LeftMouseUpAction=[!ActivateConfig "ContextDemo\Context1" "Context1.ini"]

[MeterContext2]
Meter=String
Y=2R
FontFace=#FontFace#
FontSize=#FontSize#
FontColor=#FontColor#
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
DynamicVariables=1
Text=Change FontColor
LeftMouseUpAction=[!ActivateConfig "ContextDemo\Context2" "Context2.ini"]

[MeterContext3]
Meter=String
Y=2R
FontFace=#FontFace#
FontSize=#FontSize#
FontColor=#FontColor#
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
DynamicVariables=1
Text=Change FontFace
LeftMouseUpAction=[!ActivateConfig "ContextDemo\Context3" "Context3.ini"]
Context1.ini

Code: Select all

[Rainmeter]
Group=ContextMenus
ContextTitle=Select FontSize
ContextAction=[]
ContextTitle2=---
ContextAction2=[]
ContextTitle3=9
ContextAction3=[!SetVariable FontSize "9" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle4=10
ContextAction4=[!SetVariable FontSize "10" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle5=11
ContextAction5=[!SetVariable FontSize "11" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle6=20
ContextAction6=[!SetVariable FontSize "20" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle7=30
ContextAction7=[!SetVariable FontSize "30" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]

OnRefreshAction=[!SkinCustomMenu]

[MeterDummy]
Meter=String
Context2.ini

Code: Select all

[Rainmeter]
Group=ContextMenus
ContextTitle=Select FontColor
ContextAction=[]
ContextTitle2=---
ContextAction2=[]
ContextTitle3=White
ContextAction3=[!SetVariable FontColor "255,255,255,255" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle4=Red
ContextAction4=[!SetVariable FontColor "255,119,110,255" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle5=Green
ContextAction5=[!SetVariable FontColor "201,255,201,255" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle6=Blue
ContextAction6=[!SetVariable FontColor "201,221,255,255" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle7=Cyan
ContextAction7=[!SetVariable FontColor "219,255,255,255" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]

OnRefreshAction=[!SkinCustomMenu]

[MeterDummy]
Meter=String
Context3.ini

Code: Select all

[Rainmeter]
Group=ContextMenus
ContextTitle=Select FontFace
ContextAction=[]
ContextTitle2=---
ContextAction2=[]
ContextTitle3=Arial
ContextAction3=[!SetVariable FontFace "Arial" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle4=Trebuchet MS
ContextAction4=[!SetVariable FontFace "Trebuchet MS" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle5=Segoe UI
ContextAction5=[!SetVariable FontFace "Segoe UI" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle6=Calibri
ContextAction6=[!SetVariable FontFace "Calibri" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]
ContextTitle7=Tahoma
ContextAction7=[!SetVariable FontFace "Tahoma" "ContextDemo"][!UpdateMeter "*" "ContextDemo"][!Redraw "ContextDemo"][!DeactivateConfig #CURRENTCONFIG#]

OnRefreshAction=[!SkinCustomMenu]

[MeterDummy]
Meter=String
Note that I just used !SetVariable in my example, so the changes are "temporary". If you wanted the change to be permanent, you would want to use both !WriteKeyValue and !SetVariable / !SetOption bangs when you make some change.

Let me know if you have any questions.
You do not have the required permissions to view the files attached to this post.
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5384
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Advanced custom skin context menus

Post by eclectic-tech »

I was just trying to do this same thing using @includes and was striking out...

Thanks! :great:
User avatar
winterwulf
Posts: 94
Joined: August 17th, 2016, 1:48 am
Location: São Paulo - Brazil

Re: Advanced custom skin context menus

Post by winterwulf »

Thank you so much for this tutorial! :D

I have one lil problem tho, after I activate the custom context menu, it wont unload.

Initially thats ok, because the user wont notice it, but on restart it will show up at X=0 Y=0 (left upper corner) of the screen.
is there a easy way to fix it?

Thanks!

EDIT: Answering my question, I got it done with

Code: Select all

OnUnfocusAction=[!DeactivateConfig]
Stratosteel
Posts: 12
Joined: December 13th, 2016, 10:28 pm

Re: Advanced custom skin context menus

Post by Stratosteel »

Nice tutorial, but is there any way to bold an action title?

EDIT: There is not a way :confused:
Last edited by Stratosteel on December 19th, 2016, 4:23 am, edited 1 time in total.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Advanced custom skin context menus

Post by jsmorley »

Stratosteel wrote:Nice tutorial, but is there any way to bold an action title?
There is not.
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5384
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Advanced custom skin context menus

Post by eclectic-tech »

There was an inquiry if custom context menus can have sub-menus. The definitive answer is 'no' they can not; you can not have a second custom context menu displayed relative to the initial custom context menu.

This is not 'currently' possible:Image

But as demonstrated by JSMorley's 'Advanced custom skin context menus' it is possible to create a multiple custom menu in the same skin by grouping the context menus and having each custom context menu in it's own folder.

To expand on the above topic, I experimented with the ability to have "layered" custom context menus; one context menu links to another custom context menu.

This can be done, as described above in JSMorley's example, by adding all of the custom menus to the same 'group' name. Then in your action bang, deactivate the 'group' name and activating the desired custom menu.

The only drawback is that only one context menu is display at a time, and it's position is relative to the previous menu's position. Therefore, I would recommend only having 2 layers of menus; beyond that the menus begin to travel all over your desktop! :uhuh:

Attached is a demo skin that has multiple custom context menus, that are accessed by right-clicking a hot spot, e.g. '>>'. Doing this allows access to the default right-click skin menu from anywhere else in the skin display.

To dismiss any open context menu, simply click away from it.

The demo has a first custom menu with links to subsequent custom menus: 'Styles', 'Colors', 'Fonts', and 'Options'.
customcontext2.png
When you click on one of those items, a new custom context menu will appear.
customcontext3.png
Hopefully, some authors might find this useful.
Remember: "Enjoy all things in life in moderation." :thumbup:

So please don't start creating "custom context menu monsters"; no one will appreciate the experience. :twisted:
You do not have the required permissions to view the files attached to this post.
User avatar
SilverAzide
Rainmeter Sage
Posts: 2588
Joined: March 23rd, 2015, 5:26 pm

Re: Advanced custom skin context menus

Post by SilverAzide »

Not to take anything away from the above techniques, presented here is a third way to have multiple custom menus. This method differs from the above approaches in that you do not need to create separate custom menu skins, nor do you need skin groups.

Please note that when JSMorley posted his original demo skin back in 2015, the nested variable syntax did not exist as a feature in Rainmeter (added in Rainmeter 4.1 in 2017). The approach here relies on this new feature. Also, I want to give full credit where it is due: This technique is not my idea at all, was cloned wholesale from user raiguard, specifically from his ColorPickerPlus skin. If he got the idea from someone else or came up with it on his own, I don't know.

As Eclectic-Tech described, the technique here does not prevent cascading menus from "walking" all over the screen. So I'd suggest following his advice and not nest menus too deeply.

You can also use this technique to allow your skin to have multiple context-sensitive menus, with different menus appearing based on where you click or some other trigger.
You do not have the required permissions to view the files attached to this post.
Gadgets Wiki GitHub More Gadgets...
User avatar
nek
Posts: 105
Joined: November 3rd, 2019, 12:00 am

Re: Advanced custom skin context menus

Post by nek »

Another example of the context menus.
Based on jsmorley's Advanced custom skin context menus (this topic)
✔️ Skin custom context menus (sub-menus)
✔️ Meter custom context menus (sub-menus)
menudemo.gif
ContextMenus.Demo.rmskin
Codes

Code: Select all

ContextMenus.Demo
│  Skin.ini
└─@Contexts
        Icon1.inc
        Icon2.inc
        Menu.ini
Skin.ini

Code: Select all

[Variables]
ACT1=[!SetVariable INC "#ROOTCONFIGPATH#@Contexts\[#*CURRENTSECTION*].inc"]
ACT2=[!DeactivateConfigGroup "#ROOTCONFIG#\@Contexts"][!WriteKeyValue Rainmeter @Include "[#*INC*]" "#ROOTCONFIGPATH#@Contexts\Menu.ini"][!WriteKeyValue Variables SRC_CONFIG "#CURRENTCONFIG#" "#ROOTCONFIGPATH#@Contexts\Menu.ini"][!WriteKeyValue Variables SRC_FILE "#CURRENTFILE#" "#ROOTCONFIGPATH#@Contexts\Menu.ini"][!ActivateConfig "#ROOTCONFIG#\@Contexts" "Menu.ini"]

[Rainmeter]
Update=-1
; DefaultUpdateDivider=-1
AccurateText=1
MouseActionCursor=0

[Background]
Meter=Image
W=280
H=160
SolidColor=171717B3

[Icon1]
Meter=Image
X=40
Y=40
W=80
H=80
SolidColor=FF00FFCC
RightMouseUpAction=#ACT1##ACT2#

[Icon2]
Meter=Image
X=160
Y=40
W=80
H=80
SolidColor=00FFFFCC
RightMouseUpAction=#ACT1##ACT2#
Menu.ini

Code: Select all

[Rainmeter]
Update=-1
Group=#CURRENTCONFIG#
OnRefreshAction=[!SkinCustomMenu]
OnUnfocusAction=[!DeactivateConfig]
@Include=

[Variables]
SRC_CONFIG=
SRC_FILE=

[Dummy]
Meter=String
Icon1.inc

Code: Select all

[Rainmeter]
ContextTitle=Icon1
ContextAction=[]
ContextTitle2=-
ContextAction2=[]
ContextTitle3=Settings[\x0009][\x23F5]
ContextAction3=[]
ContextTitle4=-
ContextAction4=[]
ContextTitle5=Selected  [\x2714]
ContextAction5=[]
ContextTitle6=&Edit skin
ContextAction6=[!EditSkin "#SRC_CONFIG#" "#SRC_FILE#"]
Icon2.inc

Code: Select all

[Rainmeter]
ContextTitle=Icon2
ContextAction=[]
ContextTitle2=-
ContextAction2=[]
ContextTitle3=Light mode
ContextAction3=[]
ContextTitle4=Dark mode  [\xE1F5]
ContextAction4=[]
ContextTitle5=-
ContextAction5=[]
ContextTitle6=&Refresh skin
ContextAction6=[!Refresh "#SRC_CONFIG#"]
ContextTitle7=&Unload skin
ContextAction7=[!DeactivateConfig "#SRC_CONFIG#"]
Example
menudemo.2022-03-18.gif
ContextMenus.Example.rmskin


💡 [#VariableName] [#*VariableName*] >> Nested Variables.

Code: Select all

[Variables]
NUM=0
[Meter]
...
LeftMouseUpAction=[!SetVariable NUM "([#NUM]+1)"][!Log "standard=#NUM#, nested=[#NUM]"]
Output: standard=0, nested=1



[Rainmeter]
Update, DefaultUpdateDivider, AccurateText, Context options, !SkinCustomMenu, @Include option
Variables
#CURRENTSECTION#, Nesting Variables
Meters
Image Meter, RightMouseUpAction
Bangs
!SetVariable, !WriteKeyValue, !ActivateConfig, !DeactivateConfigGroup
You do not have the required permissions to view the files attached to this post.
Last edited by nek on September 14th, 2023, 1:04 am, edited 4 times in total.
User avatar
creewick
Posts: 38
Joined: March 4th, 2022, 2:43 pm
Location: Almaty, Kazakhstan

Re: Advanced custom skin context menus

Post by creewick »

Just day before I was suffering while trying to implement multiple context menu using bangs

Code: Select all

[Language]
Meter=String
Text=#Language#
LenftMouseUpAction=[!SetOption Rainmeter ContextTitle "ru"][!SetOption Rainmeter ContextAction """[!WriteKeyValue Variables Language "ru" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle2 "ua"][!SetOption Rainmeter ContextAction2 """[!WriteKeyValue Variables Language "ua" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle3 "en"][!SetOption Rainmeter ContextAction3 """[!WriteKeyValue Variables Language "en" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle4 "de"][!SetOption Rainmeter ContextAction4 """[!WriteKeyValue Variables Language "de" "#@#Settings\Global.inc"]"""][!SkinCustomMenu]

[TemperatureUnits]
Meter=String
Text=#Units#
LeftMouseUpAction = [!SetOption Rainmeter ContextTitle "metric"][!SetOption Rainmeter ContextAction """[!WriteKeyValue Variables Units "metric" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle2 "imperial"][!SetOption Rainmeter ContextAction2 """[!WriteKeyValue Variables Units "imperial" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle3 "standard"][!SetOption Rainmeter ContextAction3 """[!WriteKeyValue Variables Units "standard" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle4 ""][!SkinCustomMenu]
Thank you for saving me from this spaghetti code, it's much easier as it described in ContextDemo
User avatar
balala
Rainmeter Sage
Posts: 16110
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Advanced custom skin context menus

Post by balala »

creewick wrote: March 18th, 2022, 5:20 pm

Code: Select all

[Language]
Meter=String
Text=#Language#
LenftMouseUpAction=[!SetOption Rainmeter ContextTitle "ru"][!SetOption Rainmeter ContextAction """[!WriteKeyValue Variables Language "ru" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle2 "ua"][!SetOption Rainmeter ContextAction2 """[!WriteKeyValue Variables Language "ua" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle3 "en"][!SetOption Rainmeter ContextAction3 """[!WriteKeyValue Variables Language "en" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle4 "de"][!SetOption Rainmeter ContextAction4 """[!WriteKeyValue Variables Language "de" "#@#Settings\Global.inc"]"""][!SkinCustomMenu]

[TemperatureUnits]
Meter=String
Text=#Units#
LeftMouseUpAction = [!SetOption Rainmeter ContextTitle "metric"][!SetOption Rainmeter ContextAction """[!WriteKeyValue Variables Units "metric" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle2 "imperial"][!SetOption Rainmeter ContextAction2 """[!WriteKeyValue Variables Units "imperial" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle3 "standard"][!SetOption Rainmeter ContextAction3 """[!WriteKeyValue Variables Units "standard" "#@#Settings\Global.inc"]"""][!SetOption Rainmeter ContextTitle4 ""][!SkinCustomMenu]
There is a small error in the LeftMouseUpAction option of the [Language] meter. It is mistakenly written as LenftMouseUpAction.