Announcement

Collapse
No announcement yet.

Problem returning string from callback

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

  • Problem returning string from callback

    The code below demonstrates a problem I'm having showing a dialog box's title bar. The title should be blank, but instead, is three extraneous characters. I believe the problem is associated with the myInput routine returning the specified string from its callback function. The problem goes away if I just change the routine from a function to a sub and use a global string for the specified one.

    I would like to keep myInput as a function if possible, and to understand why it is incorrect. I sure would appreciate some feedback on this. I have been using this replacement for PowerBasic's input function for some time, not knowing there was a problem with it.

    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "WIN32API.INC"
    
    %IDC_myInput = 1000
    
    FUNCTION myInput(OPT BYVAL prompt AS STRING, BYVAL ti AS STRING) AS STRING
       LOCAL hInput, nStyle AS LONG
       LOCAL s AS STRING, ps AS STRING PTR
       nStyle = %WS_CAPTION OR %WS_POPUP OR %WS_SYSMENU OR %DS_MODALFRAME 
       DIALOG NEW 0, ti, , , 130, 85, nStyle TO hInput
       CONTROL ADD LABEL, hInput, -1, prompt, 5, 5, 80, 12
       CONTROL ADD TEXTBOX, hInput, %IDC_myInput, "test", 10, 20, 100, 12
       CONTROL ADD BUTTON, hInput, %IDOK, "Ok", 60, 40, 50, 20 
       ps = STRPTR(s): DIALOG SET USER hInput, 1, ps
       DIALOG SHOW MODAL hInput, CALL myInputProc
       FUNCTION = @ps
    END FUNCTION 
    
    CALLBACK FUNCTION myInputProc()
       LOCAL ps AS STRING PTR
       IF CBMSG = %WM_COMMAND AND (CBCTL = %IDOK OR CBCTL = %IDCANCEL) THEN 
          DIALOG GET USER CBHNDL, 1 TO ps
          IF CBCTL = %IDOK THEN CONTROL GET TEXT CBHNDL, %IDC_myInput TO @ps
          DIALOG END CBHNDL
       END IF 
    END FUNCTION 
    
    %IDC_Problem =  100
    GLOBAL hDlg AS LONG
    GLOBAL findStr AS STRING
    GLOBAL thisFile AS STRING
    DECLARE SUB showProb()
    
    FUNCTION PBMAIN()
       DIALOG NEW 0, "Test Window Title", , , 200, 200, %WS_SYSMENU OR %WS_MINIMIZEBOX TO hDlg
       CONTROL ADD BUTTON,  hDlg, %IDC_Problem, "&Show Problem", 50, 50, 70, 40
       DIALOG SHOW MODAL hDlg, CALL dlgProc
    END FUNCTION
    
    CALLBACK FUNCTION dlgProc()
       SELECT CASE AS LONG CBMSG
          CASE %WM_COMMAND
             SELECT CASE CBCTL
                CASE %IDC_Problem
                   IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                      findStr = myInput("Search for: ")
                      IF LEN(findStr) THEN thisFile = "": showProb
                   END IF 
             END SELECT
       END SELECT   
    END FUNCTION
    
    SUB showProb()
       LOCAL nStyle, hProbDlg AS LONG
       DIALOG NEW hDlg, "", 20, 10, 200, 150, %WS_SYSMENU TO hProbDlg
       DIALOG SHOW MODAL hProbDlg, CALL ShowNoteProc
    END SUB
    
    CALLBACK FUNCTION showNoteProc()
       SELECT CASE CBMSG
          CASE %WM_INITDIALOG
             DIALOG SET TEXT CBHNDL, thisFile
       END SELECT
    END FUNCTION

  • #2
    Hi Charles,
    you problem come from mixing asciiz pointer with string pointer

    Code:
     LOCAL s  AS STRING
     s = "string"
     
     LOCAL ps AS STRING POINTER
     ps = STRPTR(s)
     
     LOCAL pz AS ASCIIZ POINTER
     pz = STRPTR(s)
     
     MSGBOX @ps 'Kaboom, "@" is for ASCIIZ and ps is declared as a STRING POINTER
                'The compiler won't like this.
     
     @ps = "chain" 'Same problem, "@" is for ASCIIZ and ps is declared as a STRING POINTER
     
     MSGBOX @pz 'This will work if there is no "zero" embedded in string, like in multi-sz...
     
     @pz = "longer string" 'If this string is longer than the original one then you will
                           'corrupt memory becose the original string is only 5 characters long
                           'and you try to write past the end
    In your code you may use ASCIIZ instead of string by...

    Code:
    replacing LOCAL s AS STRING, ps AS STRING PTR
    with      LOCAL s AS ASCIIZ * %MAX_PATH, ps AS ASCIIZ PTR
     
    replacing ps = STRPTR(s): DIALOG SET USER hInput, 1, ps
    with      ps = VARPTR(s): DIALOG SET USER hInput, 1, ps
    Last edited by Pierre Bellisle; 28 Jan 2008, 10:06 PM.

    Comment


    • #3
      Thanks for your reply, Pierre. There still seems to be something wrong. Insert the following msgbox in the dlgProc() callback function, and you will see that myInput returns a string of length 3 instead of 4.

      Code:
            findStr = myInput("Search for: ")
            MSGBOX STR$(LEN(findStr)) + ", " + findStr

      Comment


      • #4
        Hi Charles,

        I've had a quick look through your code and it seems to me that your problem lies in this line in myInput:
        Code:
        ps = STRPTR(s): DIALOG SET USER hInput, 1, ps
        because I think it should be this instead:
        Code:
        ps = VARPTR(s): DIALOG SET USER hInput, 1, ps
        The reason is, you have ps declared as a STRING PTR, so you need to point it at a STRING. VARPTR(s) is the address of the STRING. STRPTR(s) is the address of the contents of the STRING - effectively an ASCIIZ buffer. So, point your pointer at the STRING and all should be well.



        Regards,

        Pete.

        Comment


        • #5
          Yes, Peter... I think you're exactly right. And thanks for the explanation as well.
          I have made this mistake before, getting STRPTR and VARPTR backward. Maybe someday I'll learn. Thanks again.

          Comment


          • #6
            And Pierre, your way works also if I replace 'LOCAL ps AS ASCIIZ PTR' in myInputProc() as well. I guess that should have been obvious, but I missed it. Thanks again.

            Comment

            Working...
            X