Window in a Module?
Window in a Module?
Having a program with a main window open, is it possible to use a OpenWindow in a Module and get the events for that seconday windows gadgets to work?
I am trying to write a selfcontained module(with its own window) for general things to be reused in different project.
Another benefit would be to be able to use variable names in the module without conflicting with the main window, like for instance for common gadget names like btnClose etc.
I am trying to write a selfcontained module(with its own window) for general things to be reused in different project.
Another benefit would be to be able to use variable names in the module without conflicting with the main window, like for instance for common gadget names like btnClose etc.
Former VB6 developer adventuring in a brave, new Purebasic world!
Re: Window in a Module?
Code: Select all
; Make sure, that a module named common hold your extra mega super global definitions
; and declare it as the first module of your project.
DeclareModule common
; Enumeration of a Window
Enumeration enumWindows 1
#Window_Main ; = 1
EndEnumeration
EndDeclareModule
Module common
EndModule
; here your super feature module with an extra window...
DeclareModule Blabla1
; Here use the common module with your globals
UseModule common
; and go on to enumerate your windows
Enumeration enumWindows
#Window_BlaBla1 ; = 2
EndEnumeration
EndDeclareModule
Module Blabla1
EndModule
; and now use your globals in the main program
UseModule common
; and more enumerations....
Enumeration enumWindows
#myWindow ; = 3
EndEnumeration
Debug #myWindow ; 3
Debug #Window_Main ; 1
Debug Blabla1::#Window_BlaBla1 ; 2
Re: Window in a Module?
That's exactly what modules are for.Ramses800 wrote:...is it possible to use a OpenWindow in a Module and get the events for that seconday windows gadgets to work?
...selfcontained module(with its own window)...
...to use variable names in the module without conflicting with the main window...
This example implements two modules, both with exactly the same gadget variables, used side by side without any naming conflicts. It utilises the UseModule/UnuseModule function to isolate their respective namespaces:
Code: Select all
DeclareModule Win1
Define.i window, text, string, button
Declare Init()
EndDeclareModule
DeclareModule Win2
Define.i window, text, string, button
Global.s forWin2_andBeyond
Declare Init()
EndDeclareModule
Module Win1
;this GLOBAL variable IS NOT DECLARED in the module declaration
;so it is only available within the Win1 module (Private)
Global.s forWin1_Only = "Win1 String (Private)"
Procedure Init()
Shared window, string, button
window = OpenWindow(#PB_Any, 100, 200, 300, 200, "Win1 Window", #PB_Window_SystemMenu)
text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window ends the app...")
string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin1_Only)
button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Win1 Button")
EndProcedure
EndModule
Module Win2
;this GLOBAL variable IS DECLARED in the module declaration
;so it is available within & without the Win2 module (Public)
forWin2_andBeyond = "Win2 String (Public)"
Procedure Init()
Shared window, string, button
window = OpenWindow(#PB_Any, 440, 200, 300, 200, "Win2 Window", #PB_Window_SystemMenu)
text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window does not end the app...")
string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin2_andBeyond)
button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Press to see Win2 variable...")
EndProcedure
EndModule
Win1::Init()
Win2::Init()
Repeat
event = WaitWindowEvent()
Select EventWindow()
Case Win1::window
UseModule Win1
Select event
Case #PB_Event_CloseWindow
appQuit = 1
Case #PB_Event_Gadget
Select EventGadget()
Case string
Select EventType()
Case #PB_EventType_Change
SetGadgetText(button, "Typing...")
EndSelect
Case button
SetGadgetText(string, "You pressed Win1::button!")
EndSelect
UnuseModule Win1
EndSelect
Case Win2::window
UseModule Win2
Select event
Case #PB_Event_CloseWindow
CloseWindow(window)
Case #PB_Event_Gadget
Select EventGadget()
Case string
Select EventType()
Case #PB_EventType_Change
SetGadgetText(button, "Typing...")
EndSelect
Case button
If Not seenOnce
MessageRequester("Win2::Module", forWin2_andBeyond)
SetGadgetText(button, "Win2 Button")
seenOnce = #True
Else
SetGadgetText(string, "You pressed Win2::button!")
EndIf
EndSelect
EndSelect
UnuseModule Win2
EndSelect
Until appQuit = 1Code: Select all
DeclareModule Win1
Define.i window, text, string, button
Declare Init()
EndDeclareModule
DeclareModule Win2
Define.i window, text, string, button
Global.s forWin2_andBeyond
Declare Init()
EndDeclareModule
Module Win1
;this GLOBAL variable IS NOT DECLARED in the module declaration
;so it is only available within the Win1 module (Private)
Global.s forWin1_Only = "Win1 String (Private)"
Procedure Init()
Shared window, string, button
window = OpenWindow(#PB_Any, 100, 460, 300, 200, "Win1 Window", #PB_Window_SystemMenu)
text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window ends the app...")
string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin1_Only)
button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Win1 Button")
EndProcedure
EndModule
Module Win2
;this GLOBAL variable IS DECLARED in the module declaration
;so it is available within & without the Win2 module (Public)
forWin2_andBeyond = "Win2 String (Public)"
Procedure Init()
Shared window, string, button
window = OpenWindow(#PB_Any, 440, 460, 300, 200, "Win2 Window", #PB_Window_SystemMenu)
text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window does not end the app...")
string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin2_andBeyond)
button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Press to see Win2 variable...")
EndProcedure
EndModule
Win1::Init()
Win2::Init()
Define.s forMainWindowOnly = "MainWindow String"
Define.i window = OpenWindow(#PB_Any, 250, 200, 300, 200, "MainWindow", #PB_Window_SystemMenu)
Define.i text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window ends the app...")
Define.i string = StringGadget(#PB_Any, 50, 80, 200, 30, forMainWindowOnly)
Define.i button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "MainWindow Button")
Repeat
event = WaitWindowEvent()
Select EventWindow()
Case window
Select event
Case #PB_Event_CloseWindow
appQuit = 1
Case #PB_Event_Gadget
Select EventGadget()
Case string
Select EventType()
Case #PB_EventType_Change
SetGadgetText(button, "Typing...")
EndSelect
Case button
SetGadgetText(string, "You pressed MainWindow button!")
EndSelect
EndSelect
Case Win1::window
Select event
Case #PB_Event_CloseWindow
appQuit = 1
Case #PB_Event_Gadget
Select EventGadget()
Case Win1::string
Select EventType()
Case #PB_EventType_Change
SetGadgetText(Win1::button, "Typing...")
EndSelect
Case Win1::button
SetGadgetText(Win1::string, "You pressed Win1::button!")
EndSelect
EndSelect
Case Win2::window
Select event
Case #PB_Event_CloseWindow
CloseWindow(Win2::window)
Case #PB_Event_Gadget
Select EventGadget()
Case Win2::string
Select EventType()
Case #PB_EventType_Change
SetGadgetText(Win2::button, "Typing...")
EndSelect
Case Win2::button
If Not seenOnce
MessageRequester("Win2::Module", Win2::forWin2_andBeyond)
SetGadgetText(Win2::button, "Win2 Button")
seenOnce = #True
Else
SetGadgetText(Win2::string, "You pressed Win2::button!")
EndIf
EndSelect
EndSelect
EndSelect
Until appQuit = 1Hope it helps.
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 
Re: Window in a Module?
@TI-994A:
You can also do the event management within the modules, so the global event loop is not required.
Quickly modified your example:
Using getWindow() only you can send messages/events to the other window via PostEvent().
You can also do the event management within the modules, so the global event loop is not required.
Quickly modified your example:
Code: Select all
DeclareModule MainWindow
Declare Init()
Declare.i getWindow()
EndDeclareModule
DeclareModule ToolWindow
Global.s forToolWindow_andBeyond
Declare Init()
Declare.i getWindow()
EndDeclareModule
Module MainWindow
Global.i window, text, string, button
;this GLOBAL variable IS NOT DECLARED in the module declaration
;so it is only available within the Win1 module (Private)
Global.s forWin1_Only = "Win1 String (Private)"
; Private
Procedure OnCloseWindow() : End : EndProcedure
Procedure OnInputChange() : SetGadgetText(button, "Typing...") : EndProcedure
Procedure OnButtonClicked() : SetGadgetText(string, "You pressed MainWindow::button!") : EndProcedure
; Public
Procedure Init()
window = OpenWindow(#PB_Any, 100, 200, 300, 200, "MainWindow", #PB_Window_SystemMenu)
text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window ends the app...")
string = StringGadget(#PB_Any, 50, 80, 200, 30, forWin1_Only)
button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "MainWindow Button")
BindEvent(#PB_Event_CloseWindow,@OnCloseWindow(),window)
BindGadgetEvent(string,@OnInputChange(),#PB_EventType_Change)
BindGadgetEvent(button,@OnButtonClicked())
EndProcedure
Procedure.i getWindow()
ProcedureReturn window
EndProcedure
EndModule
Module ToolWindow
Global.i window, text, string, button
;this GLOBAL variable IS DECLARED in the module declaration
;so it is available within & without the ToolWindow module (Public)
forToolWindow_andBeyond = "ToolWindow String (Public)"
; Private
Procedure OnCloseWindow() : CloseWindow(window) : EndProcedure
Procedure OnInputChange() : SetGadgetText(button, "Typing...") : EndProcedure
Procedure OnButtonClicked()
Static seenOnce
If Not seenOnce
MessageRequester("ToolWindow::Module", forToolWindow_andBeyond)
SetGadgetText(button, "ToolWindow Button")
seenOnce = #True
Else
SetGadgetText(string, "You pressed ToolWindow::button!")
EndIf
EndProcedure
; Public
Procedure Init()
window = OpenWindow(#PB_Any, 440, 200, 300, 200, "ToolWindow", #PB_Window_SystemMenu)
text = TextGadget(#PB_Any, 50, 30, 250, 30, "Closing this window does not end the app...")
string = StringGadget(#PB_Any, 50, 80, 200, 30, forToolWindow_andBeyond)
button = ButtonGadget(#PB_Any, 50, 130, 200, 30, "Press to see ToolWindow variable...")
BindEvent(#PB_Event_CloseWindow,@OnCloseWindow(),window)
BindGadgetEvent(string,@OnInputChange(),#PB_EventType_Change)
BindGadgetEvent(button,@OnButtonClicked())
EndProcedure
Procedure.i getWindow()
ProcedureReturn window
EndProcedure
EndModule
MainWindow::Init()
ToolWindow::Init()
Repeat : WaitWindowEvent() : ForEverRe: Window in a Module?
Nice, neat, and truly modular.Danilo wrote:You can also do the event management within the modules, so the global event loop is not required.
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 
Re: Window in a Module?
@TI-994A,
@Danilo,
Excellent demo.
Couldn't have done that myself: Always nice to learn something new.
Thank you, both.
@Danilo,
Excellent demo.
Couldn't have done that myself: Always nice to learn something new.
Thank you, both.
DE AA EB
Re: Window in a Module?
Thanks for all the great advice! Off to coding it all up now....
Former VB6 developer adventuring in a brave, new Purebasic world!
Re: Window in a Module?
A followup question about BindGadgetEvent,
Is it possible to supply the Callback with a parameter? I'm thinking of keeping track of multiple windows opened from the module. Something like this(raises a syntax error)
Is it possible to supply the Callback with a parameter? I'm thinking of keeping track of multiple windows opened from the module. Something like this(raises a syntax error)
Code: Select all
BindGadgetEvent(iThisCloseButton,@btnClose_Click(iThisWindow),#PB_EventType_LeftClick) Former VB6 developer adventuring in a brave, new Purebasic world!
Re: Window in a Module?
No, but you can use EventWindow(), EventType(), etc. within your event procedure.
Code: Select all
Procedure btnClose_Click()
IThisWindow = EventWindow() Re: Window in a Module?
@Danilo: Great tip, just what I was looking for!
Former VB6 developer adventuring in a brave, new Purebasic world!
Re: Window in a Module?
A question for Danilo :
In your demo,
There has to be a compelling reason, but it escapes me so far...
In your demo,
why go through the procedure getWindow() to reference the value of the window variable, instead of declaring the variable itself as public ?Danilo wrote:Code: Select all
DeclareModule MainWindow ... Declare.i getWindow() EndDeclareModule DeclareModule ToolWindow ... Declare.i getWindow() EndDeclareModule
There has to be a compelling reason, but it escapes me so far...
Last edited by Blue on Thu Mar 10, 2016 6:42 pm, edited 1 time in total.
PB Forums : Proof positive that 2 heads (or more...) are better than one 
Re: Window in a Module?
No compelling reason. As you've pointed out, while the value could just as easily be referenced via a public variable, he has simply implemented a convenience getter function, presumably to demonstrate the private scope of global variables within a module.Blue wrote:...why go through the procedure getWindow() to reference the value of the window variable, instead of declaring the variable itself as public ?
There has to be a compelling reason, but it escapes me so far...
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 
Re: Window in a Module?
Thank you TI-994A for clarifying that.
That's a relief; I was so sure that I was missing something important here.
That's a relief; I was so sure that I was missing something important here.
PB Forums : Proof positive that 2 heads (or more...) are better than one 
Re: Window in a Module?
Well, if you declare the variable as public, it is also write-able from outside.Blue wrote:A question for Danilo :
why go through the procedure getWindow() to reference the value of the window variable, instead of declaring the variable itself as public ?
There has to be a compelling reason, but it escapes me so far...
There is no read-only access-specifier in PB, so everybody could just overwrite it from the outside.
The Window is handled by the module internally, and to make the Window handle read-only
from the outside, I used the getter-function. Getter without Setter means read-only and
ensures encapsulation.
Re: Window in a Module?
Ah, there's the compelling reasonDanilo wrote:[...]
There is no read-only access-specifier in PB, so everybody could just overwrite it from the outside.
The Window is handled by the module internally, and to make the Window handle read-only
from the outside, I used the getter-function.
[...]
I had a strong intuition that I was missing an important point here.
Thanks for clarifying that, Danilo.
As usual, clear, concise and informative.
As for me, as always, I greatly appreciate the learning opportunity.
PB Forums : Proof positive that 2 heads (or more...) are better than one 

