Page 1 of 2

#PB_ANY for MenuItem

Posted: Wed Aug 11, 2004 8:15 pm
by Shannara
It is nice that PB is have gone mostly dynamic since the introduction of #PB_ANY, however, I found out that #PB_ANY does not work for MenuItem, this would be quite helpfull in order to have dynamic menus.

Re: #PB_ANY for MenuItem

Posted: Sun Aug 15, 2004 6:11 am
by Randy Walker
Shannara wrote:It is nice that PB is have gone mostly dynamic since the introduction of #PB_ANY, however, I found out that #PB_ANY does not work for MenuItem, this would be quite helpfull in order to have dynamic menus.
You're more versed with PB than I am, and I don't know what #PB_ANY does just yet, but you've been really helpful to me (and many others I see) so I want to be the first to say "I second this motion" :-)

Besides, this #PB_ANY thing seems to get used a lot so anticipate others would find it useful too. (Twidlling thumbs and holding my breath as the hours count down on Freds return.)

Re: #PB_ANY for MenuItem

Posted: Sun Aug 15, 2004 8:36 am
by PB
> I don't know what #PB_ANY does

It's designed so you don't need to specify constant names for gadgets.
Here's two examples that do the same thing, with and without #PB_Any:

Code: Select all

; WITHOUT #PB_ANY

