Page 2 of 2

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

Posted: Sun Apr 24, 2016 11:29 am
by nco2k
it depends on the type of message though. if you post messages to the window que, then yes. but if you send messages to the window proc, then it doesnt really matter. you could even use SetGadgetState() etc. from withing a thread, to update the progress. no one is forcing you to post messages to the window que. :) and as long as you dont mess around with the state of the gadget, from any other thread, its perfectly safe. even if you do, windows is very forgiving, but its a pretty bad habbit though.

personally, i only use the window que for the user interaction. everything else i do with callbacks. in your example, dragging the window will stop updating the clock, because the window que is paused as well. if you use a callback however, it will work independently.

there is really no right or wrong. different tools, for different tasks. :)

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

Procedure ClockDisplay()
  SetGadgetText(#ClockDisplay, FormatDate("%hh:%ii:%ss", Date())) 
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)
BindEvent(#PB_Event_Timer, @ClockDisplay(), #MainWindow)

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
          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
c ya,
nco2k

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

Posted: Sun Apr 24, 2016 1:41 pm
by TI-994A
nco2k wrote:...you could even use SetGadgetState() etc. from withing a thread, to update the progress. no one is forcing you to post messages to the window que...
For simple, non-critical events that don't require immediate attention, sure. But not for those that do. The main event loop would remain oblivious to them until control is returned to it, and consequently, it would not be able to even prompt the user of impending action.
nco2k wrote:...in your example, dragging the window will stop updating the clock, because the window que is paused as well...
Paused, but not lost. :wink:

I've added a counter to demonstrate this:

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
      counter + 1
      SetGadgetText(#ClockDisplay, 
                    FormatDate("%hh:%ii:%ss", 
                               Date()) + "  (" + Str(counter) + ")")
      
    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
Although timer events are not processed during a window-move, they are still queued, and subsequently executed.

In a multi-event-loop model, like yours, once control is transferred to the event loop of the second window, they are never processed, as can be seen here:

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, counter
  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
            counter + 1
            SetGadgetText(#Main_Clock, 
                          FormatDate("%hh:%ii:%ss", 
                                     Date()) + "  (" + Str(counter) + ")")            
          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()
The counter increments stop as soon as the second window is opened, and continues exactly where it left off when the second window is closed. Basically, nothing in the main event loop gets processed while the second window is active; any and all events will simply be lost; not paused, and not queued.

Not always a recommended approach. :wink:

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

Posted: Sun Apr 24, 2016 2:59 pm
by nco2k
TI-994A wrote:Basically, nothing in the main event loop gets processed while the second window is active
yes and that IS exactly the wanted behavior, by design. if you choose this method, then you DONT want the user to interact with the other windows. you place the user interaction code in the window que loop of each window and use callbacks for everything else. those are simply two different concepts, with both pros and cons. nothing more, nothing less. :)

if you eat a soup, you choose a spoon. if you eat pasta, you choose a fork. if you choose a fork to eat a soup, then dont complain that its not working the way you expect it to. :P

Code: Select all

EnableExplicit

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

