How to open and reopen a window from a first window?

Just starting out? Need help? Post your questions and find answers here.
User avatar
RBart
User
User
Posts: 35
Joined: Sun May 04, 2025 11:18 am

Re: How to open and reopen a window from a first window?

Post by RBart »

It was taking it over. But the second time it is gone. Not workable. I 'solved' it by manualy coding the menu's in de procedures file. It's getting more clear bit by bit. I'm getting to a system that will be good to build larger applications that is manageable for maintaining. I'm using the template feature for new form procedures. In the template I use something like ;<NameForm> then I highlighted that with the issue tool. Everything starts with the name of the form. So I only need to change that. Find and replace. And a new procedures file is ready to be programmed.
💻 Exploring the world of PureBasic
User avatar
TI-994A
Addict
Addict
Posts: 2790
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to open and reopen a window from a first window?

Post by TI-994A »

If the goal is to create multiple forms without worrying about object clashing, perhaps modules might be a good choice. Coupled with PureBasic's dynamic object numbering (#PB_Any), multiple forms can be created with a fire-and-forget approach, even if they contain duplicate object names.

Here's an example where both forms are called PanelApp with corresponding OpenPanelApp() procedures, and both forms contain buttons named Button_0.

win1Form.pbf

Code: Select all

;
; This code is automatically generated by the Form Designer.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures need to be put in another source file.
;

Global PanelApp

Global Tree_0, Panel_0, Button_0

Enumeration FormMenu
  #MenuItem_1
  #MenuItem_2
  #MenuItem_3
  #MenuItem_4
  #MenuItem_5
EndEnumeration

