Nudgy wrote: Wed Aug 07, 2024 8:17 pm... I would like the event handling for the child window to be handled not in the "main" event loop, but in the include file, so that the main code only needs to call ShowMyCommonWindow1() and more or less nothing else. ...
Technically speaking, implementing multiple event loops is not wrong, although it's considered a poor design paradigm. All system events should ideally be routed through a centralised handler, and any additional components should be designed for modular integration into the main code.
Here's a simple working example to demonstrate this, and it also satisfies your
plug&play requirement:
the main window file:
Code: Select all
EnableExplicit
Enumeration windows
#mainWindow
EndEnumeration
Enumeration timers
#mainWindowTimer
EndEnumeration
Enumeration gadgets
#mainOpenModalButton
#mainEditor
#mainEditorLabel
#mainQuitButton
#mainTimeLabel
#mainTimeDisplay
EndEnumeration
Define wFlags, event, appQuit, modalWindow1
;###### include the modal window code ######
IncludeFile "myCommonWindow1.pbi"
;###########################################
wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(#mainWindow, #PB_Ignore, #PB_Ignore, 800, 500,
"A Multi-Window Handler Example", wFlags)
TextGadget(#mainTimeLabel, 630, 20, 60, 30, "Time: ")
TextGadget(#mainTimeDisplay, 700, 20, 80, 30, "00:00:00")
TextGadget(#mainEditorLabel, 40, 60, 400, 30,
"Text returned from the modal window:")
EditorGadget(#mainEditor, 40, 100, 720, 300)
ButtonGadget(#mainOpenModalButton, 40, 440, 250, 30, "SHOW MODAL WINDOW")
ButtonGadget(#mainQuitButton, 560, 440, 200, 30, "QUIT")
AddWindowTimer(#mainWindow, #mainWindowTimer, 1000)
;##################### add the modal window ######################
modalWindow1 = initMyCommonWindow1(#mainWindow, #mainEditor)
;#################################################################
Repeat
event = WaitWindowEvent()
Select EventWindow()
Case #MainWindow
Select event
Case #PB_Event_CloseWindow
Select EventWindow()
Case #mainWindow
appQuit = #True
EndSelect
Case #PB_Event_Timer
Select EventTimer()
Case #mainWindowTimer
SetGadgetText(#mainTimeDisplay,
FormatDate("%hh:%ii:%ss", Date()))
EndSelect
Case #PB_Event_Gadget
Select EventGadget()
;############## show the modal window ###############
Case #mainOpenModalButton
showMyCommonWindow1()
;####################################################
Case #mainQuitButton
appQuit = #True
EndSelect
EndSelect
;###### relay all the modal window events ######
Case modalWindow1
processMyCommonWindow1Events(event)
;###############################################
EndSelect
Until appQuit
the modal window include file (myCommonWindow1.pbi):
Code: Select all
Enumeration windows
#modal1Window
EndEnumeration
Enumeration timers
#modal1Timer
EndEnumeration
Enumeration gadgets
#modal1TimeLabel
#modal1TimeDisplay
#modal1Editor
#modal1EditorLabel
#modal1SayHelloButton
#modal1RelayToParentWindow
#modal1QuitButton
EndEnumeration
Define parentWindow = -1, relayGadget = -1
Macro prompt(window, message)
MessageRequester(window, message, #PB_MessageRequester_Ok)
EndMacro
Procedure initMyCommonWindow1(parentWindowNumber, relayGadgetNumber)
Shared parentWindow, relayGadget
parentWindow = parentWindowNumber
relayGadget = relayGadgetNumber
ProcedureReturn #modal1Window
EndProcedure
Procedure showMyCommonWindow1()
Shared parentWindow
Define wFlags = #PB_Window_SystemMenu | #PB_Window_WindowCentered
DisableWindow(parentWindow, #True)
OpenWindow(#modal1Window, #PB_Ignore, #PB_Ignore, 600, 300, "My Common Window 1",
wFlags, WindowID(parentWindow))
TextGadget(#modal1TimeLabel, 430, 20, 60, 30, "Time: ")
TextGadget(#modal1TimeDisplay, 500, 20, 80, 30, "00:00:00")
TextGadget(#modal1EditorLabel, 20, 50, 250, 30, "Type something:")
EditorGadget(#modal1Editor, 20, 80, 560, 150)
ButtonGadget(#modal1SayHelloButton, 20, 250, 150, 30, "SAY HELLO!")
ButtonGadget(#modal1QuitButton, 430, 250, 150, 30, "CLOSE ME!")
ButtonGadget(#modal1RelayToParentWindow, 200, 250, 200, 30, "RELAY TO PARENT")
AddWindowTimer(#modal1Window, #modal1Timer, 1000)
EndProcedure
Procedure processMyCommonWindow1Events(event)
Shared parentWindow, relayGadget
Select event
Case #PB_Event_CloseWindow
DisableWindow(parentWindow, #False)
CloseWindow(EventWindow())
Case #PB_Event_Timer
Select EventTimer()
Case #modal1Timer
SetGadgetText(#modal1TimeDisplay,
FormatDate("%hh:%ii:%ss", Date()))
EndSelect
Case #PB_Event_Gadget
Select EventGadget()
Case #modal1SayHelloButton
prompt(GetWindowTitle(EventWindow()), "Modal Window 1 says Hello!")
Case #modal1RelayToParentWindow
If relayGadget <> -1 And IsGadget(relayGadget)
SetGadgetText(relayGadget, GetGadgetText(#modal1Editor))
Else
prompt(GetWindowTitle(EventWindow()), "No relay gadget initialised!")
EndIf
Case #modal1QuitButton
DisableWindow(parentWindow, #False)
CloseWindow(EventWindow())
EndSelect
EndSelect
EndProcedure
The modal window could be easily integrated into any main code in four simple steps:
1. include the modal window code:
>
IncludeFile "myCommonWindow1.pbi"
2. initialise the window
(with one optional parameter):
>
modalWindow1 = initMyCommonWindow1(#mainWindow [, #mainEditor])
3. call the modal window whenever required:
>
showMyCommonWindow1()
4. intercept and relay the modal window events back to it:
>
processMyCommonWindow1Events(event)
The modal window include file is simply dropped in without requiring any modifications to its code. The main window has no visibility of the gadgets within the modal window, nor does it process any of its events. The main event loop will simply relay all events triggered by the modal window back to it to be processed autonomously.
This example includes a simple inter-window function which relays any text typed into the modal window editor to the main window editor. If no relay gadget is initialised
(initMyCommonWindow1(#mainWindow, -1)), the relay function will be ignored. Again, this approach is just a POC - there are many other ways to achieve this.
I hope this helps.
