For these things you don't have to write code in your own program anymore.
For whom is WinHandler intended?
All those who don't get along with the PureBasic dialog library (or don't want to use it) and prefer to create window interfaces in the "usual" way.
Automatic alignment:
PureBasic gadgets can be anchored to one or more sides of the window with so-called "anchors" during creation. When the window is resized, the gadgets are automatically repositioned or resized according to their anchor points.
Saving of window geometry and variables:
Furthermore, the module offers functions to save and reload the position and size of all windows of an application in an INI file. Furthermore, any amount of data can be stored at windows managed by the WinHandler for management (currently only strings). These data are stored also automatically in the INI file.
Herewith the management (save/load) of all settings of an application can be realized by the WinHandler.
A program, which uses the WinHandler, should have the following structure:
Code: Select all
; Register all windows used by the program by name at WinHandler.
; The windows are not yet open at that time
wh::whAddWindow("main")
wh::whAddWindow("settings")
; Load the data from the INI file
wh::whLoadWindowData("C:\Users\...\MyProgramm.ini)
; Then the main window is opened (see also below)
If Main_OpenWindow()
Repeat
WaitWindowEvent()
Until iQuit = #True
EndIf
; Finally, all windows must be removed from the Winhandler
wh::whRemoveWindow("settings")
wh::whRemoveWindow("main")
In the procedure that opens the window(s) of the program (here "Main_OpenWindow()") the minimal code looks like this:
UseModule WH
; Open the previously registered window via the WinHandler
whOpenWindow("main", #PB_Ignore, #PB_Ignore, 400, 220, "Windowtitel", #PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_SizeGadget|#PB_Window_Invisible)
; Add gadgets via the WinHandler
whAddGadget("main", "frame", FrameGadget(#PB_Any, 5, 5, 390, 165, "Frame"), #Anchor_Left | #Anchor_Top | #Anchor_Right | #Anchor_Bottom)
whAddGadget("main", "button ok", ButtonGadget(#PB_Any, 5, 180, 90, 35, "Ok", #PB_Button_Default), #Anchor_Left | #Anchor_Bottom, @Main_Event_CloseWindow(), #PB_EventType_LeftClick)
whAddGadget("main", "button cancel", ButtonGadget(#PB_Any, 305, 180, 90, 35, "Cancel"), #Anchor_Right | #Anchor_Bottom, @Main_Event_CloseWindow(), #PB_EventType_LeftClick)
BindEvent(#PB_Event_CloseWindow, @Main_Event_CloseWindow(), whGetWindowNumber("main"))
HideWindow(whGetWindowNumber("main"), #False)
The following command is used to close the window:
whCloseWindow("main")
The module has a demo, which is executed if you just start the module with F5.
The module provides the following commands:
Code: Select all
whAddWindow(sWindowName.s, iSaveGeometry.i=#True, iSaveUserData.i=#True)
; +-----------------------------------------------------------------
; |Description : Registers a new window with its name in the WinHandler and sets the flags iSaveGeometry and iSaveUserData
; |Arguments : sWindowName : Name under which the window is to be addressed
; | : iSaveGeometry: Defines whether this window should be taken into account when saving the window geometries to the INI file
; | : iSaveUserData: Determines whether the attached user data of this window should be taken into account when saving to the INI file
; |Results : #True/#False
; |Remarks : If whAddWindow() is not called by the programmer, then this is automatically made up for by whOpenWindow()
; +-----------------------------------------------------------------
whRemoveWindow(sWindowName.s)
; +-----------------------------------------------------------------
; |Description : Removes a window previously registered by whAddWindow() from WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
whOpenWindow(sWindowName.s, ix.i=#PB_Ignore, iy.i=#PB_Ignore, iWidth.i=600, iHeight.i=800, sTitel.s="", iFlags.i=-2, iParentWindow=-2)
; +-----------------------------------------------------------------
; |Description : Opens a PureBasic window (same parameter sequence, except window name)
; | : and registers the events #PB_Event_SizeWindow and #PB_Event_MoveWindow in the WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; | : For all other parameters see OpenWindow() in the PureBasic help file
; |Results : Returns the PB object number of the opened window or 0 in case of errors
; |Remarks : -
; +-----------------------------------------------------------------
whCloseWindow(sWindowName.s)
; +-----------------------------------------------------------------
; |Description : Closes a window managed by WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
whGetWindowNumber(sWindowName.s)
; +-----------------------------------------------------------------
; |Description : Returns the PB object number of a window registered in WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; |Results : Returns the PB object number of the window or 0 in case of errors
; |Remarks : -
; +-----------------------------------------------------------------
whSetWindowData(sWindowName.s, sDataKey.s, sData.s)
; +-----------------------------------------------------------------
; |Description : Stores a user-defined string at the window
; |Arguments : sWindowName: Name of the window where the data string is to be stored
; | : sDataKey : Name under which the data string is to be identified
; | : sData : The data string
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
whGetWindowData(sWindowName.s, sDataKey.s)
; +-----------------------------------------------------------------
; |Description : Returns the value of a user-defined string previously stored at a window
; |Arguments : sWindowName: Name of the window with which the data string is associated
; | : sDataKey : Name of the data string
; |Results : The user-defined string or an empty string, in case of errors
; |Remarks : -
; +-----------------------------------------------------------------
whRemoveWindowData(sWindowName.s, sDataKey.s="")
; +-----------------------------------------------------------------
; |Description : Removes a user-defined string previously stored at a window
; |Arguments : sWindowName: Name of the window with which the data string is associated
; | : sDataKey : Name of the data string
; |Results : #True/#False
; |Remarks : If sDataKey="", then all data strings associated with this window will be removed
; +-----------------------------------------------------------------
whSaveWindowData(sFileName.s, iIncludeUserData=#True, iDeleteOldFile=#False)
; +-----------------------------------------------------------------
; |Description : Saves the geometry and the data strings of all windows to an INI file
; |Arguments : sFileName : Path and filename of the INI file
; | : iIncludeUserData: Determines whether the data strings should also be saved
; | : This overrides the iSaveGeometry option on whAddWindow(), even if iSaveGeometry = #true
; | : for some windows. If iIncludeUserData = #False, then no data strings are saved at all,
; | : only the window geometries are saved
; | : iDeleteOldFile: If #True, then the file will be completely rebuilt instead of updating it
; | : (thus removing old data strings as well. Useful if they are no longer used in the program)
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
whLoadWindowData(sFileName.s, iIncludeUserData=#True)
; +-----------------------------------------------------------------
; |Description : Loads the geometry and data strings of all windows from an INI file and updates the window structures in WinHandler
; |Arguments : sFileName : Path and file name of the INI file
; | : iIncludeUserData: Determines whether the data strings should also be read
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
whAddGadget(sWindowName.s, sGadgetName.s, iGadgetNumber.i, iAnchor.i=#Anchor_Left, *Eventprocedure=0, iEventType.i=#PB_All)
; +-----------------------------------------------------------------
; |Description : Adds a (previously created) PureBasic gadget to a window registered in WinHandler
; |Arguments : sWindowName : Name under which the window was registered
; | : sGadgetName : Name under which the gadget is to be addressed
; | : iGadgetNumber : Object number of the PureBasic gadget
; | : iAnchor : With bitwise OR (|) linked values of anchor constants for this gadget (see gadget anchor constants)
; | : *Eventprocedure: Address of a (standard) event procedure to be linked to the gadget.
; | : iEventType : EventType for the specified event procedure
; |Results : Returns the PB object number of the added gadget or 0 in case of errors
; |Remarks : Besides the possibility to assign a (standard) event procedure to the gadget "on the fly" with this command,
; | you can link further events to the gadget via the normal PureBasic commands. But then you have to release
; | them yourself!
; +-----------------------------------------------------------------
whFreeGadget(sWindowName.s, sGadgetName.s)
; +-----------------------------------------------------------------
; |Description : Frees a gadget previously registered with whAddGadget() and removes it from the window
; |Arguments : sWindowName: Name under which the window was registered
; | : sGadgetName: Name under which the gadget was registered
; |Results : -
; |Remarks : This function also detaches a (standard) event from the gadget that may have been previously assigned by whAddGadget()
; +-----------------------------------------------------------------
whGetGadgetNumber(sWindowName.s, sGadgetName.s)
; +-----------------------------------------------------------------
; |Description : Returns the PB object number of a gadget registered in WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; | : sGadgetName: Name under which the gadget was registered
; |Results : Returns the PB object number of the gadget or 0 in case of errors
; |Remarks : -
; +-----------------------------------------------------------------
Code: Select all
;*************************************************************************
;* WinHandler (c) Kurzer - Markus Haacke
;*************************************************************************
;*
;* Modulname : WinHandler
;* Filename : mod_WinHandler.pbi
;* Filetype : Module [MainApp, Formular, Include, Module, Data]
;* Programming lang. : Purebasic 5.60+
;* String-Format : Unicode [Ascii, Unicode, All]
;* Platform : Windows [Windows, Mac, Linux, All]
;* Processor : All [x86, x64, All]
;* Compileroptions : -
;* Version : 1.00
;* Date : 30.08.2023
;* Autor : Markus Haacke
;* Dependencies : -
;* -----------------------------------------------------------------------
;* Description (english):
;*
;* The WinHandler module provides functions to automate the alignment of
;* gadgets within window applications and to save and reload program variables
;* and window geometries in/from an INI file.
;*
;* If you don't get along with the PureBasic dialog library and prefer to
;* create window interfaces in the "usual" way, WinHandler takes a bit of
;* work off your hands.
;*
;* Automatic alignment:
;* PureBasic gadgets can be anchored to one or more sides of the window with
;* so-called "anchors" when they are created. When the window is resized, the
;* gadgets are automatically repositioned or resized according to their anchor
;* points.
;*
;* Saving window geometry and variables:
;* Furthermore, the module offers functions to save the position and size of
;* all windows of an application in an INI file and to reload them next start.
;* In addition, windows managed by the WinHandler can have any amount of data
;* stored for management (currently only strings). These data are also auto-
;* matically stored in the INI file.
;*
;* By these functions the management (save/load) of all settings of an
;* application can be realized by the WinHandler.
;*
;* Description (deutsch):
;*
;* Das Modul WinHandler stellt Funktionen bereit, um die Ausrichtung von
;* Gadgets innerhalb von Fensteranwendungen zu automatisieren sowie
;* Programmvariablen und Fenstergeometrien in einer INI Datei zu speichern
;* und wieder zu laden.
;*
;* Wer mit der PureBasic Dialog-Library nicht zurecht kommt und Fenster-
;* oberflächen lieber auf "gewohnte" Weise erstellt, dem nimmt WinHandler
;* ein bisschen Arbeit ab.
;*
;* Automatische Ausrichtung:
;* PureBasic Gadgets können bei der Erstellung mit sogenannten "Ankern" an
;* einer oder mehreren Seiten des Fensters verankert werden. Bei einer Größen-
;* änderung des Fensters werden die Gadgets automatisch entsprechend ihrer
;* Ankerpunkte neu positioniert bzw. in der Größe angepasst.
;*
;* Speichern von Fenstergeometrie und Variablen:
;* Weiterhin bietet das Modul Funktionen an, um die Position und Größe aller
;* Fenster einer Anwendung in einer INI Datei zu speichern und wieder zu laden.
;* Darüber hinaus können an Fenstern, die durch den WinHandler gemanagt werden,
;* beliebig viele Daten zur Verwaltung hinterlegt werden (derzeit nur Strings).
;* Diese Daten werden ebenfalls automatisch in der INI-Datei gespeichert.
;*
;* Durch diese Funktionen kann die Verwaltung (Speichern/Laden) sämtlicher
;* Einstellungen einer Anwendung durch den WinHandler realisiert werden.
;*
;* -----------------------------------------------------------------------
;* License: MIT License
;*
;* Copyright (c) 2023 Kurzer - Markus Haacke
;*
;* Permission is hereby granted, free of charge, to any person obtaining a copy
;* of this software and associated documentation files (the "Software"), to deal
;* in the Software without restriction, including without limitation the rights
;* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
;* copies of the Software, and to permit persons to whom the Software is
;* furnished to do so, subject to the following conditions:
;*
;* The above copyright notice and this permission notice shall be included in all
;* copies or substantial portions of the Software.
;*
;* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;* SOFTWARE.
;*
;* ---------------- German translation of the MIT License ----------------
;*
;* MIT Lizenz:
;*
;* Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der
;* zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt,
;* sie uneingeschränkt zu nutzen, inklusive und ohne Ausnahme mit dem Recht, sie
;* zu verwenden, zu kopieren, zu verändern, zusammenzufügen, zu veröffentlichen,
;* zu verbreiten, zu unterlizenzieren und/oder zu verkaufen, und Personen, denen
;* diese Software überlassen wird, diese Rechte zu verschaffen, unter den folgenden
;* Bedingungen:
;*
;* Der obige Urheberrechtsvermerk und dieser Erlaubnisvermerk sind in allen Kopien
;* oder Teilkopien der Software beizulegen.
;*
;* DIE SOFTWARE WIRD OHNE JEDE AUSDRÜCKLICHE ODER IMPLIZIERTE GARANTIE BEREITGESTELLT,
;* EINSCHLIEßLICH DER GARANTIE ZUR BENUTZUNG FÜR DEN VORGESEHENEN ODER EINEM BESTIMMTEN
;* ZWECK SOWIE JEGLICHER RECHTSVERLETZUNG, JEDOCH NICHT DARAUF BESCHRÄNKT. IN KEINEM
;* FALL SIND DIE AUTOREN ODER COPYRIGHTINHABER FÜR JEGLICHEN SCHADEN ODER SONSTIGE
;* ANSPRÜCHE HAFTBAR ZU MACHEN, OB INFOLGE DER ERFÜLLUNG EINES VERTRAGES, EINES DELIKTES
;* ODER ANDERS IM ZUSAMMENHANG MIT DER SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE
;* ENTSTANDEN.
;* -----------------------------------------------------------------------
;* Changelog:
;* 1.00 - rel 30.08.2023:
;* First release
;*************************************************************************
;- --- [WinHandler Modul] -----------------------------------------------------
;-
DeclareModule WH
;- --- [Module declaration / public elements] ------------------------------------------
;-
;*************************************************************************
;- Macros
;*************************************************************************
;*************************************************************************
;- Constants
;*************************************************************************
; Gadget-Anchor-Modes
#Anchor_Left = %000001
#Anchor_Top = %000010
#Anchor_Right = %000100
#Anchor_Bottom = %001000
#Anchor_CenterHor = %010000
#Anchor_CenterVer = %100000
; Gadget-Spacing-Constants
Enumeration
#Spacing_Left
#Spacing_Top
#Spacing_Right
#Spacing_Bottom
EndEnumeration
;*************************************************************************
;- Structures
;*************************************************************************
Structure Gadgets ; Mapkey is the name of the gadget, e.g. "OkButton" or "OpenFile"
iNumber.i ; Gadegtnumber
iAnchor.i ; Anchor points
iSpacing.i[4] ; Initial distances of the gadgets from the window border (left, top, right, bottom)
*Eventprocedure
iEventType.i
EndStructure
Structure Windows ; Mapkey is the name of the window, e.g. "Main" or "Settings"
iNumber.i ; The PureBasic window number
iState.i ; Window state (see #WinState_XYZ constants)
iSaveGeometry.i ; Indicates if the window dimensions are saved in the prefsfile (#True/#False)
iSaveUserData.i ; Specifies whether the window user data will be saved in the prefsfile (#True/#False)
iPosX.i ; Window dimensions at runtime
iPosY.i
iWidth.i
iHeight.i
iOrgWidth.i ; Window dimensions at design time (when first opened)
iOrgHeight.i ; Needed to perform resizing of gadgets correctly
Map mpGadgets.Gadgets()
Map mpUserData.s() ; Contains the user data stored at the window and saved to the prefs file
EndStructure
;*************************************************************************
;- Variables, Arrays, Linked Lists, Maps
;*************************************************************************
Global NewMap mpWindows.Windows(30) ; Management list for windows and associated gadgets
;*************************************************************************
;- Interfaces, Prototypes
;*************************************************************************
;*************************************************************************
;- Public procedures (dec)
;*************************************************************************
Declare.i whAddWindow(sWindowName.s, iSaveGeometry.i=#True, iSaveUserData.i=#True)
Declare.i whRemoveWindow(sWindowName.s)
Declare.i whOpenWindow(sWindowName.s, ix.i=#PB_Ignore, iy.i=#PB_Ignore, iWidth.i=600, iHeight.i=800, sTitel.s="", iFlags.i=-2, iParentWindow=-2)
Declare.i whCloseWindow(sWindowName.s)
Declare.i whGetWindowNumber(sWindowName.s)
Declare.i whSetWindowData(sWindowName.s, sDataKey.s, sData.s)
Declare.s whGetWindowData(sWindowName.s, sDataKey.s)
Declare.i whRemoveWindowData(sWindowName.s, sDataKey.s="")
Declare.i whSaveWindowData(sFileName.s, iIncludeUserData=#True, iDeleteOldFile=#False)
Declare.i whLoadWindowData(sFileName.s, iIncludeUserData=#True)
Declare.i whAddGadget(sWindowName.s, sGadgetName.s, iGadgetNumber.i, iAnchor.i=#Anchor_Left, *Eventprocedure=0, iEventType.i=#PB_All)
Declare.i whFreeGadget(sWindowName.s, sGadgetName.s)
Declare.i whGetGadgetNumber(sWindowName.s, sGadgetName.s)
EndDeclareModule
Module WH
;-
;- --- [Module implementation / private elements] -----------------------------------------
;-
;*************************************************************************
;- Private procedures (imp)
;*************************************************************************
Procedure whResizeGadget()
; +-----------------------------------------------------------------
; |Description : Recalculation of gadget sizes and positions
; |Arguments : -
; |Results : -
; |Remarks : -
; +-----------------------------------------------------------------
With mpWindows()
If \mpGadgets()\iAnchor & (#Anchor_Left | #Anchor_Right) = #Anchor_Left | #Anchor_Right
ResizeGadget(\mpGadgets()\iNumber, #PB_Ignore, #PB_Ignore, \iWidth - \mpGadgets()\iSpacing[#Spacing_Left] - \mpGadgets()\iSpacing[#Spacing_Right], #PB_Ignore)
ElseIf \mpGadgets()\iAnchor & #Anchor_Right
ResizeGadget(\mpGadgets()\iNumber, \iWidth - \mpGadgets()\iSpacing[#Spacing_Right] - GadgetWidth(\mpGadgets()\iNumber), #PB_Ignore, #PB_Ignore, #PB_Ignore)
EndIf
If \mpGadgets()\iAnchor & (#Anchor_Top | #Anchor_Bottom) = #Anchor_Top | #Anchor_Bottom
ResizeGadget(\mpGadgets()\iNumber, #PB_Ignore, #PB_Ignore, #PB_Ignore, \iHeight - \mpGadgets()\iSpacing[#Spacing_Top] - \mpGadgets()\iSpacing[#Spacing_Bottom])
ElseIf \mpGadgets()\iAnchor & #Anchor_Bottom
ResizeGadget(\mpGadgets()\iNumber, #PB_Ignore, \iHeight - \mpGadgets()\iSpacing[#Spacing_Bottom] - GadgetHeight(\mpGadgets()\iNumber), #PB_Ignore, #PB_Ignore)
EndIf
If \mpGadgets()\iAnchor & #Anchor_CenterHor = #Anchor_CenterHor
ResizeGadget(\mpGadgets()\iNumber, (\iWidth - GadgetWidth(\mpGadgets()\iNumber)) / 2, #PB_Ignore, #PB_Ignore, #PB_Ignore)
EndIf
If \mpGadgets()\iAnchor & #Anchor_CenterVer = #Anchor_CenterVer
ResizeGadget(\mpGadgets()\iNumber, #PB_Ignore, (\iHeight - GadgetHeight(\mpGadgets()\iNumber)) / 2, #PB_Ignore, #PB_Ignore)
EndIf
EndWith
EndProcedure
Procedure whWinHandler()
; +-----------------------------------------------------------------
; |Description : Processing of window events #PB_Event_SizeWindow and #PB_Event_MoveWindow
; |Arguments : -
; |Results : -
; |Remarks : -
; +-----------------------------------------------------------------
Protected.i iWindow, iEvent
Static iLastWindow.i, sLastWindow.s
With mpWindows()
; Determine the relevant window from the map
; If it is the same window as in the last event, the map does not need to be searched again.
iWindow = EventWindow()
If iLastWindow = iWindow
FindMapElement(mpWindows(), sLastWindow)
Else
ResetMap(mpWindows())
While NextMapElement(mpWindows())
If \iNumber = iWindow
iLastWindow = iWindow
sLastWindow = MapKey(mpWindows())
Break
EndIf
Wend
EndIf
If \iNumber = iWindow
iEvent = Event()
If iEvent = #PB_Event_SizeWindow
; Store new window position and size
\iPosX = WindowX(\iNumber)
\iPosY = WindowY(\iNumber)
\iWidth = WindowWidth(\iNumber)
\iHeight = WindowHeight(\iNumber)
; Calculate new gadget positions and sizes according to #Gadget_Anchor constants
ResetMap(\mpGadgets())
While NextMapElement(\mpGadgets())
If \mpGadgets()\iNumber > 0
whResizeGadget()
EndIf
Wend
ElseIf iEvent = #PB_Event_MoveWindow
; Store new window position
\iPosX = WindowX(\iNumber)
\iPosY = WindowY(\iNumber)
EndIf
EndIf
EndWith
EndProcedure
;*************************************************************************
;- Public procedures (imp)
;*************************************************************************
Procedure.i whAddWindow(sWindowName.s, iSaveGeometry.i=#True, iSaveUserData.i=#True)
; +-----------------------------------------------------------------
; |Description : Registers a new window with its name in the WinHandler and sets the flags iSaveGeometry and iSaveUserData
; |Arguments : sWindowName : Name under which the window is to be addressed
; | : iSaveGeometry: Defines whether this window should be taken into account when saving the window geometries to the INI file
; | : iSaveUserData: Determines whether the attached user data of this window should be taken into account when saving to the INI file
; |Results : #True/#False
; |Remarks : If whAddWindow() is not called by the programmer, then this is automatically made up for by whOpenWindow()
; +-----------------------------------------------------------------
If sWindowName = ""
ProcedureReturn #False
EndIf
sWindowName = LCase(sWindowName)
mpWindows(sWindowName)\iSaveGeometry = iSaveGeometry
mpWindows(sWindowName)\iSaveUserData = iSaveUserData
ProcedureReturn #True
EndProcedure
Procedure.i whRemoveWindow(sWindowName.s)
; +-----------------------------------------------------------------
; |Description : Removes a window previously registered by whAddWindow() from WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
If sWindowName = ""
ProcedureReturn #False
EndIf
sWindowName = LCase(sWindowName)
; Does the entry exist at all?
If FindMapElement(mpWindows(), sWindowName) = 0
ProcedureReturn #False
EndIf
; Is the associated window still open? Then we close it.
If IsWindow(mpWindows(sWindowName)\iNumber) <> 0
whCloseWindow(sWindowName)
EndIf
DeleteMapElement(mpWindows(), sWindowName)
ProcedureReturn #True
EndProcedure
;-
Procedure.i whOpenWindow(sWindowName.s, ix.i=#PB_Ignore, iy.i=#PB_Ignore, iWidth.i=600, iHeight.i=800, sTitel.s="", iFlags.i=-2, iParentWindow=-2)
; +-----------------------------------------------------------------
; |Description : Opens a PureBasic window (same parameter sequence, except window name)
; | : and registers the events #PB_Event_SizeWindow and #PB_Event_MoveWindow in the WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; | : For all other parameters see OpenWindow() in the PureBasic help file
; |Results : Returns the PB object number of the opened window or 0 in case of errors
; |Remarks : -
; +-----------------------------------------------------------------
If sWindowName = ""
ProcedureReturn 0
EndIf
sWindowName = LCase(sWindowName)
; If the window entry does not exist yet (whAddWindow() has not been called yet), then we will make up for it.
If FindMapElement(mpWindows(), sWindowName) = 0
If whAddWindow(sWindowName) = #False
ProcedureReturn 0
EndIf
EndIf
If FindMapElement(mpWindows(), sWindowName) <> 0
If IsWindow(mpWindows()\iNumber) = 0
If mpWindows()\iWidth = 0 Or mpWindows()\iHeight = 0 Or mpWindows()\iOrgWidth = 0 Or mpWindows()\iOrgHeight = 0
mpWindows()\iPosX = ix
mpWindows()\iPosY = iy
mpWindows()\iWidth = iWidth
mpWindows()\iHeight = iHeight
mpWindows()\iOrgWidth = iWidth
mpWindows()\iOrgHeight = iHeight
EndIf
If iFlags = -2 And iParentWindow = -2
mpWindows()\iNumber = OpenWindow(#PB_Any, mpWindows()\iPosX, mpWindows()\iPosY, mpWindows()\iWidth, mpWindows()\iHeight, sTitel)
ElseIf iFlags <> -2 And iParentWindow = -2
mpWindows()\iNumber = OpenWindow(#PB_Any, mpWindows()\iPosX, mpWindows()\iPosY, mpWindows()\iWidth, mpWindows()\iHeight, sTitel , iFlags)
ElseIf iFlags <> -2 And iParentWindow <> -2
mpWindows()\iNumber = OpenWindow(#PB_Any, mpWindows()\iPosX, mpWindows()\iPosY, mpWindows()\iWidth, mpWindows()\iHeight, sTitel, iFlags , iParentWindow)
EndIf
If mpWindows()\iNumber <> 0
; Connecting window events with the
BindEvent(#PB_Event_SizeWindow, @whWinHandler(), mpWindows()\iNumber)
BindEvent(#PB_Event_MoveWindow, @whWinHandler(), mpWindows()\iNumber)
ProcedureReturn mpWindows()\iNumber
EndIf
; If the window is currently open (whOpenWindow() was called multiple times), only the window number is returned.
ElseIf IsWindow(mpWindows()\iNumber) <> 0
ProcedureReturn mpWindows()\iNumber
Else
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure.i whCloseWindow(sWindowName.s)
; +-----------------------------------------------------------------
; |Description : Closes a window managed by WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
If sWindowName = ""
ProcedureReturn #False
EndIf
sWindowName = LCase(sWindowName)
; If the window entry does not exist (whAddWindow() or whOpenWindow() have not been called yet).
If FindMapElement(mpWindows(), sWindowName) = 0
ProcedureReturn #True
Else
With mpWindows(sWindowName)
; When the window is actually open
If IsWindow(\iNumber) <> 0
; Detach window events from WinHandler
UnbindEvent(#PB_Event_MoveWindow, @whWinHandler(), \iNumber)
UnbindEvent(#PB_Event_SizeWindow, @whWinHandler(), \iNumber)
; Release all gadgets of the window
ResetMap(\mpGadgets())
While NextMapElement(\mpGadgets()) <> 0
whFreeGadget(sWindowName, MapKey(\mpGadgets()))
ResetMap(\mpGadgets())
Wend
CloseWindow(mpWindows()\iNumber)
EndIf
ClearMap(\mpGadgets())
EndWith
ProcedureReturn #True
EndIf
EndProcedure
Procedure.i whGetWindowNumber(sWindowName.s)
; +-----------------------------------------------------------------
; |Description : Returns the PB object number of a window registered in WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; |Results : Returns the PB object number of the window or 0 in case of errors
; |Remarks : -
; +-----------------------------------------------------------------
If sWindowName = ""
ProcedureReturn 0
EndIf
sWindowName = LCase(sWindowName)
; If the window entry does not exist (whAddWindow() or whOpenWindow() have not been called yet)
If FindMapElement(mpWindows(), sWindowName) = 0
ProcedureReturn 0
EndIf
; If the window is closed
If IsWindow(mpWindows()\iNumber) = 0
ProcedureReturn 0
Else
ProcedureReturn mpWindows()\iNumber
EndIf
EndProcedure
;-
Procedure.i whSetWindowData(sWindowName.s, sDataKey.s, sData.s)
; +-----------------------------------------------------------------
; |Description : Stores a user-defined string at the window
; |Arguments : sWindowName: Name of the window where the data string is to be stored
; | : sDataKey : Name under which the data string is to be identified
; | : sData : The data string
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
If sWindowName = "" Or sDataKey = ""
ProcedureReturn #False
EndIf
sWindowName = LCase(sWindowName)
sDataKey = LCase(sDataKey)
; If the window entry does not exist (whAddWindow() or whOpenWindow() have not been called yet)
If FindMapElement(mpWindows(), sWindowName) = 0
ProcedureReturn #False
EndIf
mpWindows(sWindowName)\mpUserData(sDataKey) = sData
ProcedureReturn #True
EndProcedure
Procedure.s whGetWindowData(sWindowName.s, sDataKey.s)
; +-----------------------------------------------------------------
; |Description : Returns the value of a user-defined string previously stored at a window
; |Arguments : sWindowName: Name of the window with which the data string is associated
; | : sDataKey : Name of the data string
; |Results : The user-defined string or an empty string, in case of errors
; |Remarks : -
; +-----------------------------------------------------------------
If sWindowName = "" Or sDataKey = ""
ProcedureReturn ""
EndIf
sWindowName = LCase(sWindowName)
sDataKey = LCase(sDataKey)
; If the window entry does not exist (whAddWindow() or whOpenWindow() have not been called yet)
If FindMapElement(mpWindows(), sWindowName) = 0
ProcedureReturn ""
EndIf
ProcedureReturn mpWindows(sWindowName)\mpUserData(sDataKey)
EndProcedure
Procedure.i whRemoveWindowData(sWindowName.s, sDataKey.s="")
; +-----------------------------------------------------------------
; |Description : Removes a user-defined string previously stored at a window
; |Arguments : sWindowName: Name of the window with which the data string is associated
; | : sDataKey : Name of the data string
; |Results : #True/#False
; |Remarks : If sDataKey="", then all data strings associated with this window will be removed
; +-----------------------------------------------------------------
If sWindowName = ""
ProcedureReturn #False
EndIf
sWindowName = LCase(sWindowName)
sDataKey = LCase(sDataKey)
; If the window entry does not exist (whAddWindow() or whOpenWindow() have not been called yet)
If FindMapElement(mpWindows(), sWindowName) = 0
ProcedureReturn #False
EndIf
If sDataKey = ""
ClearMap(mpWindows(sWindowName)\mpUserData())
Else
DeleteMapElement(mpWindows(sWindowName)\mpUserData(), sDataKey)
EndIf
ProcedureReturn #True
EndProcedure
Procedure.i whSaveWindowData(sFileName.s, iIncludeUserData=#True, iDeleteOldFile=#False)
; +-----------------------------------------------------------------
; |Description : Saves the geometry and the data strings of all windows to an INI file
; |Arguments : sFileName : Path and filename of the INI file
; | : iIncludeUserData: Determines whether the data strings should also be saved
; | : This overrides the iSaveGeometry option on whAddWindow(), even if iSaveGeometry = #true
; | : for some windows. If iIncludeUserData = #False, then no data strings are saved at all,
; | : only the window geometries are saved
; | : iDeleteOldFile: If #True, then the file will be completely rebuilt instead of updating it
; | : (thus removing old data strings as well. Useful if they are no longer used in the program)
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
; If the prefs file does not exist, we create it
If OpenPreferences(sFileName) = 0 Or iDeleteOldFile = #True
CreatePreferences(sFileName)
EndIf
If OpenPreferences(sFileName, #PB_Preference_GroupSeparator) = 0
ProcedureReturn #False
EndIf
With mpWindows()
ResetMap(mpWindows())
While NextMapElement(mpWindows())
If \iSaveGeometry = #True Or \iSaveUserData = #True
PreferenceGroup("Window_" + MapKey(mpWindows()))
EndIf
If \iSaveGeometry = #True
; Fenstergeometrie speichern
WritePreferenceInteger("PosX", \iPosX)
WritePreferenceInteger("PosY", \iPosY)
WritePreferenceInteger("Width", \iWidth)
WritePreferenceInteger("Height", \iHeight)
WritePreferenceInteger("OrgWidth", \iOrgWidth)
WritePreferenceInteger("OrgHeight", \iOrgHeight)
EndIf
If \iSaveUserData = #True And iIncludeUserData = #True
; UserDaten speichern
ResetMap(\mpUserData())
While NextMapElement(\mpUserData())
WritePreferenceString(MapKey(\mpUserData()), \mpUserData())
Wend
EndIf
Wend
EndWith
ClosePreferences()
ProcedureReturn #True
EndProcedure
Procedure.i whLoadWindowData(sFileName.s, iIncludeUserData=#True)
; +-----------------------------------------------------------------
; |Description : Loads the geometry and data strings of all windows from an INI file and updates the window structures in WinHandler
; |Arguments : sFileName : Path and file name of the INI file
; | : iIncludeUserData: Determines whether the data strings should also be read
; |Results : #True/#False
; |Remarks : -
; +-----------------------------------------------------------------
If OpenPreferences(sFileName) = 0
ProcedureReturn #False
EndIf
With mpWindows()
ResetMap(mpWindows())
While NextMapElement(mpWindows())
If PreferenceGroup("Window_" + MapKey(mpWindows())) <> 0
ExaminePreferenceKeys()
While NextPreferenceKey()
Select PreferenceKeyName()
Case "PosX" : \iPosX = Val(PreferenceKeyValue())
Case "PosY" : \iPosY = Val(PreferenceKeyValue())
Case "Width" : \iWidth = Val(PreferenceKeyValue())
Case "Height" : \iHeight = Val(PreferenceKeyValue())
Case "OrgWidth" : \iOrgWidth = Val(PreferenceKeyValue())
Case "OrgHeight" : \iOrgHeight = Val(PreferenceKeyValue())
Default
If iIncludeUserData = #True
\mpUserData(LCase(PreferenceKeyName())) = PreferenceKeyValue()
EndIf
EndSelect
Wend
EndIf
Wend
EndWith
ClosePreferences()
ProcedureReturn #True
EndProcedure
;-
Procedure.i whAddGadget(sWindowName.s, sGadgetName.s, iGadgetNumber.i, iAnchor.i=#Anchor_Left, *Eventprocedure=0, iEventType.i=#PB_All)
; +-----------------------------------------------------------------
; |Description : Adds a (previously created) PureBasic gadget to a window registered in WinHandler
; |Arguments : sWindowName : Name under which the window was registered
; | : sGadgetName : Name under which the gadget is to be addressed
; | : iGadgetNumber : Object number of the PureBasic gadget
; | : iAnchor : With bitwise OR (|) linked values of anchor constants for this gadget (see gadget anchor constants)
; | : *Eventprocedure: Address of a (standard) event procedure to be linked to the gadget.
; | : iEventType : EventType for the specified event procedure
; |Results : Returns the PB object number of the added gadget or 0 in case of errors
; |Remarks : Besides the possibility to assign a (standard) event procedure to the gadget "on the fly" with this command,
; | you can link further events to the gadget via the normal PureBasic commands. But then you have to release
; | them yourself!
; +-----------------------------------------------------------------
If sWindowName = "" Or sGadgetName = "" Or iGadgetNumber < 0
ProcedureReturn 0
EndIf
sWindowName = LCase(sWindowName)
sGadgetName = LCase(sGadgetName)
; If the window entry does not exist (whAddWindow() or whOpenWindow() have not been called yet)
If FindMapElement(mpWindows(), sWindowName) = 0
ProcedureReturn 0
EndIf
; If the window is closed
If IsWindow(mpWindows()\iNumber) = 0
ProcedureReturn 0
EndIf
; If the gadget entry already exists
If FindMapElement(mpWindows(sWindowName)\mpGadgets(), sGadgetName) <> 0
ProcedureReturn mpWindows(sWindowName)\mpGadgets(sGadgetName)\iNumber
Else
With mpWindows(sWindowName)
\mpGadgets(sGadgetName)\iNumber = iGadgetNumber
\mpGadgets(sGadgetName)\iAnchor = iAnchor
\mpGadgets(sGadgetName)\iSpacing[#Spacing_Left] = GadgetX(iGadgetNumber)
\mpGadgets(sGadgetName)\iSpacing[#Spacing_Top] = GadgetY(iGadgetNumber)
\mpGadgets(sGadgetName)\iSpacing[#Spacing_Right] = \iOrgWidth - GadgetX(iGadgetNumber) - GadgetWidth(iGadgetNumber)
\mpGadgets(sGadgetName)\iSpacing[#Spacing_Bottom] = \iOrgHeight - GadgetY(iGadgetNumber) - GadgetHeight(iGadgetNumber)
If *Eventprocedure <> 0
\mpGadgets(sGadgetName)\Eventprocedure = *Eventprocedure
\mpGadgets(sGadgetName)\iEventType = iEventType
BindGadgetEvent(iGadgetNumber, *Eventprocedure, iEventType)
Else
\mpGadgets(sGadgetName)\Eventprocedure = 0
\mpGadgets(sGadgetName)\iEventType = #PB_All
EndIf
ProcedureReturn mpWindows(sWindowName)\mpGadgets()\iNumber
EndWith
EndIf
EndProcedure
Procedure.i whFreeGadget(sWindowName.s, sGadgetName.s)
; +-----------------------------------------------------------------
; |Description : Frees a gadget previously registered with whAddGadget() and removes it from the window
; |Arguments : sWindowName: Name under which the window was registered
; | : sGadgetName: Name under which the gadget was registered
; |Results : -
; |Remarks : This function also detaches a (standard) event from the gadget that may have been previously assigned by whAddGadget()
; +-----------------------------------------------------------------
If sWindowName = "" Or sGadgetName = ""
ProcedureReturn #False
EndIf
; If the window entry does not exist (whAddWindow() or whOpenWindow() have not been called yet)
If FindMapElement(mpWindows(), sWindowName) = 0
ProcedureReturn #False
EndIf
; If the window is closed
If IsWindow(mpWindows(sWindowName)\iNumber) = 0
ProcedureReturn #False
EndIf
; If the gadget entry does not exist
If FindMapElement(mpWindows(sWindowName)\mpGadgets(), sGadgetName) = 0
ProcedureReturn #False
Else
With mpWindows(sWindowName)
If \mpGadgets(sGadgetName)\Eventprocedure <> 0
UnbindGadgetEvent(\mpGadgets(sGadgetName)\iNumber, \mpGadgets(sGadgetName)\Eventprocedure)
EndIf
If IsGadget(\mpGadgets(sGadgetName)\iNumber) <> 0
FreeGadget(\mpGadgets(sGadgetName)\iNumber)
EndIf
DeleteMapElement(\mpGadgets(), sGadgetName)
ProcedureReturn #True
EndWith
EndIf
EndProcedure
Procedure.i whGetGadgetNumber(sWindowName.s, sGadgetName.s)
; +-----------------------------------------------------------------
; |Description : Returns the PB object number of a gadget registered in WinHandler
; |Arguments : sWindowName: Name under which the window was registered
; | : sGadgetName: Name under which the gadget was registered
; |Results : Returns the PB object number of the gadget or 0 in case of errors
; |Remarks : -
; +-----------------------------------------------------------------
If sWindowName = "" Or sGadgetName = ""
ProcedureReturn 0
EndIf
sWindowName = LCase(sWindowName)
sGadgetName = LCase(sGadgetName)
; If the window entry does not exist (whAddWindow() or whOpenWindow() have not been called yet)
If FindMapElement(mpWindows(), sWindowName) = 0
ProcedureReturn 0
EndIf
; If the window is closed
If IsWindow(mpWindows(sWindowName)\iNumber) = 0
ProcedureReturn 0
Else
ProcedureReturn mpWindows(sWindowName)\mpGadgets(sGadgetName)\iNumber
EndIf
EndProcedure
EndModule
CompilerIf #PB_Compiler_IsMainFile = 1
;-
;*************************************************************************
;- Democode
;*************************************************************************
EnableExplicit
Global iQuit.i, sIniFile.s
sIniFile = GetPathPart(ProgramFilename()) + "WinHandler.ini"
Procedure.i Settings_CloseWindow()
UseModule WH
If IsWindow(whGetWindowNumber("settings")) <> 0
; The registered gadgets and their (standard) events are automatically released when the window is closed
whCloseWindow("settings")
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
UnuseModule WH
EndProcedure
Procedure Settings_Event_Button_Clear()
UseModule WH
SetGadgetText(whGetGadgetNumber("settings", "string"), "")
UnuseModule WH
EndProcedure
Procedure Settings_Event_Button_Save()
UseModule WH
whSetWindowData("settings", "text", GetGadgetText(whGetGadgetNumber("settings", "string")))
whSaveWindowData(sIniFile, #True, #False)
Settings_CloseWindow()
UnuseModule WH
EndProcedure
Procedure Settings_Event_CloseWindow()
Settings_CloseWindow()
EndProcedure
Procedure.i Settings_OpenWindow()
UseModule WH
If IsWindow(whGetWindowNumber("settings")) = 0
; Open the settings window
If whOpenWindow("settings", #PB_Ignore, #PB_Ignore, 400, 240, "WinHandler-Demo [settings]", #PB_Window_SystemMenu|#PB_Window_TitleBar|#PB_Window_SizeGadget|#PB_Window_Invisible) <> 0
; Open the main window
whAddGadget("settings", "frame", FrameGadget(#PB_Any, 5, 5, 390, 185, "Program settings"), #Anchor_Left | #Anchor_Top | #Anchor_Right | #Anchor_Bottom)
whAddGadget("settings", "text", TextGadget(#PB_Any, 15, 30, 260, 20, "Enter some text into the string gadget:"), #Anchor_Left | #Anchor_Top)
whAddGadget("settings", "string", StringGadget(#PB_Any, 15, 50, 370, 25, ""), #Anchor_Left | #Anchor_Top | #Anchor_Right)
whAddGadget("settings", "text ini", TextGadget(#PB_Any, 15, 90, 200, 20, "The INI file is located at:"), #Anchor_Left | #Anchor_Bottom)
whAddGadget("settings", "editor ini", EditorGadget(#PB_Any, 15, 110, 370, 70, #PB_Editor_WordWrap | #PB_Editor_ReadOnly), #Anchor_Left | #Anchor_Right | #Anchor_Bottom)
whAddGadget("settings", "button save", ButtonGadget(#PB_Any, 5, 200, 90, 35, "Save to INI", #PB_Button_Default), #Anchor_Left | #Anchor_Bottom, @Settings_Event_Button_Save(), #PB_EventType_LeftClick)
whAddGadget("settings", "button clear", ButtonGadget(#PB_Any, 150, 200, 90, 35, "Clear text", #PB_Button_Default), #Anchor_CenterHor | #Anchor_Bottom, @Settings_Event_Button_Clear(), #PB_EventType_LeftClick)
whAddGadget("settings", "button cancel", ButtonGadget(#PB_Any, 305, 200, 90, 35, "Cancel"), #Anchor_Right | #Anchor_Bottom, @Settings_Event_CloseWindow(), #PB_EventType_LeftClick)
SetGadgetText(whGetGadgetNumber("settings", "string"), whGetWindowData("settings", "text"))
SetGadgetText(whGetGadgetNumber("settings", "editor ini"), sIniFile)
SetGadgetColor(whGetGadgetNumber("settings", "editor ini"), #PB_Gadget_BackColor, $C1B7BC)
BindEvent(#PB_Event_CloseWindow, @Settings_Event_CloseWindow(), whGetWindowNumber("settings"))
; Set some window attributes and finally make the window visible
SmartWindowRefresh(whGetWindowNumber("settings"), #True)
WindowBounds(whGetWindowNumber("settings"), 300, 260, 1200, 800)
HideWindow(whGetWindowNumber("settings"), #False)
ProcedureReturn #True
EndIf
Else
ProcedureReturn #False
EndIf
UnuseModule WH
EndProcedure
Procedure Main_Event_Button_Exit()
iQuit = #True
EndProcedure
Procedure Main_Event_Button_Settings()
Settings_OpenWindow()
EndProcedure
Procedure.i Main_OpenWindow()
UseModule WH
If IsWindow(whGetWindowNumber("main")) = 0
; Open the main window
If whOpenWindow("main", #PB_Ignore, #PB_Ignore, 500, 500, "WinHandler-Demo [main]", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_Invisible) <> 0
; Add some gadgets to the window
whAddGadget("main", "button nothing", ButtonGadget(#PB_Any, 5, 10, 170, 35, "Do nothing"), #Anchor_Left | #Anchor_Top)
whAddGadget("main", "button settings", ButtonGadget(#PB_Any, 360, 10, 135, 35, "Settings"), #Anchor_Top | #Anchor_Right, @Main_Event_Button_Settings(), #PB_EventType_LeftClick)
whAddGadget("main", "container", ContainerGadget(#PB_Any, 410, 60, 85, 75), #Anchor_Right | #Anchor_CenterVer)
whAddGadget("main", "button 1", ButtonGadget(#PB_Any, 0, 0, 85, 35, "Button 1"), #Anchor_Left)
whAddGadget("main", "button 2", ButtonGadget(#PB_Any, 0, 40, 85, 35, "Button 2"), #Anchor_Left)
CloseGadgetList()
whAddGadget("main", "editor", EditorGadget(#PB_Any, 5, 60, 395, 380, #PB_Editor_WordWrap), #Anchor_Left | #Anchor_Top | #Anchor_Right | #Anchor_Bottom)
whAddGadget("main", "button exit", ButtonGadget(#PB_Any, 395, 455, 100, 35, "Exit"), #Anchor_CenterHor | #Anchor_Bottom, @Main_Event_Button_Exit(), #PB_EventType_LeftClick)
; Set a text for the editor gadget
SetGadgetText(whGetGadgetNumber("main", "editor"), "When you resize the window, the gadgets will automatically realign according to their anchor points." + #CRLF$ + #CRLF$ +
"Click the 'Settings' button to enter the Settings dialog. There you can enter a user defined string and save this string as well as all window sizes and positions in an INI file." + #CRLF$ + #CRLF$ +
"At the next start of the program all window sizes and positions will be initialized with these saved values. And also the user defined string will be loaded again and displayed in the Settings dialog." + #CRLF$ + #CRLF$ +
"All necessary program steps are done by WinHandler.")
BindEvent(#PB_Event_CloseWindow, @Main_Event_Button_Exit(), whGetWindowNumber("main"))
; Set some window attributes and finally make the window visible
SmartWindowRefresh(whGetWindowNumber("main"), #True)
WindowBounds(whGetWindowNumber("main"), 320, 200, 9999, 9999)
HideWindow(whGetWindowNumber("main"), #False)
ProcedureReturn #True
EndIf
Else
ProcedureReturn #False
EndIf
UnuseModule WH
EndProcedure
Procedure.i Main_CloseWindow()
UseModule WH
If IsWindow(whGetWindowNumber("main")) <> 0
UnbindEvent(#PB_Event_CloseWindow, @Main_Event_Button_Exit(), whGetWindowNumber("main"))
; The registered gadgets and their (standard) events are automatically released when the window is closed
whCloseWindow("main")
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
UnuseModule WH
EndProcedure
;*************************************************************************
;- Mainloop
;*************************************************************************
; Register all windows of the program to WinHandler
wh::whAddWindow("main")
wh::whAddWindow("settings")
wh::whLoadWindowData(sIniFile)
If Main_OpenWindow()
Repeat
WaitWindowEvent()
Until iQuit = #True
EndIf
; Unregister all windows from WinHandler
wh::whRemoveWindow("settings")
wh::whRemoveWindow("main")
End
CompilerEndIf
