WaitWindowEvent() - question (win/lin)

Just starting out? Need help? Post your questions and find answers here.
agb2008
User
User
Posts: 60
Joined: Fri Jan 15, 2016 2:22 pm

WaitWindowEvent() - question (win/lin)

Post by agb2008 »

I've posted message in Linux part of forum regarding issue that I've noticed while porting
(recompiling) my code from Windows to Linux. But while run some additional tests I've noticed
some strange results obtained from WaitWindowEvent() function on Linux platform.
I am using this function (as many other users do) to track different events from my windows.
In a sample application I've got just two windows (one main with button gadget and another
window, that would open when user pressed button). Simple task. But I need to keep focus
(keep second window active) - so that user could get back to main window only after closing
second window. I am using SetActiveWindow function for that purpose and it's working fine on
windows - but got issues with the same on Linux OS: http://www.purebasic.fr/english/viewtop ... 15&t=65519
And what I've noticed - on Windows platform result values obtained from WaitWindowEvent() seems
to be stable, while on Linux I am getting random number values out of that function and very
often got "-1" as returning result. Could anyone advice if that is expected results - because I think
values should be similar to ones on Windows platform... Or am I mistaken ?
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: WaitWindowEvent() - question (win/lin)

Post by nco2k »

different operating systems produce different messages. you should ignore all non #PB_Event_* messages. also take a look at DisableWindow().

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: WaitWindowEvent() - question (win/lin)

Post by infratec »

Without a 'working' code snippet no one can fix it.
Because we can not know what and how you have done it.

Provide a code which produces the fault and I'll try to find a solution.

Bernd
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: WaitWindowEvent() - question (win/lin)

Post by nco2k »

there is nothing to fix. he should only care about messages he actually needs. everything else should be ignored. also using SetActiveWindow() in a loop, is just plain wrong.

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
agb2008
User
User
Posts: 60
Joined: Fri Jan 15, 2016 2:22 pm

Re: WaitWindowEvent() - question (win/lin)

Post by agb2008 »

infratec, nco2k:

I suspect that I might do something wrong :wink: but in general use examples of code found on this forum 8) ...
Anyway, PureVison model (software) used to define GUI (I just like the concept) - so there are three files:

in main one following code used in main loop:

Code: Select all

XIncludeFile "test_Constants.pb"
XIncludeFile "test_Windows.pb"

