Announcement

Collapse
No announcement yet.

Listview with %LVS_EX_CHECKBOXES style

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

  • Listview with %LVS_EX_CHECKBOXES style

    Hi guys,

    I would like to know witch row is selected, using LISTVIEW GET STATE. What is the value for col& when i'm using LVS_EX_CHECKBOXES as style?

  • #2
    >I would like to know witch row is selected, using LISTVIEW GET STATE.

    LISTVIEW GET State does not tell you which row is selected, it tells you if a particular row is or is not selected.

    LISTVIEW GET STATE hDlg, id&, row&, col& TO datav&

    A data item is tested to see if it is currently selected. The values of row&/col& specify the position of the data item (1=first, 2=second, etc.). If the item is selected, -1 (true) is assigned to the variable specified by datav&. Otherwise, 0 (false) is assigned to it.
    Don't ask me why you need to specify a column number in that statement, since column number has absolutely nothing to do with the selected state of a row of a standard listview control. But I'd try column zero (that's in API-speak, with PB the first column is probably column one)

    If you want to know which row(S) is (are) selected, you can send the LVM_GETNEXTITEM message to the control, asking for the first item which is selected. I use this function
    Code:
    FUNCTION ListView_GetSelection (BYVAL hWnd AS LONG) AS LONG
      FUNCTION = SendMessage(hWnd, %LVM_GETNEXTITEM, -1, %LVNI_SELECTED)
    END FUNCTION
    Checkboxes added with LVS_EX_CHECKBOXES are associated only with a row; they have no column. (standard listview)

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

    Comment


    • #3
      Hi Daniel;

      You don't need to specify a column number for the checkboxes. Here is a functioning code snippet.

      Code:
          CONTROL ADD LISTVIEW, hDlg, %List1, "", 12, 246, 800, 500, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %LVS_REPORT _
              OR %LVS_SHOWSELALWAYS OR %LVS_NOCOLUMNHEADER OR %LVS_SINGLESEL OR %WS_EX_RIGHTSCROLLBAR, , 
          LISTVIEW SET STYLE hDlg, %List1, %LVS_EX_ONECLICKACTIVATE OR %LVS_EX_GRIDLINES OR %LVS_EX_CHECKBOXES 
          CONTROL SET COLOR hDlg, %List1, %BLUE, %WHITE
          LISTVIEW INSERT COLUMN hDlg, %List1, 1, "", 800, 0

      Comment


      • #4
        I'm using the folowing code to test which row has been selected.
        As you can see I'm using 0 as value for col&.
        This code can not give me the selected row when the I'm using only the checkbox to select a item
        If I select the whole row, it works fine.

        LISTVIEW GET COUNT ghDlg, %IDC_LISTVIEW1 to A_Items
        FOR x = 1 TO A_Items
        LISTVIEW GET STATE ghDlg, %IDC_LISTVIEW1, x, 0 to Found
        IF Found = -1 THEN
        ? "Row nr " & str$(x) & " is selected"
        END IF
        NEXT x

        Comment


        • #5
          This code can not give me the selected row when the I'm using only the checkbox to select a item
          That's because the "checked status" is a completely different state from "selected status."

          With a listview it's perfectly acceptable for a row to be checked but not selected and vice-versa. FWIW, "focused" is ALSO a separate status.

          I don't see a "LISTVIEW GET CHECK" function, so if you are trying to found which row(s) are checked, you can use the ListView_GetCheckState MACRO/FUNCTION. You can find details of using this in your Windows' API documentation.

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

          Comment


          • #6
            Hallo Michael,
            I changed my code and now it is working.
            Thanks.

            CONTROL HANDLE ghDlg, %IDC_LISTVIEW1 TO hLstv
            LISTVIEW GET COUNT ghDlg, %IDC_LISTVIEW1 TO A_Items
            FOR x = 0 TO A_Items - 1
            Found = Listview_GetCheckState(hLstv, x)
            IF Found = -1 THEN
            ? "Row nr " & str$(x + 1) & " is checked"
            END IF
            NEXT x
            But I have an other question.
            I want to limit the allowable to two or tree checkboxes.
            I think it must be done in the %WM_NOTIFY, but how?

            Comment


            • #7
              >I think it must be done in the %WM_NOTIFY, but how

              Well, yes, you do have to do it under WM_NOTIFY. But..

              What you have to to is process the WM_NOTIFY/LVN_ITEMCHANGING notfication. If the uchange member of the NMHEADER structure indicates a State change, then if that change is an LVIS_STATEIMAGEMASK change, and the new state is to be checked, then you count how many rows are already checked; if this would put you over your limit, you prevent the change by returning TRUE.

              However, I'm not so sure using a listview control with checkboxes would be the optimal choice here. This is maybe why detecting this - while 'do-able' - is not very straightforward at all. (If you think the above is straightforward, give me a call next time you are looking for a job).

              And, users don't expect to "not" be able to either click or press spacebar to be able to check a row of a list control with checkboxes.

              Maybe you could explain your application a little more and someone will have another idea you can play with.

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

              Comment


              • #8
                > want to limit the allowable to two or tree checkboxes

                Or, you could draw your own checkboxes, and only draw them on the rows where you want to allow them. Demo here: Listview with Multiple Checkbox Columns Demo 2-20-05

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

                Comment


                • #9
                  Hello Michael,

                  If you think the above is straightforward, give me a call next time you are looking for a job
                  I'm 62 now and looking for a job isn't really an option!!

                  In my application I want to show the sales values for a specific range of products. As there are around 20 different products I can't show them all on one graph. So I must limit the number of products the user can see.
                  For the moment I'm using two Listviews. The first has all the products, the second only those the user wants to see in a graph. By clicking on a item in the first listview the user can put it in the second listview. In a listview I can limit the number of selected products.

                  But I think it will be nicer to use a listview with checkboxes (?).
                  I'm trying now the folowing code under the %WM_NOTIFY but it doesn't work

                  CASE %WM_NOTIFY
                  local hdr As NMHDR Ptr
                  hdr = CbLParam
                  SELECT CASE @hdr.code
                  CASE %NM_CLICK
                  CONTROL HANDLE ghDlg, %IDC_LISTVIEW1 TO hLstv
                  LISTVIEW GET COUNT ghDlg, %IDC_LISTVIEW1 TO A_Items
                  FOR x = 0 TO A_Items - 1
                  Found = Listview_GetCheckState(hLstv, x)
                  IF Found = -1 THEN INCR A_Checked
                  IF A_Checked > 1 THEN
                  Listview_SetCheckState(hLstv, x, %FALSE)
                  EXIT FOR
                  END IF
                  NEXT x
                  END SELECT

                  Comment


                  • #10
                    'That's because the selection state is changed by Windows AFTER the click notification

                    Try processing WM_NOTIFY/LVN_ITEMCHANGING That will also handle changes made by pressing the the spacebar. (Assuming you are toggling the check status of the selected row when the user hits the spacebar). (Or double-clicking).

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

                    Comment


                    • #11
                      Daniel,
                      You don't show the flags being used when creating the listbox, but I'm going to take a guess that you don't have multiple selections enabled.

                      If you did, the user could select multiple items (without the need for checkboxes), then click a button to process the selections. That would make the code you did show a little simpler.

                      Here's a snippet from my own code. I've chopped out some non-relevant stuff, so this may need dependencies to be edited, but it's actually doing the kind of thing you said you want to do.

                      To limit the number of lines selected, you'd have to trap the listview change message and keep count, but that's before this code would run.


                      Code:
                         ListBox Get Selcount hDlg, %LISTBOX To NumSelLines 
                         MsgBox "NumSelLines: " & Str$(NumSelLines) ,,"Number of Selected Lines"   'just during code development 
                      
                         If NumSelLines = 0 Then
                            MsgBox "Nothing selected!",,"What?!?"
                         Else
                            ListBox Get Select hDlg, %LISTBOX To j     'get the index of the first selected item
                            For i = 1 To NumSelLines
                               ListBox Get Text   hDlg, %LISTBOX, j To SourceFile
                      
                               '(for testing) show that we have the line:
                               MsgBox "Index:" & Str$(j) & " - " & SourceFile,,"Item " & Str$(i)
                      
                               'Set the storage name from the SourceFile name
                               StorageName = gStorageLocation & "\" & PathName$(Namex, SourceFile) 
                      
                               MsgBox SourceFile & $CrLf & StorageName ,,"SourceFile and StorageName"   'just during development
                      
                               'do the work...
                               dRet = DoWork(SourceFile, StorageName)
                      
                               ListBox Get Select hDlg, %LISTBOX, j+1 To j     'get the index of the next selected item
                            Next i
                         End If
                      Hope this helps!
                      -John
                      Last edited by John Montenigro; 5 Feb 2009, 08:03 AM. Reason: edited out superfluous code fragment

                      Comment


                      • #12
                        Originally posted by Michael Mattias View Post
                        'That's because the selection state is changed by Windows AFTER the click notification

                        Try processing WM_NOTIFY/LVN_ITEMCHANGING That will also handle changes made by pressing the the spacebar. (Assuming you are toggling the check status of the selected row when the user hits the spacebar). (Or double-clicking).

                        MCM
                        I'am using now the folowing code and it works fine

                        CASE %WM_NOTIFY
                        hdr = CbLParam
                        SELECT CASE @hdr.code
                        CASE %LVN_ITEMCHANGED
                        A_GeChecked = 0
                        CONTROL HANDLE ghDlg, %IDCDC_LISTVIEW1 TO hLstv
                        LISTVIEW GET COUNT ghDlg, %IDC_LISTVIEW1 TO A_Items
                        FOR x = 0 TO A_Items - 1
                        Found = Listview_GetCheckState(hLstv, x)
                        IF Found = -1 THEN incr A_GeChecked
                        IF A_GeChecked > 4 THEN
                        MsgBox "You can only check 4 items!",
                        %MB_ICONEXCLAMATION OR %MB_OK, "Test"
                        Listview_SetCheckState(hLstv, x, %FALSE)
                        EXIT FOR
                        END IF
                        NEXT x
                        END SELECT
                        Walter, John & Walter, thanks for the support!

                        Comment


                        • #13
                          You can refine it a bit further than that, if you maintain a static state variable indicating the number of items checked, and use the notification on checking / un-checking to increment / decrement this variable, you can be rid of the loop and do fancier things like clearing the checkbox just checked if it exceeds the limit, or clearing the first checkbox checked.
                          Furcadia, an interesting online MMORPG in which you can create and program your own content.

                          Comment


                          • #14
                            When you do "unset" a check box because there are too many rows already checked, you might want to give the user a cue.

                            A MSGBOX is pretty instrusive, but you can give an audio cue using..

                            Code:
                            MessageBeep   %MB_ICONHAND
                            (The MB_ICONHAND sound is the "something bad happened" sound; versus the MB_OK sound which means, well, "Okay.")
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment

                            Working...
                            X