Page 1 of 1

Customizing the "Exit message dialog box" and resulting in the error "window freezes, not responding"

Posted: Mon Jun 10, 2024 3:26 am
by hoangdiemtinh
I am new to PB. My primary language is not US/UK. I am using Google Translate.

I customized the program exit MessageBox and the result was the "window freeze, not responding".

The "window freezing" problem occurs when I press the X Button of the Exit Window.
and when I press the No Button of the Exit Window.

I put in the event: #PB_Event_CloseWindow.

Why ? Please help me.

This is my program.

Code: Select all

EnableExplicit

DeclareModule for_all
  ;- DeclareModule for_all
  Enumeration windows
    #main_wind
    #exit_wind
  EndEnumeration
  Enumeration gadgets
    ; exit_wind
    #GG_EXIT_WIND_image_LOGO
    #GG_EXIT_WIND_Text_Title
    #GG_EXIT_WIND_String_Title
    #GG_EXIT_WIND_ButtonImage_YES
    #GG_EXIT_WIND_ButtonImage_NO
    ; main_wind
    #GG_MAIN_WIND_ButtonImage_Exit
  EndEnumeration
  Global icoH
EndDeclareModule ;-> EndDeclareModule for_all

Module for_all
  ;- Module for_all
EndModule ;-> EndModule for_all

DeclareModule exit_win
  ;- DeclareModule exit_win
  Declare Create_EXIT_WIND(Title$, Parent_IdWin.i)
  Declare Looping_EXIT_WIND(Title$, SubTitle$, Parent_IdWin.i)
EndDeclareModule ;-> EndDeclareModule exit_win

