Hello, trying to populate a menu with devices which I have done, but how do I then assign the method to run for each one in my code (which is in the EnableMenuItems event)? I would want the m.tag to be passed to the method. Or am I approaching this wrong?
There’s an example for this in the Documentation for the DesktopMenuItem but I am just using MenuItem and I cannot seem to get ‘MenuBarSelected’ to work.
dim i,c as integer
dim info as PortMidiDeviceInfoMBS
do until OpenOutputMenu.LastRowIndex = -1 //delete all current menu's
OpenOutputMenu.RemoveMenuAt(0)
loop
// Show the device list
c=p.CountDevices-1
for i=0 to c
info=p.DeviceInfo(i)
if info<>Nil then
if info.HasOutput then //only show outputdevices
Var m As New MenuItem(info.Name)
m.Name = info.Name
m.Text = info.Name
m.Tag = i
// code here for action??
OpenOutputMenu.AddMenu(m)
end if
end if
next
Right-click on the app icon of your app in the navigation pane and select Add Menu Handler. Then in the Inspector you choose which menu item you want to add the handler for. Then put the code in there, for that menu item. You won’t be using MenuBarSelected for this.
Thanks Tim, Yes I have done that previously for lots of other static menus. And I’ve finally got a message box to show up on selecting one of the dynamic menues by setting the m.name to “OpenOutputMenu” and then putting the code in the Menu Handler. But I’m still confused as to how you independently identify the specific menu that was selected say by a variable (can you do it by the ‘tag’?). The no of menu that could be populated isn’t always going to be the same.
There is ‘select case hitItem’ but I think that only works ContextualMenuAction, I am not sure if I should be using that or how?
Thanks so I have the (OpenOutputMenu) menu handler firing now when I select one of the menus using the code below. I seem to need to have the m.name for work so the event handler. The problem is the device names and the tag is always going to be different so I cannot just add a handler in the xojo because these are variables. Can the OpenOutputMenu check/retrieve for i so that it know what menu was pressed or can i be called so it can in the used handler code? or do I need to use AddHandler in the code below and then reference a method or something?
in other words I want a put a script in when the user presses the menu option that it will open that midi device and I need to know i / tag for that within the script.
Var m As New MenuItem(info.Name,i)
m.Name = "OpenOutputMenu"
OpenOutputMenu.AddMenu(m)
I tried this, and it wanted me to convert all the windows to DeskopWindows too, and so I did… Then 214 compile errors because I already have a lot of code using a standard listbox… surely there is another way?
" In certain cases you cannot specify the menu items that belong in a menu in advance. They may change depending on the context in which the application is used or on the operating system on which the application is running.
A common example of this is the Font menu that is normally included in any application that supports styled text. The programmer has no way of knowing in advance which fonts happen to be installed on the user’s computer. The Font menu’s menuitems have to be built dynamically when the application is launched.
The recommended technique is to create a subclass of MenuItem in the Project Window. To create the menuitems, you use the MenuItem’s constructor to instantiate an instance of the class for each MenuItem you need. You handle the MenuItem in the Action event."
For example, I made a MenuItem subclass for making a “Recent Files” menu:
Once you have a subclass, you can add properties, customize the Constructor, etc. Add the Action event handler in the IDE and put whatever code you want in there. You can tell which item was selected by checking Name or Text or Tag.
Yes, this is how I do it. Subclass DesktopMenuItem, and build your menus using new instances of the subclass. That subclass will then have the MenuItemSelected event directly available to it.
OK so went to the effort of converting the code to work with the desktop thingy ma bob (almost - just a few lines I commented out that I need to figure out). And I’ve used this code with a method:
Var m As New DesktopMenuItem(info.Name,i)
m.Name = info.Name
AddHandler m.MenuBarSelected, AddressOf ActionMethod // We assign the Delegate Method as the Action to execute
OpenOutputMenu.AddMenu(m)
And ugh now I’m getting this
Type mismatch error. Expected delegate Delegate( DesktopMenuItem ), but got delegate Delegate( DesktopMenuItem ) as Boolean
AddHandler m.MenuBarSelected, AddressOf ActionMethod // We assign the Delegate Method as the Action to execute
If I remove the boolean from the ActionEvent method and the ‘return true’, then it compiles but goes on a loop with the messgebox, so I assume this boolean is needed. I’ve just done the same thing as in the documentation for DestopMenuItems basically, but I probably need to have a break and come back to it. It’s like I get so close and then it doesn’t want me to be able to do this.
Thanks alot Julia, Think I’ve got it now, changing it to MenuItemSelected worked and got rid of the type mismatch. I realised now because with this project I have been learning from the ground up and I copied a couple things from a example project to get me started early on hence why I was still using alot of the old non ‘Desktop’ code (the example must have been using old type list boxes or something).
AddHandler and MenuItem.Action is working fine for me. I converted Norman’s example from the other forum into API 1.0 / Pre-Desktop controls: https://xojo.dev/IXm6YXv2
Odd. I did exactly the same, nothing.
I’ll try your project. Maybe I made a booboo
Edit:
No, I didn’t. My code ended up the same as yours, but when placed into my actual project, it didnt work.
The menu I have in mind for this is specific to a Window
When I put the code into the Window’s open event, it doesn’t work FOR ME because the Open event of the window never fires. (A problem I have had to work around for 15 years)
But putting it inside a ‘run once’ section of code that I have in activate() event, works fine. Hurrah.
No idea.
But I promise you, code in the Open() event of that window in that project does not run, and no breakpoint is ever hit. I’ve tried all kinds of tests for corruption, file formats…
I gave up scratching my head over it years ago (although sometimes it catches me out again like this) , and like most things, once I had a workaround, I just kept going.
Personally, I don’t do any window setup in constructors or open. I always use a window setup function (usually called Display) that fills all the fields and lastly shows the window. This has always worked for me, I don’t end up with race conditions or non-existent controls.