Announcement

Collapse
No announcement yet.

PB9 - Listview - Lv_Keydown - Heap Problem

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

  • PB9 - Listview - Lv_Keydown - Heap Problem

    Hi everyone

    I run into a problem with my callback function for the listview control.

    I want the user to select an item either with cursor up/down or the mouse and then accept the selection with double click or spacebar. After that, the selection is processed in another sub.

    Selection part works ok (thanks, MCM). So does the DBLCLK. But when I close the dialog in the %LVN_KEYDOWN-Part, i get the following message in the output window

    HEAP: Free Heap block 1a48bf0 modified at 1a48cc0 after it was freed<0A>

    I'm quite certain it must be something with the pointer, but this is fairly new stuff for me.

    Code:
    CALLBACK FUNCTION cbLv AS LONG
        LOCAL pNMLV  AS NM_LISTVIEW PTR
        LOCAL kb     AS LV_KEYDOWN PTR
    
            pNMLV = CB.LPARAM
            kb    = CB.LPARAM
    
            SELECT CASE @pNMLV.hdr.code
                CASE %LVN_ITEMCHANGED
                    IF ISTRUE @pNMLV.uCHANGED AND ISTRUE %LVIS_SELECTED THEN
                        IF ISTRUE (@pNMLV.uNewState AND %LVIS_SELECTED) THEN
                            IF @pNMLV.iItem > -1 THEN
                                LISTVIEW GET TEXT CB.HNDL, %IDC_Listview, @pNMLV.iItem+1, 1 TO strSel
                                FUNCTION = 1
                            END IF
                        END IF
                    END IF
                CASE %NM_DBLCLK
                    MSGBOX strSel
                    DIALOG END hdlg
                    FUNCTION = 1
                CASE %LVN_KEYDOWN
                    SELECT CASE @kb.wVKEY
                        CASE %vk_space
                           MSGBOX strSel
                           DIALOG END hdlg
                           FUNCTION = 1
                    END SELECT
            END SELECT
    END FUNCTION
    This occurs only when debugging, not when running the compiled version - but i'm sure the problem exists there as well.

    Best regards,
    Markus
    Last edited by Markus Saegesser; 8 Jan 2009, 04:21 PM.

  • #2
    You are closing the DIALOG hDlg here but you only show code for the control callback. Is it possible that the dialog's WM_DESTROY handler is doing something untoward, or even something after the dialog is closed?

    Comment


    • #3
      I don't hope so. At least it doesn't do anything i've written -there's no dialog callback in my code.

      Comment


      • #4
        oh. How about showing compileable code?

        Comment


        • #5
          Here we go - that's the stripped down version i'm trying my luck with atm.

          Code:
          #COMPILE EXE
          #DIM ALL
          '------------------------------------------------------------------------------
          '   Verhindert zuviel Ballast aus den CommCtrl.inc (wird benötigt für Listview-Callbacks)
          '------------------------------------------------------------------------------
              %NOANIMATE         = 1  ' Animate control
              %NOBUTTON          = 1  ' Button
              %NOCOMBO           = 1  ' Combo box
              %NOCOMBOEX         = 1  ' ComboBoxEx
              %NODATETIMEPICK    = 1  ' Date/time picker
              %NODRAGLIST        = 1  ' Drag list control
              %NOEDIT            = 1  ' Edit control
              %NOFLATSBAPIS      = 1  ' Flat scroll bar
              %NOHEADER          = 1  ' Header control
              %NOHOTKEY          = 1  ' HotKey control
              %NOIMAGELIST       = 1  ' Image APIs
              %NOIPADDRESS       = 1  ' IP Address edit control
              %NOLIST            = 1  ' List box control
              %NOMENUHELP        = 1  ' Menu help
              %NOMONTHCAL        = 1  ' MonthCal
              %NOMUI             = 1  ' MUI
              %NONATIVEFONTCTL   = 1  ' Native Font control
              %NOPAGESCROLLER    = 1  ' Pager
              %NOPROGRESS        = 1  ' Progress control
              %NOREBAR           = 1  ' Rebar control
              %NOSTATUSBAR       = 1  ' Status bar
              %NOSYSLINK         = 1  ' SysLink
              %NOTABCONTROL      = 1  ' Tab control
              %NOTOOLBAR         = 1  ' Tool bar
              %NOTOOLTIPS        = 1  ' Tool tips
              %NOTRACKBAR        = 1  ' Track bar
              %NOTRACKMOUSEEVENT = 1  ' Track Mouse Event
              %NOTREEVIEW        = 1  ' TreeView
              %NOUPDOWN          = 1  ' Up Down arrow control
          
          '------------------------------------------------------------------------------
          '   ** Includes **
          '------------------------------------------------------------------------------
          #INCLUDE "WIN32API.INC"
          #INCLUDE "CommCtrl.inc"
          '------------------------------------------------------------------------------
          '------------------------------------------------------------------------------
          '   ** Constants **
          '------------------------------------------------------------------------------
          %IDC_LABEL1   = 1001
          %IDC_LISTVIEW = 1003
          %IDC_BUTTON1  = 1004
          '------------------------------------------------------------------------------
          '------------------------------------------------------------------------------
          '   ** Declarations **
          '------------------------------------------------------------------------------
          '------------------------------------------------------------------------------
          '------------------------------------------------------------------------------
          GLOBAL hDlg    AS DWORD
          GLOBAL strSel  AS STRING
          GLOBAL texte() AS STRING
          '------------------------------------------------------------------------------
          '   ** Main Application Entry Point **
          '------------------------------------------------------------------------------
          FUNCTION PBMAIN()
              CALL sprachen
              CALL fundstuecke
          END FUNCTION
          '------------------------------------------------------------------------------
          FUNCTION fundstuecke AS LONG
              LOCAL i AS LONG
              DIALOG NEW 0, "Dialog1",,,                          326, 235,        TO hDlg
              CONTROL ADD LABEL,   hDlg, %IDC_LABEL1, "Label1",   10, 10, 165, 15
              CONTROL ADD LISTVIEW,hDlg, %IDC_LISTVIEW,"" ,       10, 70, 300, 90, CALL cbLv
              CONTROL ADD BUTTON,  hDlg, %IDC_BUTTON1, "Button1", 15, 200, 80, 15, CALL cbBtn1
              CONTROL SET FOCUS hDlg, %idc_listview
          
              ''listview füllen
              LISTVIEW INSERT COLUMN hDlg, %IDC_LISTVIEW, 1, "a", 120,0
              LISTVIEW INSERT COLUMN hDlg, %IDC_LISTVIEW, 2, "b", 50 ,0
              LISTVIEW INSERT COLUMN hDlg, %IDC_LISTVIEW, 3, "c", 180,0
              LISTVIEW INSERT COLUMN hDlg, %IDC_LISTVIEW, 4, "i", 1,0
              FOR i = 1 TO UBOUND(texte)
                  IF TRIM$(texte(i + 7)) = "" THEN
                      EXIT FOR
                  END IF
                  LISTVIEW INSERT ITEM hDlg, %IDC_Listview, 1,0, texte(i + 7)
                  LISTVIEW SET TEXT hDlg, %IDC_Listview, 1,2 , texte(i + 7)
                  LISTVIEW SET TEXT hDlg, %IDC_Listview, 1,3 , texte(i + 7)
                  LISTVIEW SET TEXT hDlg, %IDC_Listview, 1,4 , STR$(i + 7)
              NEXT i
              DIALOG SHOW MODAL hDlg
              FUNCTION = 1
          END FUNCTION
          
          '------------------------------------------------------------------------------
          '   ** CallBacks **
          '------------------------------------------------------------------------------
          CALLBACK FUNCTION cbBtn1
              DIALOG END hDlg
              FUNCTION = 1
          END FUNCTION
          '------------------------------------------------------------------------------
          CALLBACK FUNCTION cbLv AS LONG
              LOCAL pNMLV  AS NM_LISTVIEW PTR
              LOCAL kb     AS LV_KEYDOWN PTR
                  pNMLV = CB.LPARAM
                  kb    = CB.LPARAM
                  SELECT CASE @pNMLV.hdr.code
                      CASE %LVN_ITEMCHANGED
                          IF ISTRUE @pNMLV.uCHANGED AND ISTRUE %LVIS_SELECTED THEN
                              IF ISTRUE (@pNMLV.uNewState AND %LVIS_SELECTED) THEN
                                  IF @pNMLV.iItem > -1 THEN
                                      LISTVIEW GET TEXT CB.HNDL, %IDC_Listview, @pNMLV.iItem+1, 1 TO strSel
                                      FUNCTION = 1
                                  END IF
                              END IF
                          END IF
                      CASE %NM_DBLCLK
                          MSGBOX strSel
                          DIALOG END hdlg
                          FUNCTION = 1
                      CASE %LVN_KEYDOWN
                          SELECT CASE @kb.wVKEY
                              CASE %vk_space
                                 MSGBOX strSel
                                 DIALOG END hdlg
                                 FUNCTION = 1
                          END SELECT
                  END SELECT
          END FUNCTION
          '------------------------------------------------------------------------------
          SUB sprachen
              DIM texte(100)
                  texte(8) = "Fundstücke...: "
                  texte(9) = "Bitte nur Ziffern von 0 bis "
                  texte(10) = "Falsche Eingabe"
                  texte(11) = "User nicht gefunden"
                  texte(12) = "Nicht gefunden: "
                  texte(13) = "(extern)"
                  texte(14) = "Tel: "
                  texte(15) = "Büro: "
                  texte(16) = "Geräte-Nr: "
                  texte(17) = "IP-Adresse: "
                  texte(18) = "Angemeldet"
                  texte(19) = "Nicht angemeldet"
                  texte(20) = "letzte Anmeldung: "
                  texte(21) = "Telefax: "
                  texte(22) = "E-Mail Stellvertreter: "
                  texte(23) = "Termin-Details: "
                  texte(24) = "Start: "
                  texte(25) = "Ende: "
                  texte(26) = "Ort: "
                  texte(27) = "Optionen"
                  texte(28) = "Na&chricht senden"
                  texte(29) = "Wer gehört zur selben &Abteilung"
                  texte(30) = "Die nächsten 20 &Termine anzeigen"
                  texte(31) = "Nachrichten-Typ"
                  texte(32) = "&NetSend an: "
                  texte(33) = "E-&Mail an: "
                  texte(34) = "SMS an: "
                  texte(35) = "O&K"
                  texte(36) = "s&enden"
                  texte(37) = "Wirklich senden?"
                  texte(38) = "Nachricht"
                  texte(39) = "Nachricht von:"
                  texte(40) = "Anmeldestatus wird geprüft, " & $CRLF & "bitte warten"
                  texte(41) = "Name"
                  texte(42) = "UserID"
                  texte(43) = "Abteilung"
          END SUB

          Comment


          • #6
            Code:
             CASE %LVN_KEYDOWN
                            SELECT CASE @kb.wVKEY
                                CASE %vk_space
                                   MSGBOX strSel
                                   DIALOG END hdlg
                                   FUNCTION = 1
            Just off the top of my head, I don't like DIALOG END on LVN_KEYDOWN 'in-line' like this, since I know more notification messages are coming in response to this user action.

            I think I'd do a DIALOG POST CBHNDL, %WM_CLOSE, %NULL, %NULL there, and pick up WM_CLOSE in the main dialog procedure to do my DIALOG END.

            That way I'd know the rest of the notification messages associated with a 'key down' event will have been handled before I try ending the dialog.

            Worth a try, anyway.

            BTW..
            Code:
            pNMLV = CB.LPARAM
                    kb    = CB.LPARAM
                    SELECT CASE @pNMLV.hdr.code
            You don't need to mess with the lparam=pointer var code with 9x. There are new internal functions to deal with this. See the CB.NMCODE magic word under the "CB" topic of help.

            Than again, I'm not a "DDT" guy...

            MCM
            Michael Mattias
            Tal Systems Inc. (retired)
            Racine WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              (BTW: the error message you got there is definitely a compiler problem. That should never happen to you unless you call HeapFree() or DestroyHeap(), which I am guessing you are not doing a whole lot of).
              Michael Mattias
              Tal Systems Inc. (retired)
              Racine WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                I think it is to do with loading the array. You appear to be referencing off the end of the array - ubound(texte) is the last element which you can reference.

                Comment


                • #9
                  Assuming the stepping debugger kept running after that display...
                  I take that back, it's NOT a compiler/stepping debugger problem; it's actually a feature.

                  The stepping debugger returned a more detailed error message than would Windows.. which for this condition would simply exit on a code '0005' protection fault (attempt to access unowned memory). Not that that particular message is terribly useful to a beginning user, or maybe even the average user.

                  As for what CAUSED this error condition, that's a horse of a different color. In general it would mean you have an invalid address somewhere, but not null, and not an array bound violation, both of which would have given you an "Error 9" message.

                  This may be related to your funky "end of program" logic.... e.g Windows is trying to process a notification message for a window which no longer exists.
                  Michael Mattias
                  Tal Systems Inc. (retired)
                  Racine WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                  • #10
                    Thanks Chris but....
                    unfortunately not - I get the same when I strip down the code even further to no array and and an empty listview.

                    Originally posted by Michael Mattias View Post
                    BTW..
                    You don't need to mess with the lparam=pointer var code with 9x. There are new internal functions to deal with this. See the CB.NMCODE magic word under the "CB" topic of help.

                    Than again, I'm not a "DDT" guy...
                    Great, this one i could do without problems.


                    Originally posted by Michael Mattias View Post
                    I think I'd do a DIALOG POST CBHNDL, %WM_CLOSE, %NULL, %NULL there, and pick up WM_CLOSE in the main dialog procedure to do my DIALOG END.

                    That way I'd know the rest of the notification messages associated with a 'key down' event will have been handled before I try ending the dialog.

                    Worth a try, anyway.
                    I tested this and ended in a sort of "%WM_CLOSE-Loop". Stupid me.
                    What I did afterwards was kind of this (compilable code):


                    Code:
                    #COMPILE EXE
                    #DIM ALL
                     
                    '------------------------------------------------------------------------------
                    '   ** Includes **
                    '------------------------------------------------------------------------------
                    #INCLUDE "WIN32API.INC"
                    #INCLUDE "CommCtrl.inc"
                    '------------------------------------------------------------------------------
                    GLOBAL beenden AS LONG
                    GLOBAL hdlg AS LONG
                    '------------------------------------------------------------------------------
                    '   ** Main Application Entry Point **
                    '------------------------------------------------------------------------------
                    FUNCTION PBMAIN
                        beenden = 0
                        DIALOG NEW 0, "Dialog1",,,                        100, 100, TO hDlg
                        CONTROL ADD BUTTON,  hDlg, 1000, "Button1", 15, 15, 50, 15, CALL cbBtn1
                        CONTROL ADD LISTVIEW, hDlg, 1001, "", 15,35,65,50 CALL cbLv
                        DIALOG SHOW MODAL hDlg, CALL cbDlg
                    END FUNCTION
                    '------------------------------------------------------------------------------
                    '   ** CallBacks **
                    '------------------------------------------------------------------------------
                    CALLBACK FUNCTION cbDlg
                        IF beenden = 1 THEN
                            beenden = 0
                            DIALOG END hdlg
                        END IF
                    END FUNCTION
                    '------------------------------------------------------------------------------
                    CALLBACK FUNCTION cbBtn1
                        beenden = 1
                    END FUNCTION
                    '------------------------------------------------------------------------------
                    CALLBACK FUNCTION cbLv
                        LOCAL kb     AS LV_KEYDOWN
                        TYPE SET kb    = CB.NMHDR$(SIZEOF(kb))
                             IF CB.NMCODE = %LVN_KEYDOWN AND beenden = 0 THEN
                                    IF kb.wvkey = %vk_space THEN
                                            beenden = 1
                                    END IF
                             END IF
                    END FUNCTION
                    but I still get an error when pressing the space bar (Memory Access Violation).

                    If I change %vk_space to %vk_a, there comes the "heap" thing again.

                    Comment


                    • #11
                      I want the user to select an item either with cursor up/down or the mouse and then accept the selection with double click or spacebar.
                      That's not what a listview control does. When you use the arrow keys, you HAVE selected that item (row), unless you pre-empt it on LVB_SELCHANGING... but that has a problem because now if you reject the change, you can't 'skip over' a row in the list with the keyboard.

                      Maybe you should look at using combobox with style read-only, or maybe CBS_DROPDOWNLIST; or even a listbox. Then the user has to take an affirmative action to select one of the items in that list. Then when you click (or press spacebar on) the button, you can read the combobox/listbox to find which item has been selected to perform your processing.
                      Michael Mattias
                      Tal Systems Inc. (retired)
                      Racine WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        Maybe I'm completely wrong, but I thought that's what filefind.bas in the samples directory does?

                        (select and then process an entry from the list)


                        ----

                        by the way, if I test for %vk_return (which is caught when pressing [alt]+[return]) I neither get a
                        memory access violation nor a heap-error.
                        Last edited by Markus Saegesser; 9 Jan 2009, 10:09 AM.

                        Comment

                        Working...
                        X