Module exit_win
  ;- Module exit_win
  UseModule for_all
  Procedure Create_EXIT_WIND(Title$, Parent_IdWin.i)
    OpenWindow(#exit_wind, 0, 0, 320, 200, Title$, #PB_Window_SystemMenu|#PB_Window_ScreenCentered, Parent_IdWin.i)
    icoH = LoadIcon_(999, #IDI_APPLICATION)
    ImageGadget(#GG_EXIT_WIND_image_LOGO, 10, 10, 32, 32, icoH)
    TextGadget(#GG_EXIT_WIND_Text_Title, 50, 10, 200, 25, "#GG_EXIT_WIND_Text_Title")
    StringGadget(#GG_EXIT_WIND_String_Title, 10, 40, 300, 100, "#GG_EXIT_WIND_String_Title", #ES_MULTILINE|#ESB_DISABLE_BOTH|#ES_READONLY)
    ButtonGadget(#GG_EXIT_WIND_ButtonImage_NO, 50, 150, 80, 45, "no")
    ButtonGadget(#GG_EXIT_WIND_ButtonImage_YES, 140, 150, 80, 45, "yes")
    HideWindow(#exit_wind, #False)
    ProcedureReturn WindowID(#exit_wind)
  EndProcedure
  
  Procedure Looping_EXIT_WIND(Title$, SubTitle$, Parent_IdWin.i)
    Define.i quitWindow = #False
    ; TODO Create_EXIT_WIND
    Create_EXIT_WIND(Title$, Parent_IdWin.i)
    DisableWindow(Parent_IdWin, #True)
    ; TODO SetGadgetText
    SetGadgetText(#GG_EXIT_WIND_Text_Title, Title$)
    SetGadgetText(#GG_EXIT_WIND_String_Title, SubTitle$)
    ; TODO Looping_EXIT_WIND
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case #exit_wind
              quitWindow = #True
          EndSelect
        Case #PB_Event_Gadget
          Select EventGadget()            
            Case #GG_EXIT_WIND_ButtonImage_YES
              quitWindow = #True : End
            Case #GG_EXIT_WIND_ButtonImage_NO
              quitWindow = #True
          EndSelect
      EndSelect
    Until quitWindow
    DisableWindow(Parent_IdWin, #False)
    CloseWindow(#exit_wind)
  EndProcedure
EndModule ;-> EndModule exit_win 

DeclareModule main_win
  ;- DeclareModule main_win
  Declare Create_MAIN_WIND()
  Declare Looping_MAIN_WIND()
EndDeclareModule ;-> EndDeclareModule main_win

Module main_win
  ;- Module main_win
  UseModule for_all
  UseModule exit_win
  Procedure.i Create_MAIN_WIND()
    OpenWindow(#main_wind, 0, 0, 500, 300, "MAIN WIND to exit", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
    ButtonGadget(#GG_MAIN_WIND_ButtonImage_Exit, 170, 245, 80, 45, "exit")
    HideWindow(#main_wind, #False)
    ProcedureReturn WindowID(#main_wind)
  EndProcedure

  Procedure Looping_MAIN_WIND()
    Define.i quitWindow = #False
    ; TODO Create_MAIN_WIND
    Create_MAIN_WIND()
    Repeat
      Select EventWindow()
        Case #main_wind
          Select WaitWindowEvent()
            Case #PB_Event_CloseWindow
              ;If MessageRequester("exit of MessageRequester", "do you want to exit all ?", #PB_MessageRequester_YesNo | #PB_MessageRequester_Warning | #MB_DEFBUTTON2) = #PB_MessageRequester_Yes
              ;quitWindow = #True : CloseWindow(#main_wind)
              ;EndIf
              Looping_EXIT_WIND("exit ?", "Do you want to exit all ?", #main_wind)
            Case #PB_Event_Gadget
              Select EventGadget()
                Case #GG_MAIN_WIND_ButtonImage_Exit
                  quitWindow = #True : CloseWindow(#main_wind)
              EndSelect
          EndSelect
      EndSelect
    Until quitWindow
  EndProcedure
EndModule ;-> EndModule main_win

UseModule main_win
Looping_MAIN_WIND()

Re: Customizing the "Exit message dialog box" and resulting in the error "window freezes, not responding"

Posted: Mon Jun 10, 2024 4:44 am
by Demivec
hoangdiemtinh wrote: Mon Jun 10, 2024 3:26 am I am new to PB. My primary language is not US/UK. I am using Google Translate.

I customized the program exit MessageBox and the result was the "window freeze, not responding".

The "window freezing" problem occurs when I press the X Button of the Exit Window.
and when I press the No Button of the Exit Window.

I put in the event: #PB_Event_CloseWindow.

Why ? Please help me.
The problem is due to the event loop in Looping_MAIN_WIND().

The main event loop first looks at the EventWindow() BEFORE :!: retrieving the event. This has some very impractical results. Because a new event has not been retrieved yet the event window is always from the event received in the last execution of loop.

As long as the loop hasn't executed and no event has been retrieved the value returned from EventWindow() is zero which, by luck, is the same as as the number of your main window. It then follows that an event is then actuality retrieved an acted on.

When the main window's X Button is pressed, the Looping_EXIT_WIND() is executed and uses its own event loop after disabling the main window. Note, this does not mean there are no events for the main window still waiting in the event queue.

The Exit window executes is event loop and really only takes one of two actions. It either exits by immediately ending the program or it closes the Exit window enables the main window and returns to the main event loop where the problem lies.

In the main event loop the value of EventWindow() is looked at BEFORE :!: retrieving a new event. Because a new event has not been retrieved yet the event window is from the last event retrieved in the exit window's event loop and results in no new event ever being retrieved and/or processed again from the event loop. This is because the main window's actual event loop is locked up under the window value Case #main_wind. Since a new event is never retrieved the event window remains as that of the Exit Window and your program freezes.

Code: Select all

 Procedure Looping_MAIN_WIND()
    Define.i quitWindow = #False
    ; TODO Create_MAIN_WIND
    Create_MAIN_WIND()
    Repeat
      Select EventWindow()  ;<<<<<<< problem here
        Case #main_wind
          Select WaitWindowEvent()    :<<<<<<<<<<<< problem here
            Case #PB_Event_CloseWindow
              ;If MessageRequester("exit of MessageRequester", "do you want to exit all ?", #PB_MessageRequester_YesNo | #PB_MessageRequester_Warning | #MB_DEFBUTTON2) = #PB_MessageRequester_Yes
              ;quitWindow = #True : CloseWindow(#main_wind)
              ;EndIf
              Looping_EXIT_WIND("exit ?", "Do you want to exit all ?", #main_wind)
            Case #PB_Event_Gadget
              Select EventGadget()
                Case #GG_MAIN_WIND_ButtonImage_Exit
                  quitWindow = #True : CloseWindow(#main_wind)
              EndSelect
          EndSelect
      EndSelect
    Until quitWindow
  EndProcedure
EndModule ;-> EndModule main_win
The solution is to retrieve an event before looking at any of the events attributes. Use WaitWindowEvent() or WindowEvent() before EventWindow(), EventGadget(), etc.

I recommend also combing the separate event loops into one. Once the detail level of the event window is determined you can segregate the events of the Exit Window into its own procedure if desired.

Re: Customizing the "Exit message dialog box" and resulting in the error "window freezes, not responding"

Posted: Mon Jun 10, 2024 8:17 am
by hoangdiemtinh
Demivec wrote: Mon Jun 10, 2024 4:44 am The solution is to retrieve an event before looking at any of the events attributes. Use WaitWindowEvent() or WindowEvent() before EventWindow(), EventGadget(), etc.

I recommend also combing the separate event loops into one. Once the detail level of the event window is determined you can segregate the events of the Exit Window into its own procedure if desired.
Thank you @Demivec.

I have revised the lines of code.

I give the lines of code located in WaitWindowEvent()
Then I collect #PB_Event_Gadget and #PB_Event_CloseWindow.
With #PB_Event_Gadget, I put 3 Push Button objects together.
With #PB_Event_CloseWindow, I modified it as follows:

Code: Select all

Select EventWindow()
    Case #main_wind
          Looping_EXIT_WIND("exit ?", "Do you want to exit all ?", #main_wind)
     Case #exit_wind
          DisableWindow(#main_wind, 0)
          CloseWindow(#exit_wind)
EndSelect