xsharp.eu • I want to create a dynamic (sub)menu in a given window
Page 1 of 1

I want to create a dynamic (sub)menu in a given window

Posted: Sun Aug 25, 2024 4:58 pm
by radimpl
I'm trying to learn the X++ language and I have one problem at the beginning.
I want to create a dynamic menu in a given window, i.e. without a visual menu generator. And I can't somehow assign the SubMenu to the main Menu item (menubar). What am I doing wrong?
The SubMenu will not appear

PARTIAL CLASS MyMenu INHERIT Menu

CONSTRUCTOR( oOwner )
SELF:PreInit()

LOCAL oSubMenu AS Menu
oSubMenu := Menu{}
oSubMenu:AppendItem(103,"&Open..." )
oSubMenu:AppendItem(104,"Print Setup...")

SELF:AppendItem(101,"&File")
SELF:AppendItem(102,"&Help")
SELF:AppendItem(0,oSubMenu)

SELF:PostInit()

RETURN

END CLASS

Thanks for your help.
Radim

Re: I want to create a dynamic (sub)menu in a given window

Posted: Sun Aug 25, 2024 7:18 pm
by wriedmann
Hi Radim,
if you want to create dynamic menu entries, you need to register the item in the menu.
This is a part of code you need to add a dynamic item to a menu:

Code: Select all

method AddItem( nId, symmethod,cName,cDescription) class DynMenu

self:RegisterItem( nID, Hyperlabel{ symmethod,, cDescription,, } )
self:AppendItem( nID, cName )

return nil
Adding a submenu to a menu you can call then the AppendItem() method:

Code: Select all

oMenu:AppendItem( oSubMenu, "File" )
Wolfgang

Re: I want to create a dynamic (sub)menu in a given window

Posted: Mon Aug 26, 2024 8:05 am
by radimpl
Hi Wolfgang.

Thank for your reply.
My dynamic menu system is working now.

I have other question.

In code: self:RegisterItem( nID, Hyperlabel{ symmethod,, cDescription,, } ) is parameter "symmethod".
Yes, I can use method name #FileExit for example.
But, can I use in this parameter code block: eval(MyCodeBlock,param) for example ?

thanks.

Radim

Re: I want to create a dynamic (sub)menu in a given window

Posted: Mon Aug 26, 2024 8:18 am
by wriedmann
Hi Radim,
the VO GUI classes are using name based linking in many cases, and one of them is the link of the method name to the menu name.
If you do not wish that because you are either generating dynamic names or don't like that, you can use the MenuCommand method of the owner window:

Code: Select all

method MenuCommand( oEvent ) class MyWindow
local oMenuEvent as MenuCommandEvent
local cName as string
	
oMenuEvent := oEvent
super:MenuCommand( oMenuEvent )
cName := oMenuEvent:Name
do case
case cName == "menuchoide1"
	// ....
case cName == "menuchoide12"
	// ....
endcase
	
return nil
HTH

Wolfgang

Re: I want to create a dynamic (sub)menu in a given window

Posted: Mon Aug 26, 2024 9:16 am
by radimpl
Hi Wolfgang,

MenuCommand method is perfect.

Back to the self:RegisterItem( nID, Hyperlabel{ symmethod,, cDescription,, } )
Can I use: self:RegisterItem( nID, Hyperlabel{ #MyMethodName(cParam),, cDescription,, } )

Radim

Re: I want to create a dynamic (sub)menu in a given window

Posted: Mon Aug 26, 2024 9:26 am
by wriedmann
Hi Radim,

sorry, I had not understood your question correctly.
A Hyperlabel requires a symbolic name, and not a codeblock or similar thing.
You can do something like this:

Code: Select all

self:RegisterItem( nID, Hyperlabel{ "MyMethodName_" + cParam,, cDescription,, } )
and then split that out in the MenuCommand method.
I'm doing that in several places in some of my applications specially when the menu is based on a number of files present in a folder or similar dynamic data.
Wolfgang

Re: I want to create a dynamic (sub)menu in a given window

Posted: Mon Aug 26, 2024 2:58 pm
by radimpl
self:RegisterItem( nID, Hyperlabel{ #DoSomething(cFile,.T.),, cDescription,, } )


METHOD DoSomething(cFileName, lReadOnly) class MyWindow
.................
RETURN SELF

Re: I want to create a dynamic (sub)menu in a given window

Posted: Mon Aug 26, 2024 3:21 pm
by robert
The Hyperlabel class expects a Symbol as first parameter.

So

Code: Select all

Hyperlabel{ #DoSomething(cFile,.T.)
is not allowed.

If you want to pass parameters to the method, I recommend that you create a parameter less event handler, and call the method from that event handler

Code: Select all

self:RegisterItem( nID, Hyperlabel{ #SomethingEvent,, cDescription,, } )
.
.
.


METHOD SomethingEvent() class MyWindow

// retrieve cFile from class or other storage location
SELF:DoSomething(cFile, TRUE)



Robert