Procedure OpenPanelApp(x = 0, y = 0, width = 1170, height = 650)
  PanelApp = OpenWindow(#PB_Any, x, y, width, height, "Boekhouding", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CreateMenu(0, WindowID(PanelApp))
  MenuTitle("Bestand")
  MenuItem(#MenuItem_1, "Open Window 2")
  MenuItem(#MenuItem_2, "MenuItem 1")
  MenuItem(#MenuItem_3, "MenuItem 2")
  MenuTitle("Bewerken")
  MenuItem(#MenuItem_4, "MenuItem 3")
  MenuTitle("MenuTitle")
  MenuItem(#MenuItem_5, "MenuItem 4")
  Tree_0 = TreeGadget(#PB_Any, 0, 0, 190, 666)
  Panel_0 = PanelGadget(#PB_Any, 190, 0, 1130, 666)
  AddGadgetItem(Panel_0, -1, "Klanten")
  AddGadgetItem(Panel_0, -1, "Offertes")
  Button_0 = ButtonGadget(#PB_Any, 10, 120, 380, 30, "Window 2 Panel Button")
  CloseGadgetList()
EndProcedure

win2Form.pbf

Code: Select all

;
; This code is automatically generated by the Form Designer.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures need to be put in another source file.
;

Global PanelApp

Global Button_0

Enumeration FormMenu
  #MenuItem_1
EndEnumeration

Procedure OpenPanelApp(x = 0, y = 0, width = 400, height = 200)
  PanelApp = OpenWindow(#PB_Any, x, y, width, height, "Boekhouding Child", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CreateMenu(0, WindowID(PanelApp))
  MenuTitle("MenuTitle")
  MenuItem(#MenuItem_1, "MenuItem 1")
  Button_0 = ButtonGadget(#PB_Any, 10, 120, 380, 30, "Window 2 Button")
EndProcedure

win1Module.pb

Code: Select all

DeclareModule win1
  Declare OpenPanelApp(x = 0, y = 0, width = 1170, height = 650)
  Declare initWin()
  Global PanelApp
  #OpenWin2 = #PB_Event_FirstCustomValue
EndDeclareModule

Module win1
  
  XIncludeFile "win1Form.pbf"
      
  Procedure win1Handler()
    PostEvent(#PB_Event_CloseWindow)
  EndProcedure  
  
  Procedure win1GadgetHandler()
    Select EventGadget()
      Case Tree_0
        Debug "it's the tree from Window 1."
      Case Panel_0
        Debug "it's the panel from Window 1."
      Case Button_0
        Debug "it's the button from Window 1."
    EndSelect  
  EndProcedure  
  
  Procedure win1MenuHandler()
    If EventWindow() = PanelApp
      Select EventMenu()
        Case #MenuItem_1
          PostEvent(#OpenWin2)
        Case #MenuItem_2
          Debug "it's menu 1 from Window 1."
        Case #MenuItem_3
          Debug "it's menu 2 from Window 1."
        Case #MenuItem_4
          Debug "it's menu 3 from Window 1."
        Case #MenuItem_5
          Debug "it's menu 4 from Window 1."        
      EndSelect  
    EndIf
  EndProcedure
  
  Procedure initWin()
    AddGadgetItem (Tree_0, -1, "Tree_0 Item")   
    BindEvent(#PB_Event_Menu, @win1MenuHandler(), PanelApp)
    BindEvent(#PB_Event_Gadget, @win1GadgetHandler(), PanelApp)
    BindEvent(#PB_Event_CloseWindow, @win1Handler(), PanelApp)
  EndProcedure
    
EndModule


win2Module.pb

Code: Select all

DeclareModule win2
  Declare OpenPanelApp(x = 0, y = 0, width = 400, height = 200)
  Declare initWin()
  Global PanelApp 
EndDeclareModule

Module win2
  
  XIncludeFile "win2Form.pbf"
  
  Procedure win2Handler()        
    PostEvent(#PB_Event_CloseWindow)       
  EndProcedure
  
  Procedure win2GadgetHandler()
    Select EventGadget()
      Case Button_0
        Debug "it's the button from Window 2."
    EndSelect  
  EndProcedure
  
  Procedure win2MenuHandler()
    If EventWindow() = PanelApp
      Select EventMenu()
        Case #MenuItem_1
          Debug "it's menu 1 from Window 2."
      EndSelect
    EndIf
  EndProcedure
   
  Procedure initWin() 
    BindEvent(#PB_Event_Menu, @win2MenuHandler(), PanelApp)
    BindEvent(#PB_Event_Gadget, @win2GadgetHandler(), PanelApp)
    BindEvent(#PB_Event_CloseWindow, @win2Handler(), PanelApp)
  EndProcedure
  
EndModule

mainApp.pb

Code: Select all

XIncludeFile "win1Module.pb"
XIncludeFile "win2Module.pb"

win1::OpenPanelApp()
win1::initWin()   

Repeat
  event = WaitWindowEvent()
  
  Select event  
    Case win1::#OpenWin2
      win2::OpenPanelApp()
      win2::initWin()  
    Case #PB_Event_CloseWindow
      Select EventWindow()
        Case win1::PanelApp 
          appQuit = #True
        Case win2::PanelApp 
          CloseWindow(win2::PanelApp)
      EndSelect
  EndSelect
  
Until appQuit

The two forms work seamlessly together and their dynamically-assigned object names do not clash, despite being exactly the same.

However, the clear caveat, even with modules, is the menu. The menu from win1 was lost after opening/closing win2. In the PureBasic form designer, there is currently no way of creating menus with dynamic numbering, relegating them to always being created with the object number zero. Each subsequently opened form with menus would invariably overwrite the menu of the active form.

While the object numbers of the menus could be manually amended, the form designer would simply revert such changes whenever it is edited.

To circumvent this, here is a short routine that could automate the process each time the forms have been edited. Simply include the form names in the array here, and run it before debugging the project, or even before final compilation. Whenever the form files are edited again, save and close them, and run this again. It simply changes the menu object numbers for each form incrementally, and would not corrupt the original form files themselves.

Code: Select all

Dim forms.s(1)  ; increase as required

forms(0) = "win1Form.pbf"
forms(1) = "win2Form.pbf"

For i = 0 To 1
  form$ = ""
  ReadFile(0, forms(i))
  While Not Eof(0)
    line$ = ReadString(0)
    If FindString(line$, "CreateMenu(0")
      line$ = ReplaceString(line$, "CreateMenu(0", "CreateMenu(" + i)
    EndIf
    form$ + line$ + #CRLF$    
  Wend
  CloseFile(0)
  OpenFile(0, forms(i))
  WriteString(0, form$)
  CloseFile(0)
Next i     

After running the above code, run mainApp.pb again, and the menus for win1 would remain intact after opening/closing win2.

Reopening the form files for further editing would undo these changes, with no harm done.

With modules, and this small workaround, working with PureBasic's form designer becomes a breeze again. :wink:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
RBart
User
User
Posts: 35
Joined: Sun May 04, 2025 11:18 am

Re: How to open and reopen a window from a first window?

Post by RBart »

So modules act as events. Module::event()?
I will look if this would make life simpler. In the meantime I have about 8 windows running.

Templates make a difference. So does issues.

I found how to copy the prefs. Would be nice to see a way to backup or transfer them in the IDE.

I think in VB and VBA modules are standard and not showing how they connect. Just select the object and the event and code away. But not complaining. Purebasic has a lot more going for it. Just need to get into it.
💻 Exploring the world of PureBasic
User avatar
TI-994A
Addict
Addict
Posts: 2790
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: How to open and reopen a window from a first window?

Post by TI-994A »

RBart wrote: Sun Jan 04, 2026 5:05 pmSo modules act as events. Module::event()?
Not at all. Modules introduce the concept of namespaces to PureBasic. Their environments are virtual blackboxes, so duplicate names and labels would not clash between them.

In the example provided, the two forms are called by their corresponding handlers, which have been placed within independent modules. So the constant names, variable names, and procedure labels of the two forms would not clash, despite being duplicates.

In the example, the #OpenWin2 constant from win1 is simply a custom event, assigned the first custom value, #PB_Event_FirstCustomValue. So, when posted with the PostEvent() function from win1, the event loop of the mainApp would be able to read it.

Code: Select all

...
...
Repeat
  event = WaitWindowEvent()  
  Select event  
    Case win1::#OpenWin2   ; <--- detecting the custom event posted from win1
...
...

There is one exception to the module's blackboxing property. Object numbers transcend these namespaces, as they are universal, and thus accessible from any namespace.

For example, in this dynamic object numbering approach, two or more forms can have buttons called Button_0,

Code: Select all

Button_0 = ButtonGadget(#PB_Any, 10, 10, 100, 30, "Button")
This is because the variable name belongs to its containing namespace; win1::Button_0, win2::Button_0, etc. But the values assigned to them are different.

However, if an object is defined statically like this, the object with the number [0] is universal across all code and modules.

Code: Select all

ButtonGadget(0, 10, 10, 100, 30, "Button")
If another object is later defined with the number [0], the earlier one will be overwritten. This is the same issue plaguing menus created with the form designer.

Anyway, modules provide a sound and simple approach to keeping forms and code separate while handling multi-form projects.

PureBasic is very powerful in its own unique ways, and it shouldn't be compared to other development environments.

Learn it and use it, and you'll love it. :wink:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
RBart
User
User
Posts: 35
Joined: Sun May 04, 2025 11:18 am

Re: How to open and reopen a window from a first window?

Post by RBart »

Thanks for clarifying TI-994A

I will dive deeper into modules.

Already in love with PureBasic.
But after a long marriage... :wink:

Greetings from Belgium
Rudi
💻 Exploring the world of PureBasic
Post Reply