is it possible to update a menuitem text in real time ?
in the finder, if you press - depress option in some menus the text changes, as in many apps (save changes to “save as” for example
in xojo, I change the text in the enablemenuitem event of a control or a window, but if I check for option key it is changed but not
in real time, you have to re-clic the menu to get the new text
is there a way to achieve this in xojo, and bonus if it is multi platform.
thanks.
On macOS you would need to use create two menu items and set one of them to be the alternate and the system will swap them in and out, as required… On Windows I was able to do something similar just using a timer to poll the keyboard… I think the Windows method should work on Linux as well, but I never tested it…
I’ll go grab the code I used (will have to check it against 64-bit first, so give me a few)
[code]Public Sub SetAlternate(Extends aMenuItem As MenuItem, Assigns value As Boolean) #if TargetCocoa
Declare Sub setAlternate_ Lib “Cocoa” Selector “setAlternate:” (aNSMenuItem As Integer, value As Boolean)
setAlternate_ aMenuItem.Handle(MenuItem.HandleType.CocoaNSMenuItem), value #endif
#Pragma Unused aMenuItem #Pragma Unused value
End Sub
[/code]
For macOS, slap this in a module and then call it from somewhere (I was doing it in App.Open)
MyAlternateMenuItem.SetAlternate = TRUE
Make sure that the two menu items are in your menu stacked on top of each other and they need the same key for their shortcut…
Okay, this code also works on macOS, but feels a little hacky, so I’d stick with the extend method posted above… This code is from a long time ago (before the new framework and 64-bit) but should be easy enough to update to use the new Timer.CallLater
In my application, and test demo, all this code was part of the App class, but the EnableMenuItems event handler can be at any level…
Sub Open() Handles Open
me.InitMenuModifierTimer
End Sub
[code]Private Sub InitMenuModifierTimer()
me.mMenuModifierTimer = NEW Timer
me.mMenuModifierTimer.Period = 100 // still responsive and low CPU usage
me.mMenuModifierTimer.Mode = Timer.ModeMultiple
me.mMenuModifierTimer.Enabled = TRUE
AddHandler me.mMenuModifierTimer.Action, WeakAddressOf MenuModifierAction
End Sub
[/code]
[code]Private Sub MenuModifierAction(menuModifierTimer As Timer) #pragma Unused menuModifierTimer
EnableMenuItems
End Sub
[/code]
My test code was using the Shift Key for the modifier, but just check for whatever modifier you require and set the menu items as required…
Sub EnableMenuItems() Handles EnableMenuItems
UntitledOink.Visible = NOT Keyboard.AsyncShiftKey
UntitledOinkModified.Visible = Keyboard.AsyncShiftKey
End Sub
In my project file UntitledOinkModified had Visible set to FALSE so it wasn’t showing in the menu when the menu is first opened…
The problem is that Xojo loves to rebuild the menu, so your changes are going to get ignored.
Of course you may catch an event and do make changes after Xojo build the menu and before displaying it, but that could be difficult.
well after some tests, it doesn’t update really live, you have to choose another menu, but it does not require you to clic twice at least to get the other text of the menu.
The other way you can do it on the macOS (although’ recommend using the preferred method “alternate” as ? Sean says, anyway the other method which is really hacky, would be to inject an actual control into the menuitem and change the text on that control or label.
I’m just heading home, when I get back to work tonight, I’ll post a sample project with the timer method…
[quote=369885:@Jean-Yves Pochez]shouldn’t this line Sub EnableMenuItems() Handles EnableMenuItems
be instead Sub EnableMenuItems() // Handles EnableMenuItems
?[/quote]
Possibly, I just copied the event handler out of the IDE, so I’ll check it tonight and file a bug report if it happens again…
[quote=369885:@Jean-Yves Pochez]shouldn’t this line Sub EnableMenuItems() Handles EnableMenuItems
be instead Sub EnableMenuItems() // Handles EnableMenuItems
?[/quote]
No. It should be an actual event handler.