Announcement

Collapse
No announcement yet.

DIALOG END before DIALOG SHOW

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • DIALOG END before DIALOG SHOW

    I'm working on a function that is creating a dialog window with various controls. My code looks something like this:

    Code:
    DIALOG NEW ...  TO hDlg
    
    CONTROL ADD ...
    
    IF ISFALSE condition THEN 
       DIALOG END hDlg, 0
       EXIT FUNCTION
    END IF
    
    CONTROL ADD ...
    
    DIALOG SHOW MODAL hDlg ...
    The condition is testing for the presence of data for a combobox control that is being initialized. If no valid data exists for the control, I can abort the whole thing. Does this work (ie. DIALOG END after DIALOG NEW but before DIALOG SHOW) or do I need to do my checking before I create the dialog (before DIALOG NEW)?
    Bernard Ertl
    InterPlan Systems

  • #2
    I think doing the test first would be preferable.
    Charles Appel

    Comment


    • #3
      Either approach is fine, although I'd probably do the tests first. The SHOW is simply a vehicle for making the existing dialog visible, so you don't have to worry about executing it before you close the app with Dialog End.

      Your question did make me wonder what would happen if you did this instead:
      Code:
      Function PBMain() As Long
         Local hDlg As Dword
         Dialog New Pixels, 0, "PowerBASIC",300,300,200,200, %WS_OverlappedWindow To hDlg
         Exit Function
         Dialog Show Modal hDlg
      End Function
      ... with no Dialog End. The app disappears from Windows Task Manager this way but I don't know if the resources associated with the Dialog are cleared. I couldn't find in Help where it discusses that possibility.

      It may simply be that Windows closes the dialog when the app ends. Perhaps someone in the know can clarify.

      Comment


      • #4
        It may simply be that Windows closes the dialog when the app ends. Perhaps someone in the know can clarify
        When a process ends, Windows closes all handles (releasing all resources) owned by that process.

        I think your program would bring up a blank dialog which you could end with "X" or "Alt+F4" , causing DIALOG SHOW MODAL to return, at which point WinMain runs out of code to execute except for the ExitProcess() inserted by the compiler.

        The response to 'X' or "alt+F4" would be done by the default message processing inserted by the DDT engine.

        That DIALOG SHOW would return is a guess; the rest I know.

        MCM

        Comment


        • #5
          Hi MCM,
          I think your program would bring up a blank dialog...
          No, by test I can see that no visible dialog is shown. But your comment that ExitProcess() is provided by the compiler would seem to be the answer to the question I posed. I just can't find in Help where that is discussed to have known explicitly what the compiler does when PBMain() is exited.

          Comment


          • #6
            I just can't find in Help where that is discussed to have known explicitly what the compiler does when PBMain() is exited.
            You can't find it because it's not there. That's actually a very very small portion of all the stuff the compiler does 'under the hood' and does not document .... then again, that's why you pay real money to license a high-level language compiler, no?

            MCM

            Comment


            • #7
              FYI - I went ahead and added some preprocessing to check the condition before DIALOG NEW although it entails some extra database calls that I would rather avoid if possible for performance considerations.

              It's still a question that I would love to have answered definitively though.

              Does a dialog window get a message with WM_INITDIALOG from the DIALOG NEW statement or the DIALOG SHOW (MODAL)? Would it be possible for any WM_COMMAND/WM_DESTROY messages to be sent without the WM_INITDIALOG first?
              Bernard Ertl
              InterPlan Systems

              Comment


              • #8
                FYI - I went ahead and added some preprocessing to check the condition before DIALOG NEW although it entails some extra database calls that I would rather avoid if possible for performance considerations.
                Huh?

                I do not believe you have done your accounting correctly.

                If you HAD created the windows first, you would have then made the same database calls to determine if you had anything to list, right?

                And, for 'performance considerations'.... if there was nothing to list, then showing the window first you made all those "create the windows" calls for naught as well, and I don't see where you took even a little credit for that savings.

                Arithmetic not shown.

                Does a dialog window get a message with WM_INITDIALOG from the DIALOG NEW statement or the DIALOG SHOW (MODAL)? Would it be possible for any WM_COMMAND/WM_DESTROY messages to be sent without the WM_INITDIALOG first?
                The first part you can test yourself easily enough, but the answer is going to be it's the DIALOG SHOW call where WM_INITDIALOG occurs.

                On the second part, the answer is, "Not using the DDT engine you can't." DDT has a restriction not present in SDK methods that you may not use the DIALOG END statement when processing WM_INITDIALOG. (This is documented somewhere). Using SDK methods, either EndDialog() or DestroyWindow() may be used on WM_INITDIALOG without adverse effects. If using CreateWindowEx() to create your screen, you can simply return TRUE on the WM_CREATE notification to abort window creation.


                By the way, both the WM_COMMAND and WM_DESTROY notifications are sent by Windows in response to user actions; While either can be a byproduct of either user actions or program calls, they are not considered notification messages directly sent by program commands.

                MCM
                Last edited by Michael Mattias; 21 Sep 2015, 01:28 PM.

                Comment


                • #9
                  Originally posted by Michael Mattias View Post
                  Huh?

                  I do not believe you have done your accounting correctly.
                  That's the MCM I know and love.

                  Originally posted by Michael Mattias View Post
                  If you HAD created the windows first, you would have then made the same database calls to determine if you had anything to list, right?
                  No. I purposely kept the "code" in the OP stripped to the fundamental question. The "condition" involves a bit of work to resolve. My "pre-check" makes a less demanding call to the database to determine whether or not to proceed.

                  Originally posted by Michael Mattias View Post
                  ... it's the DIALOG SHOW call where WM_INITDIALOG occurs. ...
                  Thanks. I guess I'm wondering what happens when DIALOG END is called from outside the dialog's callback function before the WM_INITDIALOG message/handler fires. The code below appears to work, so it appears as if the DIALOG END is working, but I tried adding a global and setting it in a WM_DESTROY (and WM_SYSCOMMAND / SC_CLOSE) handler and it doesn't trip/fire. I'm not sure if that is indicative of anything or not though because the dialog window was never fully realized to begin with.

                  BTW - WM_COMMAND was a typo - I meant WM_SYSCOMMAND (with SC_CLOSE)

                  Code:
                  #PBFORMS Created
                  #COMPILE EXE
                  #DIM ALL
                  
                  '--------------------------------------------------------------------------------
                  '   ** Includes **
                  '--------------------------------------------------------------------------------
                  #PBFORMS Begin Includes
                  #IF NOT %DEF(%WINAPI)
                     #INCLUDE "WIN32API.INC"
                  #ENDIF
                  #PBFORMS End Includes
                  '--------------------------------------------------------------------------------
                  
                  '--------------------------------------------------------------------------------
                  '   ** Constants **
                  '--------------------------------------------------------------------------------
                  #PBFORMS Begin Constants
                  %IDD_DIALOG1   = 101
                  %IDC_BUTTON1   = 1001
                  #PBFORMS End Constants
                  '--------------------------------------------------------------------------------
                  
                  '--------------------------------------------------------------------------------
                  '   ** Declarations **
                  '--------------------------------------------------------------------------------
                  DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
                  DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                  #PBFORMS Declarations
                  '--------------------------------------------------------------------------------
                  
                  '--------------------------------------------------------------------------------
                  FUNCTION PBMAIN()
                     ShowDIALOG1 %HWND_DESKTOP
                     MSGBOX "all done"
                  END FUNCTION
                  '--------------------------------------------------------------------------------
                  
                  '--------------------------------------------------------------------------------
                  '   ** CallBacks **
                  '--------------------------------------------------------------------------------
                  CALLBACK FUNCTION ShowDIALOG1Proc()
                  
                     SELECT CASE CBMSG
                        CASE %WM_COMMAND
                           SELECT CASE CBCTL
                              CASE %IDC_BUTTON1
                                 IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                    MSGBOX "%IDC_BUTTON1=" + FORMAT$(%IDC_BUTTON1), _
                                       %MB_SYSTEMMODAL
                                 END IF
                  
                           END SELECT
                     END SELECT
                  
                  END FUNCTION
                  '--------------------------------------------------------------------------------
                  
                  '--------------------------------------------------------------------------------
                  '   ** Dialogs **
                  '--------------------------------------------------------------------------------
                  FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                     LOCAL lRslt AS LONG
                  #PBFORMS Begin Dialog %IDD_DIALOG1->->
                     LOCAL hDlg AS DWORD
                  
                  
                     DIALOG NEW hParent, "Dialog1", 251, 444, 195, 102, %WS_POPUP OR %WS_DLGFRAME _
                        OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_VISIBLE OR _
                        %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_WINDOWEDGE OR _
                        %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                     CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Button1", 45, 25, 95, 35
                  
                  #PBFORMS End Dialog
                     DIALOG END hDlg, 0
                     EXIT FUNCTION
                  
                     DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                  
                     FUNCTION = lRslt
                  END FUNCTION
                  '--------------------------------------------------------------------------------
                  Bernard Ertl
                  InterPlan Systems

                  Comment


                  • #10
                    as if the DIALOG END is working, but I tried adding a global and setting it in a WM_DESTROY (and WM_SYSCOMMAND / SC_CLOSE) handler and it doesn't trip/fire.
                    Of course it doesn't. WM_DESTROY is a notification message which results from a DIALOG END call. WM_DESTROY is the last message sent to a window before destruction is complete... which you should have read in your WinAPI documentation and if you had remembered it you wouldn't have even tried what you tried because you'd know it could not succeed.

                    Then again, the DDT engine (or you) may be short-circuiting something. Maybe if you did it SDK-style you could figure it out for certain. (code not shown)

                    My "pre-check" makes a less demanding call to the database to determine whether or not to proceed.
                    Good plan. Now you are thinking!

                    It for sure beats putting up a screen and then just exiting if "nothing do do."

                    Just FWIW.. users are used to programs taking a while to "do something" after clicking the desktop or start menu icon. You probably could have done the whole nine yards before starting on the screen creation and no one would have noticed.

                    Of course, you can always keep them interested by putting up a splash screen right away.

                    MCM

                    Comment


                    • #11
                      Explained in docs of DIALOG END and applied to your code.

                      This code will end dialog from %WM_INITDIALOG or a thread.

                      Note:
                      IF DIALOG SEND hDlg, %WM_SYSCOMMAND, %SC_CLOSE, 0,0 is used from a thread, respond to it in the callback or the dialog will keep running!
                      DIALOG POST hDlg, %WM_SYSCOMMAND, %SC_CLOSE, 0,0 may end correctly, but docs say to respond to the message.

                      It is easier to use DIALOG POST hDlg, %WM_USER + 999,0,0 for either %WM_INITDIALOG or from a thread.

                      Code:
                      #PBFORMS CREATED V2.01
                      #COMPILE EXE
                      #DIM ALL
                      GLOBAL gMustEnd AS LONG 'If you want to end in %WM_INITDIALOG
                      #PBFORMS BEGIN INCLUDES
                      #INCLUDE ONCE "WIN32API.INC"
                      #PBFORMS END INCLUDES
                      #PBFORMS BEGIN CONSTANTS
                      %IDC_BUTTON1 = 1001
                      #PBFORMS END CONSTANTS
                      DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
                      DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                      #PBFORMS DECLARATIONS
                       
                      FUNCTION PBMAIN()
                        gMustEnd = 0 'change to 1 to end in %WM_INITDIALOG
                        ShowDIALOG1 %HWND_DESKTOP
                        MSGBOX "all done",,"End program"
                      END FUNCTION
                       
                      CALLBACK FUNCTION ShowDIALOG1Proc()
                          SELECT CASE CB.MSG
                            CASE %WM_INITDIALOG
                              IF gMustEnd THEN DIALOG POST CB.HNDL, %WM_USER+999,0,0
                            CASE %WM_COMMAND
                               SELECT CASE CB.CTL
                                  CASE %IDC_BUTTON1
                                     IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                        LOCAL hThread AS LONG
                                        THREAD CREATE MyThreadFUNCTION(CB.HNDL) TO hThread
                                        THREAD CLOSE hThread TO hThread
                                     END IF
                                END SELECT
                            CASE %WM_USER + 999
                              DIALOG END CB.HNDL
                              FUNCTION = 1
                         END SELECT
                       END FUNCTION
                       
                      FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                         LOCAL lRslt AS LONG
                      #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
                        LOCAL hDlg  AS DWORD
                         DIALOG NEW hParent, "Dialog1", 801, 161, 195, 102, %WS_POPUP OR _
                          %WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                          %WS_VISIBLE OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
                          %WS_EX_WINDOWEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
                          %WS_EX_RIGHTSCROLLBAR, TO hDlg
                        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Create thread", 45, 25, 95, 35
                      #PBFORMS END DIALOG
                         DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                       #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
                      #PBFORMS END CLEANUP
                          FUNCTION = lRslt
                      END FUNCTION
                       
                      THREAD FUNCTION MyThreadFunction(BYVAL hDlg AS DWORD) AS LONG
                        ? "Click to post message",,"Thread running"
                        DIALOG POST hDlg, %WM_USER+999,0,0
                      END FUNCTION
                      https://www.tesla.com/roadster

                      Comment


                      • #12
                        Instead of WM_SYSCOMMAND or a WM_USER message, you could use WM_CLOSE, which has a default processing provided by Windows.

                        I don't know enough about DDT to know if you have to issue a 'DIALOG END' statement but ISTR WM_CLOSE is handled cleanly with or without it.

                        WM_CLOSE is the 'conventional' notification for "user wants to end this screen so this is a good place to see if that is going to be allowed now" and preempt the requested user action if application conditions are not right.

                        Also FWIW, any references to "threads" here are immaterial. Messages posted or sent to any window ("hDlg") are always processed in the context of the thread which owns the window, with Windows handling the thread switch if necessary.
                        Last edited by Michael Mattias; 22 Sep 2015, 10:00 AM.

                        Comment


                        • #13
                          Getting back directly on point..

                          >DIALOG END before DIALOG SHOW

                          Seems to me the best way to not require some One Universal Truth About This Circumstance is, "Don't do that."

                          Comment


                          • #14
                            Originally posted by Michael Mattias View Post
                            Getting back directly on point..

                            >DIALOG END before DIALOG SHOW

                            Seems to me the best way to not require some One Universal Truth About This Circumstance is, "Don't do that."
                            Why even create the dialog if you aren't going to use it?
                            I'd place the test before the whole dialog creation code block.
                            The world is strange and wonderful.*
                            I reserve the right to be horrifically wrong.
                            Please maintain a safe following distance.
                            *wonderful sold separately.

                            Comment


                            • #15
                              Seconded.
                              I also wondered why the dialog was created if it wasn't going to be used.
                              I can see ending it from a thread, but not sure why it would be ended in
                              the %WM_INITDIALOG or before DIALOG SHOW.
                              https://www.tesla.com/roadster

                              Comment


                              • #16
                                Originally posted by Kurt Kuzba View Post
                                Why even create the dialog if you aren't going to use it?
                                I'd place the test before the whole dialog creation code block.
                                User clicks a button wanting program to do X.

                                App creates dialog to do X, but needs to process some data from the database while creating dialog. During this processing, it's determined that doing X is not possible, so dialog is aborted.

                                As stated already, I have added a "pre-check" to ensure that doing X is possible before dialog creation. It adds extra database calls and processing when doing X is possible, but that is apparently the price that needs to be paid to ensure that the dialog is handled correctly.
                                Bernard Ertl
                                InterPlan Systems

                                Comment


                                • #17
                                  What I would probably actually do is create the dialog, then beg patience of the user while checking if there is anything to do...

                                  Code:
                                  %PWM_INIT_COMPLETE  =  %WM_USER + 1&
                                  
                                  CALLBACK FUNCTION dlgProc 
                                     Case msg (CB.MSG?) 
                                  
                                             CASE %WM_INITIDIALOG
                                                  DIALOG POST CB.HNDL, %PWM_INIT_COMPLETE, %NULL, %NULL
                                  
                                               CASE %PWM_INIT_COMPLETE  ' dialog will be showing when processed
                                                    CONTROL SET TEXT CB.HDNL, %ID_USER_MESSAGE, "Checking to see if anything to do..." 
                                                    bStuffToDo = CheckIfStuffToDo ( params) 
                                                    IF ISTRUE  bSTuffToDo THEN 
                                                         sTxt = "loading your screen"
                                                    ELSE
                                                         sTxt =   "Nothing to do!"
                                                    END IF 
                                                    CONTROL SET TEXT  CB.HNDL, %ID_USER_MESSAGE, sTxt
                                                    IF ISTRUE bStuffToDo THEN
                                                          CALL LoadUpControls (CB.HNDL, other params) 
                                                    ELSE
                                                          Beep or sound 
                                                          Delay a short time so user can read his message
                                                          DIALOG END 
                                                    END IF
                                  Something like that, anyway ... the user ALWAYS sees the screen, regardless if there is anything to do or not. I like that kind of consistency. YMMV.

                                  MCM

                                  Comment


                                  • #18
                                    I haven't been able to find any info on it, but since I switched from DOS, I've been operating with the idea that "DIALOG NEW" is just an "in-memory specification", and that the new dialog is not actually created until the DIALOG SHOW...

                                    I have no idea where I got that from, and now I'm wondering if it's at all correct.

                                    But that's the way I've thought of it, and treated it.

                                    I have not seen any negative effect from "bugging out" of a SUB or FUNCTION in which a DIALOG NEW was performed, and not a DIALOG SHOW...

                                    -John

                                    Comment


                                    • #19
                                      Hi John,
                                      The Dialog New does create the dialog. It's just not visible until you use "SHOW" to make it visible.

                                      Comment


                                      • #20
                                        The Dialog New does create the dialog. It's just not visible until you use "SHOW" to make it visible.
                                        I'm not so sure about that.

                                        test code:
                                        Code:
                                           DIALOG NEW      .... To hDLG 
                                           MSGBOX   "hDlg is "  & IIF$ (IsFalse (isWindow(hDlg)), "NOT", "") & " a window   
                                        
                                           DIALOG SHOW..
                                        If the dialog were created, you'd have to process WM_INITDIALOG before the MSGBOX in MAIN() shows up.

                                        Also, the functions used by the compiler are CreateDialogIndirectParam and DialogBoxIndirectParam, DialogBox is used for MODAL and CreateDialog is used for modeless... so how could the compiler know which one to use, unless it does some klind of "lookahead"... which would be impossible if either method is possible in code...

                                        Code:
                                            DIALOG NEW ...  
                                        
                                            CALL  howToShow() TO bShowModal 
                                        
                                            IF ISTRUE bShowModal THEN 
                                                   DIALOG SHOW MODAL .. 
                                            ELSE 
                                                   DIALOG SHOW MODELESS
                                                   DO 
                                                        DIALOG DOEVENTS 
                                                   LOOP
                                            END IF
                                        Not that it is all that significant. The point I was trying to make is, never do something (DIALOG NEW) when you may have to cancel it so it does not happen.

                                        MCM
                                        Last edited by Michael Mattias; 23 Sep 2015, 02:40 PM. Reason: quote cite

                                        Comment

                                        Working...
                                        X