Announcement

Collapse
No announcement yet.

How to 'END'?

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

  • How to 'END'?

    Hi

    Just a quick question..

    I'm wondering what the equivilent END function is in PB, from VB.

    I have a Dialog, receiving window messages mainly for a TCP server socket.
    The dialog is started Modeless, and a Doevents Loop keeps its message queue
    running.

    From ANY sub/function, how can i completely and cleaning unload my program?

    Thanks very much.

    - Nathan.

  • #2
    Nathan,

    change your message pump to this:

    Code:
    DO
            DIALOG DOEVENTS TO Count&
    LOOP UNTIL Count&=0
    ------------------
    -Greg
    -Greg
    [email protected]
    MCP,MCSA,MCSE,MCSD

    Comment


    • #3
      Greg,

      Done that.

      But when i call DIALOG END hDlg, the program still does not end.



      - Nathan

      ------------------


      [This message has been edited by Nathan Evans (edited July 02, 2001).]

      Comment


      • #4
        You should be able to end it from within the dialog's Callback
        Function. If you do it within the Main function, the program
        won't "see" it, because it'll still be in the message (DOEVENTS)
        loop.


        ------------------
        Clay C. Clear

        http://www.v3space.com/a/a39/202/

        [email protected]
        [email protected]

        Comment


        • #5
          I'm calling the 'DIALOG END hDlg' from within the window message handler
          callback..




          -Nath.

          ------------------

          Comment


          • #6
            Make sure that your "hDlg" is declared as GLOBAL. Remember,
            variables are local to a sub/function unless declared otherwise.
            In other words, if you're not declaring hDlg as GLOBAL, as far
            as your message processor function is concerned, it's
            terminating a nonexistent dialog.

            Also, try putting

            FUNCTION = 1

            after terminating the dialog in the callback function.

            G'luck!


            ------------------
            Clay C. Clear

            http://www.v3space.com/a/a39/202/

            [email protected]
            [email protected]

            Comment


            • #7
              Nathan --
              Probably, you will find some ideas in this code (I cut a fragment from one "SetDateTime" utility).
              Modeless dialog. You can cancel it by Alt-F4.

              Code:
                 #Compile Exe
                 #Register None
                 #Dim All
                 #Include "WIN32API.INC"
                 %ID_DIRECTORY = 101
                 %ID_FILE = 102
              
                 Global Stopped As Long
                 
                 Sub DoQueryEvents(hDlg As Long)
                    Dim Msg As tagMsg
                    While PeekMessage(Msg, %NULL, %NULL, %NULL, %PM_REMOVE)
                        If IsDialogMessage(hDlg, Msg) Then
                        Else
                           TranslateMessage Msg
                           DispatchMessage Msg
                        End If
                    Wend
                 End Sub
              
                 CallBack Function DlgProc
                    Select Case CbMsg
                       Case %WM_INITDIALOG
                          Control Add TextBox, CbHndl, %ID_DIRECTORY, "", 10, 15, 230, 12
                          Control Add TextBox, CbHndl, %ID_FILE, "", 10, 30, 230, 12
                       Case %WM_DESTROY
                          Incr Stopped
                    End Select
                 End Function
              
                 Function PbMain
                    Dim hDlg As Long
                    Dialog New 0, "", , , 270, 70, %WS_CAPTION Or %WS_SYSMENU Or %WS_MINIMIZEBOX, _
                       %WS_EX_TOPMOST To hDlg
                    Dialog Show Modeless hDlg Call DlgProc
               
                    Local hDir As Long, nSubDir As Long, maxSubDir As Long
                    Local lpFindFileData As WIN32_FIND_DATA
                    Local azDirectory As Asciiz * %MAX_PATH
                    Local lpSystemTime As SYSTEMTIME
                    
                    azDirectory = "C:\"
                    nSubDir = 1
                    maxSubDir = 1000: ReDim azSubDir (0 To maxSubDir) As Asciiz * %MAX_PATH
                    Do
                       If nSubDir = 0 Then Incr Stopped: Exit Do
                       azSubDir(0) = azSubDir(nSubDir)
                       If Stopped Then Exit Do
                       Control Set Text hDlg, %ID_DIRECTORY, azDirectory + azSubDir(0)
                       DoQueryEvents hDlg
                       hDir = FindFirstFile(azDirectory + azSubDir(0) + "\*.*", lpFindFileData)
                       Decr nSubDir
                       If hDir <> %INVALID_HANDLE_VALUE Then
                          Do
                             If (lpFindFileData.dwFileAttributes And %FILE_ATTRIBUTE_DIRECTORY) Then
                                If Asc(lpFindFileData.cFilename) <> 46 Then ' . ..
                                   If nSubDir >= maxSubDir Then
                                      maxSubDir = maxSubDir * 2
                                      ReDim Preserve aSubDir (0 To maxSubDir) As Asciiz * %MAX_PATH
                                   End If
                                   Incr nSubDir
                                   azSubDir(nSubDir) = azSubDir(0) + "\" + lpFindFileData.cFilename
                                End If
                              Else
                                 Control Set Text hDlg, %ID_FILE, lpFindFileData.cFilename
                                 DoQueryEvents hDlg
                             End If
                             If Stopped Then Exit Do
                          Loop While FindNextFile(hDir, lpFindFileData)
                          FindClose hDir
                      End If
                    Loop
                    
                    PostMessage hDlg, %WM_SYSCOMMAND, %SC_CLOSE, 0
                    Do
                       If IsWindow(hDlg) Then DoQueryEvents hDlg Else Exit Do
                    Loop
                    If Stopped = 1 Then MsgBox "Canceled", %MB_TASKMODAL Else MsgBox "End of Job", %MB_TASKMODAL
              
                 End Function
              PS. Forgot to mention - change azDirectory = "C:\", if necessary.
              ------------------
              E-MAIL: [email protected]

              [This message has been edited by Semen Matusovski (edited July 02, 2001).]

              Comment


              • #8
                I've got it working

                I have declared a variable global to my whole program, called bClose AS LONG.

                Now all i have to do, in any procedure, is set bClose to 1.

                I've adapted my DoEvents Loop to detect this... Now, it will only run a
                DoEvents if bClose = 0 and there is a Dialog to actually run a DoEvents on.

                Pretty study code, no ?

                Code:
                    DO
                        DIALOG DOEVENTS TO x
                    LOOP WHILE bClose = 0 AND x

                Thanks for your help people


                - Nathan.

                Comment


                • #9
                  If your app is designed correctly, that sort of solution should be unnecessary. I've written a *LOT* of DDT code and I've *NEVER* needed such a solution.

                  There are a couple of minor "rules" for DIALOG END that you should be aware of:
                  1. DIALOG END only works within the thread that owns the dialog.
                  2. DIALOG END should not be used from within %WM_INITDIALOG.

                  Next, since you are apparently using DIALOG END hDlg in the callback, maybe you need to use DIALOG END CBHNDL to ensure hDlg contains the correct dialog handle.

                  Finally, you maay want to post the code thaat you used (before you added the "bClose" cop-out) so we can check out why you are having problems.


                  ------------------
                  Lance
                  PowerBASIC Support
                  mailto:[email protected][email protected]sic.com</A>
                  Lance
                  mailto:[email protected]

                  Comment


                  • #10
                    Here is the code i was using before i added the bClose

                    Code:
                    CALLBACK FUNCTION DlgProc
                    
                       LOCAL sInBuffer AS STRING
                    
                       SELECT CASE CBMSG
                    
                          CASE %WM_INITDIALOG
                             hSock = FREEFILE
                             TCP OPEN SERVER PORT 400 AS hSock TIMEOUT 90
                                IF ERR THEN
                                   MSGBOX "Couldn't create socket."
                    
                                   DIALOG END CBHNDL
                                ELSE
                                   TCP NOTIFY hSock, ACCEPT TO CBHNDL AS %TCP_CONNECT
                                END IF
                             FUNCTION = 1
                             PostMessage CBHNDL, %WM_USER + 999&, 0, 0
                    
                          CASE %WM_USER + 999&
                             ShowWindow CBHNDL, %SW_HIDE
                    
                          CASE %TCP_CONNECT
                                SELECT CASE LOWRD(CBLPARAM)
                    
                                    CASE %FD_ACCEPT
                                    TCP ACCEPT hSock AS gSock
                                     TCP NOTIFY gSock, RECV CLOSE TO CBHNDL AS %TCP_CONNECT
                                      FUNCTION = 1
                    
                                    CASE %FD_READ
                                    TCP RECV gSock, 1024, sInBuffer
                                     CALL RunCommand(BYVAL sInBuffer)
                                      FUNCTION = 1
                    
                                    CASE %FD_CLOSE
                                    TCP CLOSE gSock
                                      FUNCTION = 1
                                 END SELECT
                                 FUNCTION = 1
                    
                          CASE %WM_DESTROY
                           TCP CLOSE gSock
                           FUNCTION = 1
                    
                       END SELECT
                    
                    END FUNCTION
                    The line i highlighted, is a Sub procedure, in that some procedure
                    is a Select Case, if the sInBuffer = "4" it will attempt to DIALOG END hDlg..

                    I will try using DIALOG END CBHNDL, and see if that works

                    Once i've got this sorted, i'll register my own window messages
                    for the winsock messages.


                    -Nathan

                    Comment


                    • #11
                      Lance,

                      I've figured it

                      Code:
                            CASE %WM_DESTROY
                             TCP CLOSE gSock
                             FUNCTION = 0
                      All i had to do was set return value for the Messageproc to 0 in the %WM_DESTROY
                      case. Now i can call DIALOG END hDlg from anywhere, and the program will properly unload.

                      Can you confirm that this really was the problem? thanks.

                      BTW: I've now removed the GLOBAL declaration for hDlg.. and from the WindowProc, i pass
                      the CBHNDL (byval) to the sub so it has the window handle, if it needs to close the program.



                      -Nathan.



                      [This message has been edited by Nathan Evans (edited July 03, 2001).]

                      Comment


                      • #12
                        Hmmm... I can't recall seeing this behavior with %WM_DESTROY with DDT before.

                        Can you please email the code (in compilable form) to me so I can investigate further? Thanks!


                        ------------------
                        Lance
                        PowerBASIC Support
                        mailto:[email protected][email protected]</A>
                        Lance
                        mailto:[email protected]

                        Comment


                        • #13
                          Lance,

                          Check your email

                          ------------------

                          Comment


                          • #14
                            Ummmm, Nathan and Lance, i hate to be iconoclastic, but I still
                            think the EASIEST way to terminate a dialog or program that is
                            based on a dialog callback is to simply declare the hDlg as a
                            GLOBAL. All that needs is the one line of code declaring that,
                            and the dialog can then be ENDed from within the main function
                            OR the callback function. I've used both (ENDed in the main
                            function with MODELESS dialogs, and in the callback function for
                            MODAL dialogs), with no problems. Depending on the structure of
                            your code, ENDing the dialog in such a fashion should also
                            be able to terminate the program. At least *I* haven't had any
                            problems with that approach.

                            However, I'm glad for the postings in this topic, because y'all
                            have shown me a better way to process my DOEVENTS loop. Up
                            until I saw the code, I was using:

                            'CREATE MODELESS DIALOG HERE, HIDE IT
                            Code:
                            START:
                            IF ISFALSE Flag1 THEN
                            DIALOG DOEVENTS
                            ELSE
                            DIALOG END hDlg
                            EXIT FUNCTION
                            END IF
                            GOTO START
                            END FUNCTION
                            Note that Flag1 is DIMmed as a GLOBAL LONG in my custom .INC
                            file. It is set to TRUE by the %WM_COMMAND that is designated
                            to terminate the dialog/program, within the callback.

                            Pretty sloppy, huh? <grin>

                            Yup, I got a LOT of learning to do.



                            ------------------
                            Clay C. Clear

                            http://www.v3space.com/a/a39/202/

                            [email protected]
                            [email protected]

                            Comment


                            • #15
                              Clay,

                              I used the same principle at first.. but Lance said it is not the correct
                              way to go about doing that. I've emailed him my code so hopefully
                              he'll verify that the currently method im using is working.

                              -Nath.

                              Comment


                              • #16
                                What's INcorrect about it??? I know it's not TRADITIONAL, but it
                                works FINE! There are, many times, more than one way to
                                accomplish a programming objective.

                                However, I'm not brushing you and Lance off. I'm going to be
                                recoding all of my programs (even though they work FINE, as is)
                                so they use INI files, as recommended by Mr. Scott Turchin. I
                                was looking at recoding them so they use the Registry, but Scott
                                raised a good point or two about INI files. It doesn't really
                                matter to me which way to go, so I'll "go with the flow" on
                                that particular matter. Anyway, my point is that I'm going to
                                use in my programs some of the techniques that Lance has
                                spoken of in various postings in the Forums. I'll DEFINITELY be
                                using the DIALOG DOEVENTS as posted in this topic, BUT, I'm
                                going to use my own "iconoclastic" method of terminating the
                                dialogs/programs. Like I said, my technique works FINE, and it's
                                never caused my programs to "bomb", or GPF, or anything. I also
                                think my method MIGHT require fewer lines of coding than the
                                "traditional" methods. I don't know that for a fact, though, as
                                I've never looked into the more standard techniques.

                                I'm not trying to pick an argument with you and Lance, just
                                wanted to share my opinion that there's "more than one way to
                                skin a cat." Unless you or Lance have an argument, preferably
                                with sample code, that illustrates the benefits of the
                                standard approach(es)? After I post this reply, I'm going to
                                re-read all the postings in this topic. I've been up all night
                                coding, and I'm tired enough to have missed a vital message that
                                would compel me to change my viewpoint. I am openminded about
                                programming, and will change my ways, if I agree with the
                                arguments of the other Members. That means that I usually do
                                change my ways, as I am fully aware of my relative inexperience.


                                Anyway, I apologize for mty rambling reply.

                                I do have one final question, for you or Lance:

                                under what code circumstances would a %WM_DESTROY be required?
                                I have NEVER used that windows message, never needed it, so I
                                assume that it's only used in certain cases? Or is it something
                                that SHOULD be used when working with dialogs? I can research
                                it, if you'd like, but I'm just hoping for a "down-and-dirty"
                                definitive answer. If it's an important function of dialogs,
                                then I'll start using it.


                                ------------------
                                Clay C. Clear

                                http://www.v3space.com/a/a39/202/

                                [email protected]
                                [email protected]

                                Comment


                                • #17
                                  Firstly, by using CBHNDL (and passing it as a parameter to other subs/functions as required), you reduce the GLOBAL variable count by one; your code is more clear/concise (and possibly more reusable); and it makes it easier to ensure the code is dealing with a valid handle at all times. If a GLOBAL works for you - great. If you dislike GLOBALs, then pass parameters and use CBHNDL.

                                  %WM_DESTROY is very useful for cleaning up after your window/dialog just as it is about to be destroyed.

                                  For example, if you subclassed the window/dialog, restoring the subclass is usually done during %WM_DESTROY.

                                  More examples: on a SDI app, %WM_DESTROY may be used to deallocate memory, close open files, delete critical sections, updte INI files, etc. Basically, a whole range of user-defined practices can be installed in the %WM_DESTROY handler.

                                  ------------------
                                  Lance
                                  PowerBASIC Support
                                  mailto:[email protected][email protected]</A>
                                  Lance
                                  mailto:[email protected]

                                  Comment


                                  • #18
                                    Lance,

                                    Great! So i've coded it the right way at last

                                    BTW: Is there any reason why my app should be using 3 threads?
                                    Task Manager reports ~100 handles, and 3 threads.. That's fine with me...
                                    but it would be nice to know what they're being used on.

                                    -Nath

                                    [This message has been edited by Nathan Evans (edited July 04, 2001).]

                                    Comment

                                    Working...
                                    X