Page 1 of 1

Adding item in SubMenu closed [Resolved]

Posted: Sat Apr 09, 2022 7:27 pm
by Kwai chang caine
Hello at all

Is it possible to adding an item in a Submenu already created and closed ?
Because there are just OpenSubMenu() function and it create another Submenu even if it exist in the same level :cry:

Code: Select all

OpenWindow(0, 200, 200, 220, 100, "Exemple SubMenu")
CreateMenu(0, WindowID(0))
  
MenuTitle("Projet") 
MenuItem(1, "Ouvrir")  

OpenSubMenu("Récents files")
 MenuItem( 2, "C:\Autoexec.bat")
CloseSubMenu()

MenuItem(3, "D:\Teste.txt")

; I want adding this item in "Récents files" SubMenu after have called his CloseSubMenu()
OpenSubMenu("Récents files")
 MenuItem(4, "C:\Autoexec.bat")
CloseSubMenu()
    
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
Have a good day

Re: Adding item in SubMenu closed

Posted: Sat Apr 09, 2022 8:58 pm
by Marc56us
Hi Kcc,

There is only 3 possibles action to modify menu: SetMenuItemState, SetMenuItemText, SetMenuTitleText
The simple solution for some actions like add recents files it to put some placeholders and use SetMenuItemText

Code: Select all

OpenWindow(0, 200, 200, 220, 100, "Exemple SubMenu")
CreateMenu(0, WindowID(0))
  
MenuTitle("Projet") 
MenuItem(1, "Ouvrir")  

OpenSubMenu("Récents files")
 MenuItem( 2, "C:\Autoexec.bat")
 MenuItem( 4, "-")
 MenuItem( 5, "-")
 MenuItem( 6, "-")
 MenuItem( 7, "-")
CloseSubMenu()

MenuItem(3, "D:\Teste.txt")

; Add new recent file: simply change title
SetMenuItemText(0, 4, "c:\newfile.txt") 
    
Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
The other possibility is to destroy it (FreeMenu) and rebuild it
:wink:

Re: Adding item in SubMenu closed

Posted: Sat Apr 09, 2022 9:34 pm
by RASHAD
Hi KCC
For Windows
Insert - Remove items

Code: Select all