;- Main Loop
If Window_Form1()

  Define quitForm1=0
  Repeat
    EventID  =WaitWindowEvent()
    MenuID   =EventMenu()
    GadgetID =EventGadget()
    WindowID =EventWindow()

    Select EventID
      Case #PB_Event_CloseWindow
        If WindowID=#Window_Form1
          quitForm1=1
        EndIf


      Case #PB_Event_Gadget
        Select GadgetID
          Case #Gadget_Form1_Button2
            ; Window #2 visible here
            If Window_Form3()
                   Define quitAboutForm=0
                    Repeat
                     ABEventID=WaitWindowEvent()
                      SetActiveWindow(#Window_Form3)
                      Select ABEventID
                    Case #PB_Event_CloseWindow
                        quitAboutForm=1
                    EndSelect
                Until quitAboutForm
              CloseWindow(#Window_Form3)
            EndIf 
        EndSelect

    EndSelect
  Until quitForm1
  CloseWindow(#Window_Form1)
EndIf
End
In test_Windows.pb file I've got definition of windows functions like:

Code: Select all

Procedure.i Window_Form3()
  If OpenWindow(#Window_Form3,2165,271,100,80,"Click outside window !",#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible)
      TextGadget(#Gadget_Form3_Text4,10,30,80,20,"Click outside!",#PB_Text_Center)
      HideWindow(#Window_Form3,0)
    ProcedureReturn WindowID(#Window_Form3)
  EndIf
EndProcedure
Basic idea is to reproduce model of main application where user could open special type of
windows where definition of certain parameters performed: by selecting certain options or
typing in required values. But That window should be active (in focus) - so user should be forced
to finish inputting required parameters and close that window - and only after that he could
go back to main application window...

Right now I am getting following result - on windows platform everything working as expected,
while on Linux, when I try to use the same code I am getting complete hang of GUI... :?
What might be wrong ? Or could anyone suggest better way to get similar result - one that
would work in Windows and Linux environments ?
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: WaitWindowEvent() - question (win/lin)

Post by infratec »

I wrote 'working'.

Your code snippets are not working.
And I have not the time to write and stuff which I can not know because it's missing.
My crystall ball stays dark.

Bernd
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: WaitWindowEvent() - question (win/lin)

Post by nco2k »

nco2k wrote:different operating systems produce different messages. you should ignore all non #PB_Event_* messages. also take a look at DisableWindow().

c ya,
nco2k
nco2k wrote:there is nothing to fix. he should only care about messages he actually needs. everything else should be ignored. also using SetActiveWindow() in a loop, is just plain wrong.

c ya,
nco2k
EDIT:

Code: Select all

EnableExplicit

Enumeration
  #Window_Main = 0
  #Window_About
  #Main_Button = 0
  #About_Text
EndEnumeration

Procedure About()
  Protected WindowEvent
  If OpenWindow(#Window_About, 0, 0, 200, 100, "About...", #PB_Window_SystemMenu | #PB_Window_WindowCentered | #PB_Window_Invisible, WindowID(#Window_Main));<--- THIS
    TextGadget(#About_Text, 10, 10, 100, 25, "Text")
    DisableWindow(#Window_Main, #True);<--- THIS
    HideWindow(#Window_About, #False)
    Repeat
      WindowEvent = WaitWindowEvent()
      If EventWindow() = #Window_About
        Select WindowEvent
          Case #PB_Event_CloseWindow
            Break
        EndSelect
      EndIf
    ForEver
    CloseWindow(#Window_About)
    DisableWindow(#Window_Main, #False);<--- THIS
  EndIf
EndProcedure

Procedure Main()
  Protected WindowEvent
  If OpenWindow(#Window_Main, 0, 0, 300, 200, "Main", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered | #PB_Window_Invisible)
    ButtonGadget(#Main_Button, 10, 10, 150, 25, "Click")
    HideWindow(#Window_Main, #False)
    Repeat
      WindowEvent = WaitWindowEvent()
      If EventWindow() = #Window_Main
        Select WindowEvent
          Case #PB_Event_Gadget
            Select EventGadget()
              Case #Main_Button
                About()
            EndSelect
          Case #PB_Event_CloseWindow
            Break
        EndSelect
      EndIf
    ForEver
    CloseWindow(#Window_Main)
  EndIf
EndProcedure

Main()
c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
User avatar
TI-994A
Addict
Addict
Posts: 2751
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: WaitWindowEvent() - question (win/lin)

Post by TI-994A »

agb2008 wrote:Basic idea is to reproduce model of main application where user could open special type of windows where definition of certain parameters performed: by selecting certain options or typing in required values. But that window should be active (in focus) - so user should be forced to finish inputting required parameters and close that window - and only after that he could go back to main application window...
The double call to the WaitWindowEvent() function in the event loop might be the reason your code is tripping in Linux; can't be sure though.

Nevertheless, this little snippet could be what you're looking for:

Code: Select all

Enumeration
  #MainWindow
  #SettingsButton
EndEnumeration

Define settingsWindow, requiredInfo, doneButton, infoDone, wFlags

Procedure OpenSettingsWindow(parentWindow.i)
  Shared settingsWindow, requiredInfo, doneButton, wFlags
  settingsWindow = OpenWindow(#PB_Any, #PB_Any, #PB_Any, 
                              300, 200, "Settings Window", 
                              wFlags, WindowID(parentWindow))
  requiredInfo = StringGadget(#PB_Any, 100, 80, 100, 30, "")
  doneButton = ButtonGadget(#PB_Any, 100, 130, 100, 30, "DONE")  
  SetActiveGadget(requiredInfo)
EndProcedure

Procedure CloseSettingsWindow(done.i)
  Shared infoDone, settingsWindow
  If infoDone
    infoDone = #False
    CloseWindow(settingsWindow)
  Else
    If done
      MessageRequester("Settings", "Input Required!")
    Else
      If MessageRequester("Settings", "Confirm Abort Settings?", 
                          #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
        CloseWindow(settingsWindow)
      EndIf
    EndIf
  EndIf
EndProcedure

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(#MainWindow, #PB_Any, #PB_Any, 600, 400, "Main Window", wFlags)
ButtonGadget(#SettingsButton, 100, 330, 400, 50, "SETTINGS")

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Select EventWindow()
        Case #MainWindow
          appQuit = 1
        Case settingsWindow
          CloseSettingsWindow(0)
      EndSelect
            
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #SettingsButton
          OpenSettingsWindow(#MainWindow)
        Case doneButton
          CloseSettingsWindow(1)
        Case requiredInfo
          Select EventType()
            Case #PB_EventType_Change
              If Trim(GetGadgetText(requiredInfo))
                infoDone = #True
              Else
                infoDone = #False
              EndIf
          EndSelect
      EndSelect
  EndSelect
Until appQuit = 1
Far as I can see, it should work on Linux as well. :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
agb2008
User
User
Posts: 60
Joined: Fri Jan 15, 2016 2:22 pm

Re: WaitWindowEvent() - question (win/lin)

Post by agb2008 »

infratec:

Understood. Would do so in case of future questions posts. 8)

nco2k:

Thank you very much ! I've tested the code that you suggested and could confirm that it's solving issue that i am getting
and as well working on both Windows and Linux platforms ! :D

TI-994A:

Thank you for suggestion. Unfortunately it does not provide functionality that I am looking for - main application window
continue to be active when child window visible. I was looking for solution that would block main window until child window
is closed (like code provided by nco2k)
User avatar
TI-994A
Addict
Addict
Posts: 2751
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: WaitWindowEvent() - question (win/lin)

Post by TI-994A »

agb2008 wrote:...main application window continue to be active when child window visible. I was looking for solution that would block main window until child window is closed...
Right; although a few strategically inserted DisableWindow() statements would nicely achieve that.

On the other hand, with no disrespect to nco2k's solution, transferring the event loop away from the main program has it's pros and cons. While it helps with modularising certain interface functions, it halts the main program totally.

To demonstrate this, clock displays have been added to both examples:

from nco2k's example:

Code: Select all

EnableExplicit

Enumeration
  #Window_Main = 0
  #Window_About
  #Main_Button = 0
  #Main_Clock
  #About_Text
EndEnumeration

Procedure About()
  Protected WindowEvent
  If OpenWindow(#Window_About, 0, 0, 220, 100, "About...", #PB_Window_SystemMenu | #PB_Window_WindowCentered | #PB_Window_Invisible, WindowID(#Window_Main));<--- THIS
    TextGadget(#About_Text, 10, 30, 200, 25, "NOTICE HOW THE CLOCK STOPS!", #PB_Text_Center)
    DisableWindow(#Window_Main, #True);<--- THIS
    HideWindow(#Window_About, #False)
    Repeat
      WindowEvent = WaitWindowEvent()
      If EventWindow() = #Window_About
        Select WindowEvent
          Case #PB_Event_CloseWindow
            Break
        EndSelect
      EndIf
    ForEver
    CloseWindow(#Window_About)
    DisableWindow(#Window_Main, #False);<--- THIS
  EndIf
EndProcedure

Procedure Main()
  Protected WindowEvent
  If OpenWindow(#Window_Main, 0, 0, 300, 250, "Main", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered | #PB_Window_Invisible)
    ButtonGadget(#Main_Button, 75, 200, 150, 25, "Click")
    TextGadget(#Main_Clock, 10, 10, 200, 30, FormatDate("%hh:%ii:%ss", Date())) 
    AddWindowTimer(#Window_Main, 0, 1000)    
    HideWindow(#Window_Main, #False)
    Repeat
      WindowEvent = WaitWindowEvent()
      If EventWindow() = #Window_Main
        Select WindowEvent
          Case #PB_Event_Timer
            SetGadgetText(#Main_Clock, FormatDate("%hh:%ii:%ss", Date()))             
          Case #PB_Event_Gadget
            Select EventGadget()
              Case #Main_Button
                About()
            EndSelect
          Case #PB_Event_CloseWindow
            Break
        EndSelect
      EndIf
    ForEver
    CloseWindow(#Window_Main)
  EndIf
EndProcedure

Main()
from my example:

Code: Select all

Enumeration
  #MainWindow
  #ClockDisplay
  #SettingsButton
EndEnumeration

Define settingsWindow, requiredInfo, doneButton, infoDone, wFlags

Procedure OpenSettingsWindow(parentWindow.i)
  Shared settingsWindow, requiredInfo, doneButton, wFlags
  settingsWindow = OpenWindow(#PB_Any, #PB_Any, #PB_Any, 
                              300, 200, "Settings Window", 
                              wFlags, WindowID(parentWindow))
  requiredInfo = StringGadget(#PB_Any, 100, 80, 100, 30, "")
  doneButton = ButtonGadget(#PB_Any, 100, 130, 100, 30, "DONE")  
  SetActiveGadget(requiredInfo)
EndProcedure

Procedure CloseSettingsWindow(done.i)
  Shared infoDone, settingsWindow
  If infoDone
    infoDone = #False
    CloseWindow(settingsWindow)
    DisableWindow(#MainWindow, #False)
  Else
    If done
      MessageRequester("Settings", "Input Required!")
    Else
      If MessageRequester("Settings", "Confirm Abort Settings?", 
                          #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
        CloseWindow(settingsWindow)
        DisableWindow(#MainWindow, #False)
      EndIf
    EndIf
  EndIf
EndProcedure

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(#MainWindow, #PB_Any, #PB_Any, 600, 400, "Main Window", wFlags)
TextGadget(#ClockDisplay, 10, 10, 200, 30, FormatDate("%hh:%ii:%ss", Date())) 
ButtonGadget(#SettingsButton, 100, 330, 400, 50, "SETTINGS")
AddWindowTimer(#MainWindow, 0, 1000)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Timer
      SetGadgetText(#ClockDisplay, FormatDate("%hh:%ii:%ss", Date())) 
      
    Case #PB_Event_CloseWindow
      Select EventWindow()
        Case #MainWindow
          appQuit = 1
        Case settingsWindow
          CloseSettingsWindow(0)
      EndSelect
            
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #SettingsButton
          DisableWindow(#MainWindow, #True)
          OpenSettingsWindow(#MainWindow)
        Case doneButton
          CloseSettingsWindow(1)
        Case requiredInfo
          Select EventType()
            Case #PB_EventType_Change
              If Trim(GetGadgetText(requiredInfo))
                infoDone = #True
              Else
                infoDone = #False
              EndIf
          EndSelect
      EndSelect
  EndSelect
Until appQuit = 1
Notice how the clock stops in the first example.

In addition to timer-based events, even thread and network events would not be processed.

Bears noting. :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
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: WaitWindowEvent() - question (win/lin)

Post by nco2k »

TI-994A wrote:transferring the event loop away from the main program has it's pros and cons.
correct. it all depends on the type of app you are creating. if you want the user to be able to work on multiple windows at the same time, then yes, you should keep everything in one event loop. but if you want the user to be able to work on just one window at a time, then transfering the event loop, is the easiest way and has some huge advantages.

in your example, clicking multiple times on the button, will open multiple windows and you wont be able to close the others, because you used #PB_Any and you overwrite the settingsWindow variable each time. with my example, all of this can never happen. sure, you fixed it by simply using DisableWindow(), but if some joker finds out the hWnd and uses EnableWindow_() to change that, then you will have the same problem again. you should use IsWindow() and check if the window already exists, before opening a new one. having one event loop requires more code, to make it bulletproof. its really just a design choice. :)
TI-994A wrote:even thread and network events would not be processed.
threads and network events are totally independet from the window event loop. in fact, you should always run the netcode and the gui, in two separate threads. running both in one thread, will significally slow down your netcode, as it has to always wait for the gui to finish painting. you wont notice anything on a small scale, but if you have 100.000 connections coming in at the same time, you will notice. trust me, i have been there. :wink:

EDIT: holy shit my 1000th post! it took me nearly 13 years. do i now get a medal or something? fred? :mrgreen:

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
mestnyi
Addict
Addict
Posts: 1102
Joined: Mon Nov 25, 2013 6:41 am

Re: WaitWindowEvent() - question (win/lin)

Post by mestnyi »

nco2k Now this will not work purebasik 542 using Bendevent that's stupidity :evil:

Code: Select all

EnableExplicit

Enumeration
  #Window_Main = 0
  #Window_About
  #Main_Button = 0
  #About_Text
EndEnumeration

Procedure About()
  Protected WindowEvent
  If OpenWindow(#Window_About, 0, 0, 200, 100, "About...", #PB_Window_SystemMenu | #PB_Window_WindowCentered | #PB_Window_Invisible, WindowID(#Window_Main));<--- THIS
    TextGadget(#About_Text, 10, 10, 100, 25, "Text")
    DisableWindow(#Window_Main, #True);<--- THIS
    HideWindow(#Window_About, #False)
    Repeat
      WindowEvent = WaitWindowEvent()
      If EventWindow() = #Window_About
        Select WindowEvent
          Case #PB_Event_CloseWindow
            Break
        EndSelect
      EndIf
    ForEver
    CloseWindow(#Window_About)
    DisableWindow(#Window_Main, #False);<--- THIS
  EndIf
EndProcedure


Procedure BindProcedure()
  Select EventGadget()
    Case #Main_Button
      About()
  EndSelect
EndProcedure

Procedure Main()
  Protected WindowEvent
  If OpenWindow(#Window_Main, 0, 0, 300, 200, "Main", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered | #PB_Window_Invisible)
    ButtonGadget(#Main_Button, 10, 10, 150, 25, "Click")
    HideWindow(#Window_Main, #False)
    
    BindEvent( #PB_Event_Gadget, @BindProcedure(), #Window_Main )
    Repeat
      WindowEvent = WaitWindowEvent()
      If EventWindow() = #Window_Main
        Select WindowEvent
;           Case #PB_Event_Gadget
;             Select EventGadget()
;               Case #Main_Button
;                 About()
;             EndSelect
          Case #PB_Event_CloseWindow
            Break
        EndSelect
      EndIf
    ForEver
    CloseWindow(#Window_Main)
  EndIf
EndProcedure

Main()
User avatar
nco2k
Addict
Addict
Posts: 1344
Joined: Mon Sep 15, 2003 5:55 am

Re: WaitWindowEvent() - question (win/lin)

Post by nco2k »

i totally agree, your code is stupid. :D if you dont know how BindEvent() works and what you can and cannot do in a callback, then you shouldnt use them in the first place. :wink:

agb2008 asked for a solution that fits his needs and i gave him one. now you expect it to magically work for your needs. if you had actually read what TI-994A and i were talking about, you would know that those are two different concepts. but i guess you are just one of those guys, who eat a soup with a fork. :twisted:

c ya,
nco2k
If OSVersion() = #PB_OS_Windows_ME : End : EndIf
DontTalkToMe
Enthusiast
Enthusiast
Posts: 334
Joined: Mon Feb 04, 2013 5:28 pm

Re: WaitWindowEvent() - question (win/lin)

Post by DontTalkToMe »

nco2k wrote:eat a soup with a fork
You should try with chopsticks. :)
User avatar
TI-994A
Addict
Addict
Posts: 2751
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: WaitWindowEvent() - question (win/lin)

Post by TI-994A »

nco2k wrote:...threads and network events are totally independet from the window event loop. in fact, you should always run the netcode and the gui, in two separate threads. running both in one thread, will significally slow down your netcode, as it has to always wait for the gui to finish painting...
You're quite right; threads by their very nature run independently. And although network events can be processed within the main event loop, it's recommended that they run in separate threads.

However, spawned threads invariably communicate with the main program by posting events, updating the main event loop with its progress, results, completion, etc. When the main event loop is suspended or transferred to another loop, such events would be lost.

Losing timer events for updating a clock display may be inconsequential, but losing critical events posted by threads could be detrimental.

This constitutes a major failing, which is why multiple message loops are not recommended. :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
Post Reply