If OpenWindow(1,300,250,400,200,#PB_Window_SystemMenu,"Window")
  CreateGadgetList(WindowID())
  #button1=1 : ButtonGadget(#button1,50,50,60,25,"1")
  #button2=2 : ButtonGadget(#button2,150,50,60,25,"2")
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget
      Select EventGadgetID()
        Case #button1 : Debug "1"
        Case #button2 : Debug "2"
      EndSelect
    EndIf
  Until ev=#PB_EventCloseWindow
EndIf

Code: Select all

; WITH #PB_ANY

If OpenWindow(1,300,250,400,200,#PB_Window_SystemMenu,"Window")
  CreateGadgetList(WindowID())
  b1=ButtonGadget(#PB_Any,50,50,60,25,"1")
  b2=ButtonGadget(#PB_Any,150,50,60,25,"2")
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget
      Select EventGadgetID()
        Case b1 : Debug "1"
        Case b2 : Debug "2"
      EndSelect
    EndIf
  Until ev=#PB_EventCloseWindow
EndIf

Re: #PB_ANY for MenuItem

Posted: Sun Aug 15, 2004 12:48 pm
by Randy Walker

Code: Select all

; WITHOUT #PB_ANY

  #button1=1 : ButtonGadget(#button1,50,50,60,25,"1")
  #button2=2 : ButtonGadget(#button2,150,50,60,25,"2")
  
; WITH #PB_ANY

  b1=ButtonGadget(#PB_Any,50,50,60,25,"1")
  b2=ButtonGadget(#PB_Any,150,50,60,25,"2")
Perfectly clear... thanks PB

Ok, I see simpler code but no distinct functional advantage, unless b1 and b2 could be replaced with b(1) and b(2) when using MenuItem.

Is #PB_ANY not allowed for MenuItem in both CreateMenu and CreatePopupMenu routines? CreateMenu seems to replace the default "system menu" for a window and I'm thinking PB may not find a popup menu so gummy to work with internally... guessing.

Posted: Sun Aug 15, 2004 4:28 pm
by Shannara
When you get into high numbers with enumeration or such, the PB program will crash. Also, this is more dynamic, before PB_ANY PB was majorly restrictive.. I mean HUGELY restrictive. Believe or not, for some odd reason the PureVision author still uses enumerations instead of PB_ANY for it's generated code.... I guess some people are not into dynamic code generation :D

Anyways, its quite helpfull for anything to do with database, games, networking, etc. As with anything you do not know the exact number of objects the user would be using.

Anyways, I was suprised Fred havent added this into the menu commands... really weird, actually.

Re: #PB_ANY for MenuItem

Posted: Sun Aug 15, 2004 10:04 pm
by PB
> I see simpler code but no distinct functional advantage

It means you don't have to declare a million constants if you have a million
gadgets. :) Let's say you have 20 x ButtonGadgets... compare the code:

Code: Select all

; WITH #PB_ANY

Dim gid(20)
If OpenWindow(1,200,150,600,450,#PB_Window_SystemMenu,"Window")
  CreateGadgetList(WindowID())
  For n=1 To 20
    gid(n)=ButtonGadget(#PB_Any,n*20,n*20,30,25,Str(n))
  Next
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget
      For n=1 To 20
        If EventGadgetID()=gid(n) : Debug n : Break : EndIf
      Next
    EndIf
  Until ev=#PB_EventCloseWindow
EndIf

Code: Select all

; WITHOUT #PB_ANY

If OpenWindow(1,200,150,600,450,#PB_Window_SystemMenu,"Window")
  CreateGadgetList(WindowID())
  #gid1=1 : n+1 : ButtonGadget(#gid1,n*20,n*20,30,25,Str(n))
  #gid2=2 : n+1 : ButtonGadget(#gid2,n*20,n*20,30,25,Str(n))
  #gid3=3 : n+1 : ButtonGadget(#gid3,n*20,n*20,30,25,Str(n))
  #gid4=4 : n+1 : ButtonGadget(#gid4,n*20,n*20,30,25,Str(n))
  #gid5=5 : n+1 : ButtonGadget(#gid5,n*20,n*20,30,25,Str(n))
  #gid6=6 : n+1 : ButtonGadget(#gid6,n*20,n*20,30,25,Str(n))
  #gid7=7 : n+1 : ButtonGadget(#gid7,n*20,n*20,30,25,Str(n))
  #gid8=8 : n+1 : ButtonGadget(#gid8,n*20,n*20,30,25,Str(n))
  #gid9=9 : n+1 : ButtonGadget(#gid9,n*20,n*20,30,25,Str(n))
  #gid10=10 : n+1 : ButtonGadget(#gid10,n*20,n*20,30,25,Str(n))
  #gid11=11 : n+1 : ButtonGadget(#gid11,n*20,n*20,30,25,Str(n))
  #gid12=12 : n+1 : ButtonGadget(#gid12,n*20,n*20,30,25,Str(n))
  #gid13=13 : n+1 : ButtonGadget(#gid13,n*20,n*20,30,25,Str(n))
  #gid14=14 : n+1 : ButtonGadget(#gid14,n*20,n*20,30,25,Str(n))
  #gid15=15 : n+1 : ButtonGadget(#gid15,n*20,n*20,30,25,Str(n))
  #gid16=16 : n+1 : ButtonGadget(#gid16,n*20,n*20,30,25,Str(n))
  #gid17=17 : n+1 : ButtonGadget(#gid17,n*20,n*20,30,25,Str(n))
  #gid18=18 : n+1 : ButtonGadget(#gid18,n*20,n*20,30,25,Str(n))
  #gid19=19 : n+1 : ButtonGadget(#gid19,n*20,n*20,30,25,Str(n))
  #gid20=20 : n+1 : ButtonGadget(#gid20,n*20,n*20,30,25,Str(n))
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget
      Select EventGadgetID()
        Case #gid1 : Debug "1"
        Case #gid2 : Debug "2"
        Case #gid3 : Debug "3"
        Case #gid4 : Debug "4"
        Case #gid5 : Debug "5"
        Case #gid6 : Debug "6"
        Case #gid7 : Debug "7"
        Case #gid8 : Debug "8"
        Case #gid9 : Debug "9"
        Case #gid10 : Debug "10"
        Case #gid11 : Debug "11"
        Case #gid12 : Debug "12"
        Case #gid13 : Debug "13"
        Case #gid14 : Debug "14"
        Case #gid15 : Debug "15"
        Case #gid16 : Debug "16"
        Case #gid17 : Debug "17"
        Case #gid18 : Debug "18"
        Case #gid19 : Debug "19"
        Case #gid20 : Debug "20"
      EndSelect
    EndIf
  Until ev=#PB_EventCloseWindow
EndIf

Re: #PB_ANY for MenuItem

Posted: Sun Aug 15, 2004 10:56 pm
by Randy Walker

Code: Select all

; WITH #PB_ANY

Dim gid(20)
If OpenWindow(1,200,150,600,450,#PB_Window_SystemMenu,"Window")
  CreateGadgetList(WindowID())
  For n=1 To 20
    gid(n)=ButtonGadget(#PB_Any,n*20,n*20,30,25,Str(n))
  Next
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget
      For n=1 To 20
        If EventGadgetID()=gid(n) : Debug n : Break : EndIf
      Next
    EndIf
  Until ev=#PB_EventCloseWindow
EndIf
Ok, now I see a disticnt advantage. This type approach was not allowed in GFA Basic (or at least I never figured out how) so I am accustomed to doing it the long way, except I would specify the gadget number as a constant; ButtonGadget(1,20,20,30,25,"button 1")
Then again, my project only uses slightly over hundred gadgets and I only have the one project. Still, I can see where #PB_ANY will be very handy when I port to PureBasic - Thanks PB - also very helpful - excellent sample code comparison too!

Shannara - My project is a database oriented, but each record only has about 50 fields so in my case, the long approach has not been a great challenge. That being my only project, extending the use of #PB_ANY into MenuItem wont help me a lot, but for those with more serious projects, PB's example above does signify a strong advantage so I'm sticking with the motion in favor of this enhancement.

Re: #PB_ANY for MenuItem

Posted: Fri Oct 15, 2004 1:08 pm
by Randy Walker
- EDITED -
Shannara wrote:...this would be quite helpfull in order to have dynamic menus.
If it is only the gadget constants and #PB_ANY stopping you from having dynamic popups... it shouldn't. Maybe I misunderstood, but i've devised a means of using ONLY one single popup routine to "display" any selection I want. Maybe it can help you. (Should be useful to someone - need to do something to gain myself some brownie points around here. :))

Code: Select all

; Psuedo Dynamic PopUp created by Randy Walker using snippets from PB forum,
; PB manual, MS-refereces and a lot of hacking.
; Enjoy unresticted at your own risk...

; Enumerate each selection possible throughout your entire program here!!!
Enumeration
  #pick_1
  #pick_2
  #pick_3
  #pick_4
  #pick_5
  #pick_6
  #pick_7
  #pick_8
EndEnumeration


; Create dynamic popup "ONLY ONCE" and REUSE as desired!!!
PU_HND.w = CreatePopupMenu(0)   ; Begin creating dynamic pop-up.
If PU_HND
  MenuItem(#pick_1, "ITEM 1") ; just like in a normal menu... 
  MenuItem(#pick_2, "ITEM 2") 
  MenuItem(#pick_3, "ITEM 3") 
  ; "New ITEM 4" Not added yet - See InsertMenu_() below.
  ; "New ITEM 5" Not added yet - See InsertMenu_() below.
EndIf 

Procedure handlePopup(x,y)
  Repeat ; enumerated "Case" options remain static for handling purposes.
    Event = WaitWindowEvent()
    Select Event     ; check for window events.
      Case #WM_RButtonDown       ; right mouse button was clicked.
        PopUpPos = DisplayPopupMenu(0,WindowID(),x,y)  ; now display the popup-menu.
      Case #PB_EventMenu         ; an item of the popup-menu was clicked.
        Select EventMenuID()     ; get the clicked menu item... 
          Case #pick_1 : Debug "Menu: ITEM 1" 
          Case #pick_2 : Debug "Menu: ITEM 2" 
          Case #pick_3 : Debug "Menu: ITEM 3" 
          Case #pick_4 : Debug "Menu: ITEM 4" ;Not added yet.
          Case #pick_5 : Debug "Menu: ITEM 5" ;Not added yet.
          Case #pick_6 : Debug "Menu: ITEM 6" ;Not added yet.
          Case #pick_7 : Debug "Menu: ITEM 7" ;Not added yet.
          Case #pick_8 : Debug "Menu: ITEM 8" ;Not added yet.
            ; This procedure MUST remain static to index properly -AND- all
            ; "Case" selections MUST be included here for every popup item
            ; to be included in your program.
        EndSelect
    EndSelect 
  Until Event = #PB_Event_Menu  ; 
EndProcedure


;/ DO NOT "CreatePopupWindow" AGAIN!!!  Just call handlePopup() as desired.
; Use the "#pick_n" handle to setup your selections before each
; handlePopup() call.  Just insert, delete and modify labels as needed.


;/ Going into 1st popup sample loop...
If OpenWindow(0, 200, 400, 350, 120, #PB_Window_SystemMenu, "Right Click Popup 1 Sample  --  PICK ONE To Continue!") 

  ; 1st setup performed above using CreatePopupWindow()
  handlePopup(210,440)    
  
EndIf 
HideWindow(0,1)  ; hide this window for a moment...


; Now demonstrate "same" dynamic popup on top of "ANOTHER" parent window.

If OpenWindow(1, 200, 500, 350, 120, #PB_Window_SystemMenu, "Right Click Popup 2 Sample  --  PICK ONE To Continue!") 
  
  ; Setup again before calling handlePopup()
  
  ; insert where #pick_2 is, pushing #2 and rest down.
  InsertMenu_(PU_HND,#pick_2, #MFT_STRING ,#pick_4, "New ITEM 4")

  ; insert where #pick_2 is, coming in just below new item 4.
  InsertMenu_(PU_HND,#pick_2, #MFT_STRING ,#pick_5, "New ITEM 5")
  ; 2nd parameter is reference item - indexed relative to #pick_n.
  ; 4th parameter is new item ID as indexed in handlePopup & enumeration.
  ; try swapping these two insertMenu lines for fun.
  ; also try setting both "2nd parameters" to #pick_2.
  handlePopup(240,560) ; uses screen coordinate so figure this yourself :)
  
  
  ; NOW - Popup again for 2nd parent but show ONLY NEW menu items.
  SetWindowTitle(1,"Right Click Popup 3 Sample  --  PICK ONE To Continue!") 
  
  ; Setup again before calling handlePopup()
  
  ; First clear our original items before replacing.
  RemoveMenu_(PU_HND, 0, #MF_BYPOSITION) ;remove first item on list.
  RemoveMenu_(PU_HND, 0, #MF_BYPOSITION) ;do it again.  Item 1 & 5 gone.
  
  ; ... and add 3 new selections, (top and bottom).
  InsertMenu_(PU_HND, 0, #MFT_STRING ,#pick_6, "New ITEM 6") ; 0 for top
  InsertMenu_(PU_HND, 0, #MFT_STRING ,#pick_7, "New ITEM 7") 
  InsertMenu_(PU_HND,-1, #MFT_STRING ,#pick_8, "New ITEM 8")  ; -1 will append
  handlePopup(100,500)
  
  ; NOW - Popup again for 2nd parent but show ONLY NEW menu items.
  SetWindowTitle(1,"Right Click Popup 4 Sample  --  PICK ONE To QUIT!") 
  
  ; Setup again before calling handlePopup()
  
  ModifyMenu_(PU_HND, #pick_6, #MFT_STRING, #pick_6, "2nd New ITEM 6")
  ModifyMenu_(PU_HND, #pick_3, #MFT_STRING, #pick_3, "New ITEM 3")
  handlePopup(100,500)
  
EndIf 
CloseWindow(0)
CloseWindow(1)
End

Posted: Fri Oct 15, 2004 1:27 pm
by Karbon
#PB_Any still feels like a hack to me. I do see the benefit if you are dynamically creating gadgets, but to use this feature all the time just isn't necessary - especially when the bulk of GUI design is done through a WYSIWYG editor like Visual Designer or PureVision. If Paul had changed PureVision to use PB_Any it would have invalidated all code written with PureVision. I don't want to go through all my code and change the constants to variables and I think Paul feels the same way.

I have an extremely large PB project with a whole lot of controls - I've never had a crash due to a high enumeration value. If you can reproduce that, report it as a bug!

Posted: Fri Oct 15, 2004 1:34 pm
by Dare2
Horses for courses.

PureBasic is richer for having #PB_Any. It is not the best approach all of the time, but it is the better approach some of the time.

:)

Posted: Fri Oct 15, 2004 1:42 pm
by PB
> #PB_Any still feels like a hack to me

There were many people requesting it over and over in the past (do a search
and you'll see) which is why it was eventually added. This is not meant to set
a precedent though!

Posted: Fri Oct 15, 2004 1:58 pm
by Randy Walker
I agree with both sides... #PB_ANY feels like a hack, and enumeration is a bother. I could say the same about programming too :lol:

Posted: Fri Oct 15, 2004 6:21 pm
by Randy Walker
I cleanup up my code a bit to make the demo more user friendly.

Also added ModifyMenu to just rename an item.

Posted: Sat Oct 16, 2004 12:27 am
by Karbon
I know people wanted it.. I'm glad that it was just added on and not changed.

Posted: Sat Oct 16, 2004 1:22 am
by tinman
Karbon wrote:#PB_Any still feels like a hack to me. I do see the benefit if you are dynamically creating gadgets...
Not just that, but if you are writing some functions which create windows and gadgets for general use then #PB_Any means you aer guaranteed not to interfere with any other gadgets in the users code. Remember that any gadget ID must be completely unique across the entire application (something else I'm not a fan of), so hardcoding everything isn't great.

Of course, doing it that way also became less hassle since the introduction of enumerations, so the advantage of #PB_Any isn't as big as it was.

I tend to use both styles depending on the size of the project and what it needs to do. I'm glad we have that ability.