OpenWindow(0, 0, 0, 220, 125, "Exemple SubMenu",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateMenu(0, WindowID(0))

MenuTitle("Projet") 
MenuItem(1, "Ouvrir")  

hSubmenu_1 = OpenSubMenu("Récents files")
MenuItem( 2, "C:\Autoexec.bat")
CloseSubMenu()

MenuItem(3, "D:\Teste.txt")

; I want adding this item in "Récents files" SubMenu after have called his CloseSubMenu()
hSubmenu_2 = OpenSubMenu("Récents files")
MenuItem(4, "C:\Autoexec.bat")
CloseSubMenu()

ButtonGadget(1,10,70,80,20,"Insert")
ButtonGadget(2,100,70,80,20,"Remove")

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          InsertMenu_(hSubmenu_2,5,#MF_BYPOSITION|#MF_POPUP,hSubmenu,"Title_2")
          DrawMenuBar_(WindowID(0))
        Case 2
          RemoveMenu_(hSubmenu_2,1,#MF_BYPOSITION)
          DrawMenuBar_(WindowID(0))
      EndSelect
  EndSelect
Until Quit = 1


Re: Adding item in SubMenu closed

Posted: Sat Apr 09, 2022 11:54 pm
by TassyJim
I clear and then re-create the menu when I want to make changes.
It allows you to have a choice of simple and advanced etc.

Code: Select all

Procedure mainMenu()
  Protected n, k
  If IsMenu(#MMenu)
    FreeMenu(#MMenu)
  EndIf
  
  If CreateMenu(#MMenu, WindowID(#WindowMain))
  ...
  

Re: Adding item in SubMenu closed

Posted: Sun Apr 10, 2022 3:34 am
by BarryG
Freeing and rebuilding the menu can be so much work, though, because the user can have changed a lot of the item settings. So you'd need to store all that runtime menu information somewhere first, in order to recreate the menu later: setting any changed check marks again, using the current icons for them, disabling the items that the user disabled, etc. And don't forget that recreating the menu can actually fail (return value 0) at times - it's happened to me despite having 16 GB of RAM on Windows 10.

For Windows, it's far easier and less hassle just to use Rashad's solution and avoid all that pain.

Re: Adding item in SubMenu closed

Posted: Sun Apr 10, 2022 7:56 am
by Marc56us
The pure PureBasic way (compatible all OS, no destroy/create menu) :)

Code: Select all

OpenWindow(0, 200, 200, 220, 100, "Exemple SubMenu", 
           #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateMenu(0, WindowID(0))

MenuTitle("Projet") 
MenuItem(1, "Ouvrir")  

OpenSubMenu("Récents files")
MenuItem( 11, "C:\Autoexec.bat")
MenuItem( 12, "-")
MenuItem( 13, "-")
MenuItem( 14, "-")
MenuItem( 15, "-")
CloseSubMenu()

MenuItem(2, "Ajouter récent")

Repeat 
    Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
            End
        Case #PB_Event_Menu
            Select EventMenu()
                Case 2 
                    For i = 11 To 15
                        If GetMenuItemText(0, i) = "-"
                            SetMenuItemText(0, i, "C:\newfile_" + Str(i) + ".txt") 
                            Break
                        EndIf
                    Next
            EndSelect            
    EndSelect
ForEver

End
:wink:

Re: Adding item in SubMenu closed

Posted: Sun Apr 10, 2022 6:11 pm
by Kwai chang caine
First thanks at all for your help 8)

@MARC56
It's a good idea, but in your solution you must have before the empty item "-" :wink:
Me i want adding dynamicaly the item, even if he not have his place

@TASSYJIM
It's a solution, but in my project i can have numerous items in several column, and like BarryG say, i think it's when even a big job to recreate all the menu for only adding one item :wink:
But thanks when even for your advice 8)

@RASHAD

It's exactely what i want !!! :D

I have found this API, but i don't understand why, i was "like a chicken with a fork" (French expression) I don't really know how use it :oops:

Image

And impossible to adapt in my code :oops:

@ALL
Again thanks for your precious help
I wish you all a very very good day 8)

Re: Adding item in SubMenu closed [Resolved]

Posted: Tue Oct 24, 2023 2:38 pm
by HarrysLad
RASHAD:

Your code shown earlier has helped a lot with my latest Windows-based problems. I can now insert and remove submenu items successfully but a problem remains...

Given the line (say) "InsertMenu_(hSubmenu_2,5,#MF_BYPOSITION|#MF_POPUP,hSubmenu,"Title_2")"

How do I find the associated ID of the item?

Sorry if this has a stupidly simple answer but I'm struggling here... :oops:

TIA
Dave

Re: Adding item in SubMenu closed [Resolved]

Posted: Tue Oct 24, 2023 5:18 pm
by AZJIO
You can attach one menu to another and only update one attached menu.

Code: Select all

EnableExplicit
#Menu = 0
#PopupMenu = 1

Define hMenu, hSubMenu, hPopupMenu
Define MenuItemInfo.MENUITEMINFO

If OpenWindow(0, 200, 200, 200, 100, "Menu Example")
	hMenu = CreateMenu(#Menu, WindowID(0))    ; menu creation starts....
	MenuTitle("Project")
	MenuItem(1, "Open")
	MenuItem(2, "Save")
	MenuItem(3, "Save as")
	MenuItem(4, "Close")
	hSubMenu = OpenSubMenu("Pre")
	MenuItem(5, "Pre1")
	CloseSubMenu()
	
	
	hPopupMenu = CreatePopupMenu(#PopupMenu)
	MenuItem(6, "Cut")
	MenuItem(7, "Copy")
	MenuItem(8, "Paste")
	MenuBar()
	OpenSubMenu("Options")
	MenuItem(9, "Window...")
	MenuItem(10, "Gadget...")
	CloseSubMenu()
	MenuBar()
	MenuItem( 11, "Quit")
	

MenuItemInfo\cbSize = SizeOf(MENUITEMINFO)
MenuItemInfo\fMask = #MIIM_SUBMENU
MenuItemInfo\hSubMenu = hSubMenu
SetMenuItemInfo_(hPopupMenu, 1, #True, @MenuItemInfo)
; SetMenuItemInfo_(MenuID(#PopupMenu), 1, #True, @MenuItemInfo)
DrawMenuBar_(WindowID(0))
	
	
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_RightClick
				DisplayPopupMenu(1, WindowID(0))
			Case #PB_Event_Menu        ; кликнут элемент всплывающего Меню
				Select EventMenu()
					Case 1 : Debug "Menu: Открыть"
				EndSelect
			Case #PB_Event_CloseWindow
				CloseWindow(0)
				End
		EndSelect
	ForEver
EndIf

Re: Adding item in SubMenu closed [Resolved]

Posted: Tue Oct 24, 2023 7:29 pm
by HarrysLad
AZJIO:
You can attach one menu to another and only update one attached menu.
Thanks for the response but it doesn't seem to help much. My understanding of the way Windows does things is practically negative.

What I'm trying to do is insert a variable number (1 to 20) of items dynamically into a submenu. Each item needs to have an ID attached so that I can detect that the user's clicked on it and behave appropriately.

Approaching the problem from a different perspective, the underlying problem is that I can't manage to refresh/update/rebuild my Windows main menu.

The usual
If isMenu(#Menu) : FreeMenu(#Menu) : Endif
approach works well for MacOS and Linux but crashes the main menu in Windows leaving only an empty "File" item in the menu bar.

Any ideas/solutions about either of these things would be most appreciated.

ATB
Dave

Re: Adding item in SubMenu closed [Resolved]

Posted: Tue Oct 24, 2023 10:13 pm
by normeus
HarrysLad,
Since KCC marked this one as solved, you might not get an answer.
You add an ID when you create the menu item with InsertMenu_
Modify Rashad's example, change the select routine to this:

Code: Select all

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
    Case #PB_Event_Menu  
      Select EventMenu()
        Case 1: Debug "Menu 1"
        Case 2: Debug "Menu 2"
        Case 3: Debug "Menu 3"
        Case 4: Debug "Menu 4"
        Case 5: Debug "Menu 5"
        Case 6: Debug "Menu 6"
        Case 7: Debug "Menu 7"
          EndSelect
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          InsertMenu_(hSubmenu_2,-1,#MF_BYCOMMAND|#MF_POPUP,5,"Title_5")  ; item 5
          InsertMenu_(hSubmenu_2,-1,#MF_BYPOSITION|#MF_POPUP,6,"Title_6") ; item 6
          InsertMenu_(hSubmenu_2,-1,#MF_BYPOSITION|#MF_POPUP,7,"Title_7") ; item 7
          DrawMenuBar_(WindowID(0))
        Case 2
          RemoveMenu_(hSubmenu_2,1,#MF_BYPOSITION) ; delete last item 
          DrawMenuBar_(WindowID(0))
      EndSelect
  EndSelect
Until Quit = 1

Norm

Re: Adding item in SubMenu closed [Resolved]

Posted: Wed Oct 25, 2023 2:48 am
by AZJIO
You may have to do the processing of menu items using Winapi. And you need to get events from WM_MENUSELECT.
Of course, I won’t be able to give you the code at once at your request, I need to sleep, then to work, so even if you wish, I can’t do it.

Re: Adding item in SubMenu closed [Resolved]

Posted: Wed Oct 25, 2023 1:06 pm
by HarrysLad
Normeus :
Thanks for that. Everything I needed and now, after a bit of fiddling, it's working fine. :D
I don't often use these API functions - and I hate to include code that I don't understand - so, for reference, could you explain the constant terms in your solution and/or tell me where such information might be found?

AZJIO :
Thanks for your response but Normeus' code does everything I need.

ATB
Dave

Re: Adding item in SubMenu closed [Resolved]

Posted: Wed Oct 25, 2023 8:57 pm
by AZJIO
If you open and close files, then it will be more economical to generate the menu at the time it is opened, at the time the menu is accessed, and not always. It's easier to have a list where you add a file to the beginning or end, and remove it from the other end. And when you request a menu (MF_POPUP), you create it based on the list.
Perhaps you will never open the list during your work session, then why recreate it every time you open/close a file?

Code: Select all

EnableExplicit

#Window = 0
#Menu = 0

Global k = 0
Global hCUI

Procedure WinCallback(hWnd, Msg, wParam, lParam)
	Protected info$, ID, Flags
	ID = wParam & $FFF ; LoWord
	Flags = wParam >> 16 ; HiWord
	
	If Msg = #WM_MENUSELECT
		k + 1
		SetWindowTitle(#Window, "Call " + k)
		If Flags & #MF_CHECKED
			info$ + "MF_CHECKED" + #CRLF$
		EndIf
		If Flags & #MF_DISABLED
			info$ + "MF_DISABLED" + #CRLF$
		EndIf
		If Flags & #MF_GRAYED
			info$ + "MF_GRAYED" + #CRLF$
		EndIf
		If Flags & #MF_HILITE
			info$ + "MF_HILITE" + #CRLF$
		EndIf
		If Flags & #MF_MOUSESELECT
			info$ + "MF_MOUSESELECT" + #CRLF$
		EndIf
		If Flags & #MF_OWNERDRAW
			info$ + "MF_OWNERDRAW" + #CRLF$
		EndIf
		If Flags & #MF_POPUP
			info$ + "MF_POPUP" + #CRLF$
		EndIf
		If Flags & #MF_SYSMENU
			info$ + "MF_SYSMENU" + #CRLF$
		EndIf
		
		SetGadgetText(1, "handle = " + lParam + #CRLF$ + 
		                 "ID = " + ID + #CRLF$ + 
		                 "Flags:" + Flags + #CRLF$ + 
		                 info$)
		
	EndIf
	
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

hCUI = OpenWindow(#Window, 5, 5, 590, 270, "WM_MENUSELECT")
If hCUI
	TextGadget(0, 10, 5, 300, 94, "The WM_MENUSELECT function is triggered when the main or context menu and its items are selected.")
	TextGadget(1, 400, 5, 185, 264, "")
	
	
	If CreateMenu(#Menu, WindowID(#Window))
		MenuTitle("+File")
		MenuItem(1, "Open")
		MenuItem(2, "Save")
		MenuItem(3, "Save as")
		MenuBar()
		OpenSubMenu("Options")
		MenuItem(9, "Window...")
		MenuItem(10, "Gadget...")
		CloseSubMenu()
		MenuItem(4, "Close")
		MenuTitle("Help")
		MenuItem(5, "Web")
		MenuItem(6, "Support")
		SetMenuItemState(#Menu , 1 , #True)
		DisableMenuItem(#Menu , 2 , #True)
	EndIf
	
	SetWindowCallback(@WinCallback())
	
	Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
Simplified version

Code: Select all

EnableExplicit

#Window = 0
#Menu = 0

Global hSubmenu, Allow = 1, em

Procedure WinCallback(hWnd, Msg, wParam, lParam)
	Protected ID, Flags, i
	ID = wParam & $FFF ; LoWord
	Flags = wParam >> 16 ; HiWord

	If Msg = #WM_MENUSELECT
		If ID = 4 And Flags & #MF_POPUP And Allow
			Debug "menu created"
			For i = 10 To 20
				DeleteMenu_(hSubmenu, i, #MF_BYCOMMAND)
			Next
			For i = 10 To 20
				InsertMenu_(hSubmenu, -1, #MF_BYCOMMAND, i, "Path_" + Random(9))
			Next
			DrawMenuBar_(WindowID(0))
			Allow = 0
		ElseIf Flags = $FFFF
			Debug "allow to create menu"
			Allow = 1
		EndIf
	EndIf

	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

If OpenWindow(#Window, 5, 5, 590, 270, "Recent")

	If CreateMenu(#Menu, WindowID(#Window))
		MenuTitle("File")
		MenuItem(1, "Open")
		MenuItem(2, "Save")
		MenuItem(3, "Save as")
		MenuBar()
		hSubmenu = OpenSubMenu("Recent")
		CloseSubMenu()
		MenuItem(5, "Close")

		MenuTitle("Help")
		MenuItem(6, "Web")
		MenuItem(7, "Support")
	EndIf

	SetWindowCallback(@WinCallback())

	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Menu
				em = EventMenu()
				Select em
					Case 10 To 20
						Debug "Array index = " + Str(em - 10)
				EndSelect
			Case #PB_Event_CloseWindow
				CloseWindow(#Window)
				End
		EndSelect
	ForEver
EndIf
You can add a list modification flag. If it has changed, then you recreate the menu again, otherwise use the previously created one.