Global counter

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 DOESNT STOP!", #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 ClockDisplay()
  counter + 1
  SetGadgetText(#Main_Clock, 
  FormatDate("%hh:%ii:%ss", 
  Date()) + "  (" + Str(counter) + ")")    
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)    
    BindEvent(#PB_Event_Timer, @ClockDisplay(), #Window_Main)
    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

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

Posted: Sun Apr 24, 2016 3:28 pm
by mestnyi
For example, here is how you can implement without another cycle provided versatility?

Code: Select all

#CC_Program = "Visual designer helper"
#CC_MainProgram_Title = "Main"
#CC_ImageHelper_Title = "Image editor"


Enumeration CC_Window
  #CC_MainProgram
EndEnumeration

Enumeration CC_Gadget
  #CC_MainProgram_Gadget_Close
  #CC_MainProgram_Gadget_View
EndEnumeration


UseJPEG2000ImageDecoder()
UseJPEGImageDecoder() 
UsePNGImageDecoder()
UseTIFFImageDecoder() 
UseTGAImageDecoder()

Enumeration CC_Window
  #CC_ImageHelper
EndEnumeration

Enumeration CC_Gadget
  #CC_ImageHelper_Gadget_Close
  #CC_ImageHelper_Gadget_Open
  #CC_ImageHelper_Gadget_View
  
  #CC_ImageHelper_Gadget_Ok
  #CC_ImageHelper_Gadget_Cancel
EndEnumeration

Procedure CC_ImageHelper_Close( )
  PostEvent( #PB_Event_CloseWindow, #CC_ImageHelper, #PB_Ignore )
EndProcedure

Procedure CC_ImageHelper_Event_Gadgets( )
  
  Select EventGadget()
    Case #CC_ImageHelper_Gadget_Close
      Select EventType()
        Case #PB_EventType_LeftClick
          CC_ImageHelper_Close( )
          
      EndSelect
      
  EndSelect
  
EndProcedure

Procedure CC_ImageHelper_Gadgets( Window, Width, Height )
  ImageGadget(#CC_ImageHelper_Gadget_View, 5, 5, 326, 198, 0, #PB_Image_Border)
  ButtonGadget(#CC_ImageHelper_Gadget_Open, 335, 5, 101, 23, "Загрузить")
  
  ButtonGadget(#CC_ImageHelper_Gadget_Ok, 335, 152, 101, 23, "Применить")
  ButtonGadget(#CC_ImageHelper_Gadget_Cancel, 335, 179, 101, 23, "Отменить")
  
  BindEvent( #PB_Event_Gadget, @CC_ImageHelper_Event_Gadgets(), Window )
EndProcedure

Procedure CC_ImageHelper_Window( Flag, ParentID = #False, Width = 441, Height = 207 )
  Protected Window = #CC_ImageHelper
  
  If IsWindow( Window ) 
    If (( Flag & #PB_Window_NoActivate ) = #PB_Window_NoActivate )
      HideWindow( Window, #True )
    Else
      SetActiveWindow( Window )
    EndIf
  Else
    OpenWindow( Window, #PB_Ignore, #PB_Ignore, Width, Height, #CC_ImageHelper_Title, Flag, ParentID )
    CC_ImageHelper_Gadgets( Window, Width, Height )
    
    
    If ( Flag &~ #PB_Window_Invisible )
      If (( Flag & #PB_Window_ScreenCentered ) = #PB_Window_ScreenCentered )
        HideWindow( Window, #False, #PB_Window_ScreenCentered )
      ElseIf (( Flag & #PB_Window_WindowCentered ) = #PB_Window_WindowCentered )
        HideWindow( Window, #False, #PB_Window_WindowCentered )
      ElseIf (( Flag & #PB_Window_NoActivate ) = #PB_Window_NoActivate )
        HideWindow( Window, #False, #PB_Window_NoActivate)
      EndIf
    EndIf
  EndIf
  
  ProcedureReturn Window
EndProcedure

Procedure CC_ImageHelper_Show( MainWindow =- 1, Flag = #PB_Window_WindowCentered )
  Protected Result, Window
  
  If IsWindow( MainWindow ) 
    DisableWindow( MainWindow , #True )
    
    Window = CC_ImageHelper_Window( Flag, WindowID( MainWindow ) )
    
    While IsWindow( Window ) 
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow 
          ;If MessageRequester( "Settings", "Confirm Abort Settings?", #PB_MessageRequester_YesNo ) = #PB_MessageRequester_Yes
            CloseWindow( EventWindow() )
          ;EndIf
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #CC_ImageHelper_Gadget_Open
              Select EventType()
                Case #PB_EventType_LeftClick
                  Protected File$ = OpenFileRequester("Please choose file to load", "", "PNG Image (*.png)|*.png|All files (*.*)|*.*", 0)
                  If File$
                    Protected img = LoadImage(#PB_Any,File$)
                    SetGadgetState(#CC_ImageHelper_Gadget_View,ImageID(img))
                  EndIf
                  
              EndSelect
              
            Case #CC_ImageHelper_Gadget_Ok
              Select EventType()
                Case #PB_EventType_LeftClick
                  CloseWindow( EventWindow() )
                  Result = img
                  
              EndSelect
              
          EndSelect
    
      EndSelect
    Wend
    
    DisableWindow( MainWindow , #False )
  EndIf
  
  ProcedureReturn Result
EndProcedure




Procedure CC_MainProgram_Event_Close( )
  Protected Window = #CC_MainProgram
  
  If IsWindow( Window )
    CloseWindow( Window )
  EndIf
  
  ProcedureReturn Window
EndProcedure

Procedure CC_MainProgram_Event_Gadgets( )
  
  Select EventGadget()
    Case #CC_MainProgram_Gadget_Close
      Select EventType()
        Case #PB_EventType_LeftClick
          ;CC_ImageHelper_Show( EventWindow() )
          
      EndSelect
      
  EndSelect
  
EndProcedure

Procedure CC_MainProgram_Gadgets( Window, Width, Height )
  ImageGadget(#CC_MainProgram_Gadget_View, 5, 5, Width-10, Height-50, 0, #PB_Image_Border)
  ButtonGadget(#CC_MainProgram_Gadget_Close, Width-111, Height-34, 101, 24, "Load Image")
  
  BindEvent( #PB_Event_Gadget, @CC_MainProgram_Event_Gadgets(), Window )
EndProcedure

Procedure CC_MainProgram_Window( Flag, ParentID = #False, Width = 496, Height = 364 )
  Protected Window = #CC_MainProgram
  
  If IsWindow( Window ) 
    If (( Flag & #PB_Window_NoActivate ) = #PB_Window_NoActivate )
      HideWindow( Window, #True )
    Else
      SetActiveWindow( Window )
    EndIf
  Else
    OpenWindow( Window, #PB_Ignore, #PB_Ignore, Width, Height, #CC_MainProgram_Title, Flag, ParentID )
    CC_MainProgram_Gadgets( Window, Width, Height )
    
    
    If ( Flag &~ #PB_Window_Invisible )
      If (( Flag & #PB_Window_ScreenCentered ) = #PB_Window_ScreenCentered )
        HideWindow( Window, #False, #PB_Window_ScreenCentered )
      ElseIf (( Flag & #PB_Window_WindowCentered ) = #PB_Window_WindowCentered )
        HideWindow( Window, #False, #PB_Window_WindowCentered )
      ElseIf (( Flag & #PB_Window_NoActivate ) = #PB_Window_NoActivate )
        HideWindow( Window, #False, #PB_Window_NoActivate)
      EndIf
    EndIf
    
    If (( Flag & #PB_Window_SystemMenu ) = #PB_Window_SystemMenu )
      BindEvent( #PB_Event_CloseWindow, @CC_MainProgram_Event_Close(), Window )
    EndIf
  EndIf
  
  ProcedureReturn Window
EndProcedure

Procedure CC_MainProgram_Show( MainWindow =- 1, Flag = #PB_Window_ScreenCentered|#PB_Window_MaximizeGadget )
  Protected Window = CC_MainProgram_Window( Flag )
  
  While IsWindow( Window ) 
    Select WaitWindowEvent()
        ;       Case #PB_Event_CloseWindow 
        ;         CloseWindow( EventWindow() )
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #CC_MainProgram_Gadget_Close
            Select EventType()
              Case #PB_EventType_LeftClick
                Protected img = CC_ImageHelper_Show( EventWindow() )
                  SetGadgetState(#CC_MainProgram_Gadget_View,ImageID(img))
                  
            EndSelect
            
        EndSelect
        
    EndSelect
  Wend
  
  ProcedureReturn Window
EndProcedure

CompilerIf #PB_Compiler_IsMainFile
  CC_MainProgram_Show( )
  End
CompilerEndIf

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

Posted: Sun Apr 24, 2016 4:32 pm
by TI-994A
nco2k wrote:...that IS exactly the wanted behavior, by design. if you choose this method, then you DONT want the user to interact with the other windows. you place the user interaction code in the window que loop of each window and use callbacks for everything else.
Not quite. There's a big difference between not wanting the user to interact with other windows and suspending the main program loop altogether. :wink:

Sure, now you've implemented a callback as a workaround, but that was not in your initial design. We're discussing the total surrender of the main event loop to another. With callbacks, that's no longer the case.

Stop trying to use forks and spoons to code! :lol:

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

Posted: Sun Apr 24, 2016 5:02 pm
by nco2k
TI-994A wrote:There's a big difference between not wanting the user to interact with other windows and suspending the main program loop altogether
TI-994A wrote:We're discussing the total surrender of the main event loop to another
which is a design choice. :wink:
TI-994A wrote:Sure, now you've implemented a callback as a workaround, but that was not in your initial design
neither was the timer. you came up with that. :P and its not a workaround, its exactly how this type of concept should work. i said it multiple times already, i put the user interaction code in the loop and everything else in callbacks. :)

dont get me wrong, im not against "your" method. i use it a lot actually, when the app requires it. but im also using "my" method, when the app requires it. it really just depends on the app itself, as both methods have pros and cons.
TI-994A wrote:Stop trying to use forks and spoons to code!
well, DontTalkToMe stole my chopsticks. :x

anyway, im done talking about this. we already spent way too much time on it. :)

c ya,
nco2k

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

Posted: Mon Apr 25, 2016 5:52 am
by mestnyi
here is how you can implement without another cycle
???

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

Posted: Mon Apr 25, 2016 6:33 am
by TI-994A
nco2k wrote:which is a design choice.
No; it's a design flaw. Let's not forget that we're discussing the example that you originally posted; which totally relinquished control of the main event loop to another, with no callbacks or contingencies. :wink:

We can wax ideal on the proper ways to implement different models, but that's not what's being discussed. Bottom line: totally transferring control away from the main event loop should be avoided at all costs. PERIOD.

And, maintaining a single event loop does not have any drawbacks; forks, spoons, or chopsticks! :lol:

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

Posted: Thu Apr 28, 2016 8:05 am
by agb2008
Just as additional note - I've rearranged a bit main test.pb file and looks like solution was much easier
for my case - was able to solve issue with Linux builds and as well got exactly what I want without
implementing separate main loop:

File: test.pb

Code: Select all

;/ Created with PureVision v5.41
;/ Wed, 20 Apr 2016 17:34:44

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

;- Main Loop
If Window_Form1()

  Repeat
    EventID  = WaitWindowEvent()
    MenuID   = EventMenu()
    GadgetID = EventGadget()
    WindowID = EventWindow()
    
    Debug EventID
    Debug WindowID

    Select WindowID
      Case #Window_Form1
        Select EventID
           Case #PB_Event_CloseWindow
             CloseWindow(#Window_Form1)
             End
           Case #PB_Event_Gadget
             Select GadgetID
               Case #Gadget_Form1_Button2
                 Window_Form3()
                 DisableWindow(#Window_Form1,#True)
                 StickyWindow(#Window_Form3,#True)
              EndSelect
          EndSelect
        Case #Window_Form3
          Select EventID
            Case #PB_Event_CloseWindow
              StickyWindow(#Window_Form3,#False)
              DisableWindow(#Window_Form1,#False)
              CloseWindow(#Window_Form3)
          EndSelect
      EndSelect
    ForEver
EndIf
As you could see it's just combination of DisableWindow and StickyWindow functions.
So I could avoid using SetActiveWindow function.

Just have to add additional window footer - to let user know that settings window have to closed
to get main application window active. :D

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

Posted: Thu Apr 28, 2016 3:39 pm
by collectordave
Interesting.

If you use Modules as well!

frmMain.pb

Code: Select all

DeclareModule Application
  
  Global Title.s = "World Collector"
  Global VersionMajor.i = 1
  Global VersionMiddle.i = 0
  Global VersionMinor.i = 0
    
  Global frmMain.i
  
  Declare Run()
  Declare EventHandler(Event)
  
EndDeclareModule

IncludeFile "dlgtest.pbi"
IncludeFile "dlgAbout.pbi"

Module Application
  
  Global Button_0.i, Button_1.i,  String_0.i
  
Procedure Run()

frmMain = OpenWindow(#PB_Any, 0, 0, 360, 150, "", #PB_Window_SystemMenu)
Button_0 = ButtonGadget(#PB_Any, 20, 90, 90, 30, "About")
Button_1 = ButtonGadget(#PB_Any, 120, 90, 90, 30, "Dialog")
String_0 = StringGadget(#PB_Any, 20, 10, 170, 20, "")
AddWindowTimer(frmMain, 0, 1000)

EndProcedure

Procedure EventHandler(Event)
  
  Static Time.i
  
  Select Event
        
      Case #PB_Event_Timer 
        time = time + 1
        SetGadgetText(String_0,Str(Time))
        
      Case #PB_Event_CloseWindow
        
       End

     Case #PB_Event_Gadget
       
       Select EventGadget()
           
         Case Button_0

          ;This dialog is not modal
           dlgAbout::Open(frmMain)
           
         Case Button_1
           
           ;This dialog is as modal as you wish
           Dialog::open(frmMain)
           
      EndSelect
      
  EndSelect
  
EndProcedure

EndModule

Application::Run()
Repeat
  
  Event = WaitWindowEvent()
  
  Application::EventHandler(Event) ;Execution of this loop stops here until the EventHandler() procedure returns
  
ForEver
dlgAbout.pbi

Code: Select all

DeclareModule dlgAbout
  
  Declare Open(Parent.i)
   
EndDeclareModule

Module dlgAbout
    
Procedure Open(ctlWnd.i)
  
  Define dlgAbout.i,btnClose.i,txtTitle.i,txtVersion.i
  
  dlgAbout = OpenWindow(#PB_Any, 0, 0, 330, 110, "About", #PB_Window_TitleBar | #PB_Window_Tool)
  btnClose = ButtonGadget(#PB_Any, 260, 70, 60, 30, "Close")
  txtTitle = TextGadget(#PB_Any, 10, 10, 310, 20, "AppTitle")
  txtVersion = TextGadget(#PB_Any, 10, 40, 310, 20, "Version")
  StickyWindow(dlgAbout,#True)
  SetGadgetText(txtTitle,Application::Title)
  SetGadgetText(txtVersion,"Version : " + Str(Application::VersionMajor) + "." + Str(Application::VersionMiddle) + "." + Str(Application::VersionMinor))
  Repeat
    
    Event = WaitWindowEvent()

    If EventWindow() = ctlWnd
      Application::EventHandler(Event)
    EndIf

    Select event

      Case #PB_Event_Gadget
        Select EventGadget()
          Case btnClose
            CloseWindow(dlgAbout)
            Break
        EndSelect
    EndSelect 
    
  ForEver
  
EndProcedure

EndModule
dlgTest.pbi

Code: Select all

DeclareModule Dialog
  
  Declare Open(Parent.i)  
  
EndDeclareModule

Module Dialog

Procedure Open(ctlWnd.i)
  
  ;ctlWnd is a handle to the window that controls this dialog
  
  dlgWindow = OpenWindow(#PB_Any, 0, 0, 360, 150, "My Dialog - Modal or Not Modal?",  #PB_Window_TitleBar | #PB_Window_Tool)
  Button_0 = ButtonGadget(#PB_Any, 120, 60, 90, 30, "Close")
  StickyWindow(dlgWindow,#True)
  
  Repeat
    ;When opened all application events are routed here
    Event = WaitWindowEvent()
    
    ;This dialog fully modal uncomment the next three program lines
    ;to keep main form counter working
    
    ;If EventWindow() = ctlWnd
    ;  Application::EventHandler(Event)
    ;EndIf

    Select event

      Case #PB_Event_Gadget
        Select EventGadget()
          Case Button_0
            CloseWindow(dlgWindow)
            Break
        EndSelect
    EndSelect 
    
  ForEver
  
EndProcedure

EndModule
You can have your cake and eat it. Put all three files in the same folder and run frmMain.

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

Posted: Thu Apr 28, 2016 7:04 pm
by mk-soft
I think that I did not understand the problem.

There's a simple rule. An event loop in the program.
Then everything work in the event loop or work with BindEvent.

In the "EventDesigner", I use the method with BindEvent and spread the events over a virtual table.

To start an operator request of a thread, I use SendEvent.

Code: Select all

; ***************************************************************************************

;-TOP
; Comment : SendEvent
; Author  : mk-soft
; Version : v1.05

;- Structure
Structure udtSendEvent
  Signal.i
  Result.i
  *pData
EndStructure

; ---------------------------------------------------------------------------------------

Procedure SendEvent(Event, Window = 0, Object = 0, EventType = 0, pData = 0, Semaphore = 0)
 
  Protected MyEvent.udtSendEvent, result
 
  With MyEvent
    If Semaphore
      \Signal = Semaphore
    Else
      \Signal = CreateSemaphore()
    EndIf
    \pData = pData
    PostEvent(Event, Window, Object, EventType, @MyEvent)
    WaitSemaphore(\Signal)
    result = \Result
    If Semaphore = 0
      FreeSemaphore(\Signal)
    EndIf
  EndWith
 
  ProcedureReturn result
 
EndProcedure

; ---------------------------------------------------------------------------------------

Procedure SendEventData(*MyEvent.udtSendEvent)
 
   ProcedureReturn *MyEvent\pData
 
EndProcedure

; ---------------------------------------------------------------------------------------

Procedure DispatchEvent(*MyEvent.udtSendEvent, result)
 
  *MyEvent\Result = result
  SignalSemaphore(*MyEvent\Signal)
 
EndProcedure

; ***************************************************************************************

;- Test

Enumeration
   #Window
EndEnumeration


;- Constants
Enumeration #PB_Event_FirstCustomValue
  #My_Event_Question
EndEnumeration

Procedure Test(Null)
 
  Protected result
 
  Debug "Init Thread"
  MySemaphore = CreateSemaphore()
 
  Repeat
    Delay(500)
    result = SendEvent(#My_Event_Question, 0, 0, 0, Random(100), MySemaphore)
    Select result
      Case #PB_MessageRequester_Yes
        Debug "Antwort Ja"
      Case #PB_MessageRequester_No
        Debug "Antwort Nein"
      Case #PB_MessageRequester_Cancel
        Debug "Antwort Abbrechen"
    EndSelect
  Until result = #PB_MessageRequester_Cancel
 
  If MySemaphore
    FreeSemaphore(MySemaphore)
  EndIf
 
  Debug "Exit Thread"
 
EndProcedure

Global MyEvent

If OpenWindow(#Window, 0, 0, 800, 600, "WindowTitle", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
 
  hThread = CreateThread(@Test(), #Null)
 
  Repeat
     
    Select WaitWindowEvent()
           
        Case #PB_Event_CloseWindow
           exit = 1
           
        Case #PB_Event_Gadget
         
        Case #My_Event_Question
           MyEvent = EventData()
           Value = SendEventData(MyEvent)
           Debug "Es kommt ein SendEvent: " + Str(Value)
           result = MessageRequester("Frage", "Wie soll es weiter gehen?", #PB_MessageRequester_YesNoCancel)
           DispatchEvent(MyEvent, result)
       
     EndSelect
     
   Until exit
   If IsThread(hThread)
     Debug "Thread läuft"
     KillThread(hThread)
   EndIf
   
 EndIf
With BindEvent

Code: Select all

; ***************************************************************************************

;-TOP
; Comment : SendEvent
; Author  : mk-soft
; Version : v1.05

;- Structure
Structure udtSendEvent
  Signal.i
  Result.i
  *pData
EndStructure

; ---------------------------------------------------------------------------------------

Procedure SendEvent(Event, Window = 0, Object = 0, EventType = 0, pData = 0, Semaphore = 0)
 
  Protected MyEvent.udtSendEvent, result
 
  With MyEvent
    If Semaphore
      \Signal = Semaphore
    Else
      \Signal = CreateSemaphore()
    EndIf
    \pData = pData
    PostEvent(Event, Window, Object, EventType, @MyEvent)
    WaitSemaphore(\Signal)
    result = \Result
    If Semaphore = 0
      FreeSemaphore(\Signal)
    EndIf
  EndWith
 
  ProcedureReturn result
 
EndProcedure

; ---------------------------------------------------------------------------------------

Procedure SendEventData(*MyEvent.udtSendEvent)
 
   ProcedureReturn *MyEvent\pData
 
EndProcedure

; ---------------------------------------------------------------------------------------

Procedure DispatchEvent(*MyEvent.udtSendEvent, result)
 
  *MyEvent\Result = result
  SignalSemaphore(*MyEvent\Signal)
 
EndProcedure

; ***************************************************************************************

;- Test

Enumeration
   #Window
EndEnumeration


;- Constants
Enumeration #PB_Event_FirstCustomValue
  #My_Event_Question
EndEnumeration

; Thread
Procedure Test(Null)
 
  Protected result
 
  Debug "Init Thread"
  
  Repeat
    Delay(500)
    result = SendEvent(#My_Event_Question, 0, 0, 0, Random(100))
    Select result
      Case #PB_MessageRequester_Yes
        Debug "Antwort Ja"
      Case #PB_MessageRequester_No
        Debug "Antwort Nein"
      Case #PB_MessageRequester_Cancel
        Debug "Antwort Abbrechen"
    EndSelect
  Until result = #PB_MessageRequester_Cancel
  
  Debug "Exit Thread"
 
EndProcedure

; BindEvent
Procedure MyEvent()
  
  Protected MyEvent
  
  MyEvent = EventData()
  Value = SendEventData(MyEvent)
  Debug "Es kommt ein SendEvent: " + Str(Value)
  result = MessageRequester("Frage", "Wie soll es weiter gehen?", #PB_MessageRequester_YesNoCancel)
  DispatchEvent(MyEvent, result)
  
EndProcedure


If OpenWindow(#Window, 0, 0, 800, 600, "WindowTitle", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
  
  BindEvent(#My_Event_Question, @MyEvent())
  
  hThread = CreateThread(@Test(), #Null)
 
  Repeat
     
    Select WaitWindowEvent()
           
        Case #PB_Event_CloseWindow
           exit = 1
           
        Case #PB_Event_Gadget
         
     EndSelect
     
   Until exit
   If IsThread(hThread)
     Debug "Thread läuft"
     KillThread(hThread)
   EndIf
   
 EndIf

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

Posted: Tue May 03, 2016 1:01 pm
by mestnyi
And whether or not right? Or is there another option?

Code: Select all

#CC_Program = "Visual designer helper"
#CC_MainProgram_Title = "Main"
#CC_ImageHelper_Title = "Image editor"

EnableExplicit

;-
Enumeration CC_Window
  #CC_MainProgram
EndEnumeration

Enumeration CC_Gadget
  #CC_MainProgram_Gadget_View
  #CC_MainProgram_Gadget_Close
EndEnumeration


UseJPEG2000ImageDecoder()
UseJPEGImageDecoder() 
UsePNGImageDecoder()
UseTIFFImageDecoder() 
UseTGAImageDecoder()

Global CC_ImageHelper_Show_Type =- 1
Global CC_ImageHelper_Show_Gadget =- 1
Global CC_ImageHelper_Show_Window =- 1
Global CC_ImageHelper_Show_Result =- 1

;-
Enumeration CC_Window
  #CC_ImageHelper
EndEnumeration

Enumeration CC_Gadget
  #CC_ImageHelper_Gadget_Close
  #CC_ImageHelper_Gadget_Open
  #CC_ImageHelper_Gadget_View
  
  #CC_ImageHelper_Gadget_Ok
  #CC_ImageHelper_Gadget_Cancel
EndEnumeration

Procedure CC_ImageHelper_Close( )
  
  DisableWindow( CC_ImageHelper_Show_Window , #False )
  CloseWindow( #CC_ImageHelper )
  ;PostEvent( #PB_Event_CloseWindow, #CC_ImageHelper, #PB_Ignore )
EndProcedure

Procedure CC_ImageHelper_Event_Gadgets( )
  
  Select EventGadget()
    Case #CC_ImageHelper_Gadget_Open
      Select EventType()
        Case #PB_EventType_LeftClick
          Protected File$ = OpenFileRequester("Please choose file to load", "", "PNG Image (*.png)|*.png|All files (*.*)|*.*", 0)
          
          If File$
            CC_ImageHelper_Show_Result = LoadImage(#PB_Any, File$)
            SetGadgetState(#CC_ImageHelper_Gadget_View, ImageID(CC_ImageHelper_Show_Result))
            
            DisableGadget(#CC_ImageHelper_Gadget_Ok, #False)
          EndIf
          
      EndSelect
      
    Case #CC_ImageHelper_Gadget_Ok
      Select EventType()
        Case #PB_EventType_LeftClick
          If IsImage( CC_ImageHelper_Show_Result )
            CC_ImageHelper_Close( )
            
            PostEvent( #PB_Event_Gadget, CC_ImageHelper_Show_Window, CC_ImageHelper_Show_Gadget, CC_ImageHelper_Show_Type )
          EndIf
          
      EndSelect
      
      
    Case #CC_ImageHelper_Gadget_Cancel
      Select EventType()
        Case #PB_EventType_LeftClick
          CC_ImageHelper_Close( )
          If IsImage( CC_ImageHelper_Show_Result )
            FreeImage( CC_ImageHelper_Show_Result )
          EndIf
          
      EndSelect
      
  EndSelect
  
EndProcedure

Procedure CC_ImageHelper_Gadgets( Window, Width, Height )
  ImageGadget(#CC_ImageHelper_Gadget_View, 5, 5, 326, 198, 0, #PB_Image_Border)
  ButtonGadget(#CC_ImageHelper_Gadget_Open, 335, 5, 101, 23, "Загрузить")
  
  ButtonGadget(#CC_ImageHelper_Gadget_Ok, 335, 152, 101, 23, "Применить")
  DisableGadget(#CC_ImageHelper_Gadget_Ok,#True)
  
  ButtonGadget(#CC_ImageHelper_Gadget_Cancel, 335, 179, 101, 23, "Отменить")
  
  BindEvent( #PB_Event_Gadget, @CC_ImageHelper_Event_Gadgets(), Window )
EndProcedure

Procedure CC_ImageHelper_Window( Flag, ParentID = #False, Width = 441, Height = 207 )
  Protected Window = #CC_ImageHelper
  
  If IsWindow( Window ) 
    If (( Flag & #PB_Window_NoActivate ) = #PB_Window_NoActivate )
      HideWindow( Window, #True )
    Else
      SetActiveWindow( Window )
    EndIf
  Else
    OpenWindow( Window, #PB_Ignore, #PB_Ignore, Width, Height, #CC_ImageHelper_Title, Flag, ParentID )
    CC_ImageHelper_Gadgets( Window, Width, Height )
    
    
    If ( Flag &~ #PB_Window_Invisible )
      If (( Flag & #PB_Window_ScreenCentered ) = #PB_Window_ScreenCentered )
        HideWindow( Window, #False, #PB_Window_ScreenCentered )
      ElseIf (( Flag & #PB_Window_WindowCentered ) = #PB_Window_WindowCentered )
        HideWindow( Window, #False, #PB_Window_WindowCentered )
      ElseIf (( Flag & #PB_Window_NoActivate ) = #PB_Window_NoActivate )
        HideWindow( Window, #False, #PB_Window_NoActivate)
      Else
        HideWindow( Window, #False )
      EndIf
    EndIf
  EndIf
  
  ProcedureReturn Window
EndProcedure

Procedure CC_ImageHelper_Show( Flag = #PB_Window_WindowCentered )
  Protected Result
  Protected ParentID
  
  If IsImage( CC_ImageHelper_Show_Result )
    Result = CC_ImageHelper_Show_Result
    CC_ImageHelper_Show_Result =- 1
    
    ProcedureReturn Result
  EndIf
  
  If IsWindow( EventWindow() ) 
    CC_ImageHelper_Show_Type = EventType()
    CC_ImageHelper_Show_Gadget = EventGadget()
    CC_ImageHelper_Show_Window = EventWindow()
    
    DisableWindow( CC_ImageHelper_Show_Window, #True )
    ParentID = WindowID( CC_ImageHelper_Show_Window )
  EndIf
  
  CC_ImageHelper_Window( Flag, ParentID )
  
EndProcedure



;-
Procedure CC_MainProgram_Event_Close( )
  Protected Window = #CC_MainProgram
  
  If IsWindow( Window )
    CloseWindow( Window )
  EndIf
  
  ProcedureReturn Window
EndProcedure

Procedure CC_MainProgram_Event_Gadgets( )
  
  Select EventGadget()
    Case #CC_MainProgram_Gadget_Close
      Select EventType()
        Case #PB_EventType_LeftClick
          Protected img = CC_ImageHelper_Show( )
          
          If IsImage(img)
            SetGadgetState(#CC_MainProgram_Gadget_View, ImageID(img))
          EndIf
          
      EndSelect
      
  EndSelect
  
EndProcedure

Procedure CC_MainProgram_Gadgets( Window, Width, Height )
  ImageGadget(#CC_MainProgram_Gadget_View, 5, 5, Width-10, Height-50, 0, #PB_Image_Border)
  ButtonGadget(#CC_MainProgram_Gadget_Close, Width-111, Height-34, 101, 24, "Load Image")
  
  BindEvent( #PB_Event_Gadget, @CC_MainProgram_Event_Gadgets(), Window )
EndProcedure

Procedure CC_MainProgram_Window( Flag, ParentID = #False, Width = 496, Height = 364 )
  Protected Window = #CC_MainProgram
  
  If IsWindow( Window ) 
    If (( Flag & #PB_Window_NoActivate ) = #PB_Window_NoActivate )
      HideWindow( Window, #True )
    Else
      SetActiveWindow( Window )
    EndIf
  Else
    OpenWindow( Window, #PB_Ignore, #PB_Ignore, Width, Height, #CC_MainProgram_Title, Flag, ParentID )
    CC_MainProgram_Gadgets( Window, Width, Height )
    
    
    BindEvent( #PB_Event_CloseWindow, @CC_MainProgram_Event_Close(), Window )
    
    If ( Flag &~ #PB_Window_Invisible )
      If (( Flag & #PB_Window_ScreenCentered ) = #PB_Window_ScreenCentered )
        HideWindow( Window, #False, #PB_Window_ScreenCentered )
      ElseIf (( Flag & #PB_Window_WindowCentered ) = #PB_Window_WindowCentered )
        HideWindow( Window, #False, #PB_Window_WindowCentered )
      ElseIf (( Flag & #PB_Window_NoActivate ) = #PB_Window_NoActivate )
        HideWindow( Window, #False, #PB_Window_NoActivate)
      Else
        HideWindow( Window, #False )
      EndIf
    EndIf
  EndIf
  
  ProcedureReturn Window
EndProcedure

Procedure CC_MainProgram_Show( Flag = #PB_Window_ScreenCentered|#PB_Window_MaximizeGadget )
  Protected Window = CC_MainProgram_Window( Flag )
  
  While IsWindow( Window ) 
    Select WaitWindowEvent()
;       Case #PB_Event_CloseWindow 
;          CloseWindow( EventWindow() )
        
    EndSelect
  Wend
  
  ProcedureReturn Window
EndProcedure

CompilerIf #PB_Compiler_IsMainFile
  CC_MainProgram_Show( )
  End
CompilerEndIf