Announcement

Collapse
No announcement yet.

AutoSize Column in OwnerDraw ListView

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

  • AutoSize Column in OwnerDraw ListView

    I'd like to resize a column automatically in an OwnerDraw ListView control, to fit the content.

    But something like this next line seems to affect only the currently displayed content. If the user scrolls to a line with wider content, the column may no longer be sized for the new data.
    Code:
    ListView Set Column  hDlg, %IDC_ListView, 6, -2
    I tried putting the statement it within the ownerdraw code, like this:
    Code:
      Case 5   'column to be auto-widened
    
         LVZ = LCF(tag(iRow).idx)
         @pLVDI.item.pszText = VarPtr(LVZ)
         ListView Set Column hDlg, %IDC_ListView, 6, -2
    But that just crashes the app.


    Has anyone implemented an autoresize on an ownerdraw ListView?


    Gary
    Last edited by Gary Beene; 22 Feb 2014, 01:58 PM.

  • #2
    After item count has been set, one can do:
    Code:
            ListView_SetColumnWidth hListView, 1, %LVSCW_AUTOSIZE  ' or %LVSCW_AUTOSIZE_USEHEADER
    where second parameter is zero based column count - 1 meaning column 2, etc.
    Last edited by Borje Hagsten; 22 Feb 2014, 02:20 PM.

    Comment


    • #3
      Hey Borje!
      Does that line of code continue to apply as the user scrolls new rows into visibility, where the new rows have longer content than were visible when it was called?

      The DDT version doesn't appear to be persistent.

      I knew of the API version (your post), but perhaps wrongly assumed it would work as does the DDT version?

      I've got some ownerdraw ListView code I can go test it in.

      Comment


      • #4
        Only used it in one code and it worked for me there - but not in first column, only columns > 0. Important part seems to be to use it after item count has been set.

        Comment


        • #5
          I'll go give it a try and report back!

          Comment


          • #6
            Gary,
            Do you mean to auto-resize depending on which is longer? (The column Title or the content of the column, whichever is longer?)
            Engineer's Motto: If it aint broke take it apart and fix it

            "If at 1st you don't succeed... call it version 1.0"

            "Half of Programming is coding"....."The other 90% is DEBUGGING"

            "Document my code????" .... "WHYYY??? do you think they call it CODE? "

            Comment


            • #7
              Hi Cliff,
              Yes, whichever is the longest - header or longest string element of the array

              It's an owner draw ListView with 200K entries. What I found that that using DDT Fit To Content seems to resize the column to the visible entries, but not to every member of the array.

              I could scroll (displaying new members of the array) and the column was smaller than some distant array elements.

              Comment


              • #8
                I may be wrong here but it seems that it's sizing based on what's available.
                When you scroll you are changing what's available, right? It is an
                owner-drawn listview.

                Why not at the beginning go through your whole list and figure out the
                longest item for each column. Then make the column headers width to
                match your longest column.

                Comment


                • #9
                  Hi Paul,
                  I could, but I was hoping that the built-in functions would do it for me!

                  Comment


                  • #10
                    They will but if you change the data you will have to tell them to do it
                    again for the new data.

                    Your choice : once or every time the data changes.

                    Comment


                    • #11
                      Gary,
                      I will have to look but at some point I had the same sort of thing, and I think I did it with fitting the content first and then fit the header? (Maybe that was the other way around?)
                      Engineer's Motto: If it aint broke take it apart and fix it

                      "If at 1st you don't succeed... call it version 1.0"

                      "Half of Programming is coding"....."The other 90% is DEBUGGING"

                      "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                      Comment


                      • #12
                        Originally posted by Gary Beene View Post
                        Hi Paul,
                        I could, but I was hoping that the built-in functions would do it for me!
                        So you want the whole listview visible without it being visible?
                        That would require a duplicate listview out of sight that is sized to that the
                        whole list is visible, wouldn't it?
                        You could also get the text metrics as you populate the list, checking the
                        text width of every entry and keeping a variable that holds the largest size.
                        The world is strange and wonderful.*
                        I reserve the right to be horrifically wrong.
                        Please maintain a safe following distance.
                        *wonderful sold separately.

                        Comment


                        • #13
                          I was just hoping that the ListView Fit To Content was a persistent setting/automatic, not one that I had to repeat as additional content was displayed, nor that I would have to read through my entire array and calculate the maximum width of all elements. Since it's not, I'll just go with one of the approaches I discussed.
                          ...That would require a duplicate listview out of sight that is sized to that the whole list is visible, wouldn't it?
                          Kurt, no, there are at least 2 other solutions. Besides, with an ownerdraw ListView, having a 2nd non-ownerdraw ListView would defeat the purpose of the 1st.
                          Last edited by Gary Beene; 24 Feb 2014, 07:59 AM.

                          Comment


                          • #14
                            I don't userstand how any "auto" resize can work if the LV is owner-draw, as the control does not retain any text to measure.
                            Michael Mattias
                            Tal Systems Inc. (retired)
                            Racine WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              Hi MCM,
                              Look back up in post #1 at the code I posted. While that code crashes, it shows how to do what you ask. At least, it shows that there's a place where the ListView authors could have written the control code such that the Size To Content setting was persistent, i.e., the ListiVew control could have kept a running track of the MaxReceivedWidth and adjusted the size of the columns accordingly.

                              Text retention would not have been required for the solution:
                              ...does not retain any text to measure.

                              Comment


                              • #16
                                re:
                                Code:
                                     LVZ = LCF(tag(iRow).idx)
                                     @pLVDI.item.pszText = VarPtr(LVZ)
                                     ListView Set Column hDlg, %IDC_ListView, 6, -2
                                When you do this, is the LVIF_TEXT Bit of @pLVDI.Item.mask set?

                                In response to what notification message are you doing all this?

                                Have you insured your pszText will be valid when the procedure exits?

                                Is the style of the listview control LVS_OWNERDATA or LVS_OWNERDRAWFIXED? (Insufficent code shown or linked).

                                Are you sure the error is at this point in the code, or might you have made an error (missed an edit) earlier which only now shows up?


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

                                Comment


                                • #17
                                  Hi Gary,

                                  Here's a simple solution.
                                  Code:
                                          CASE %WM_INITDIALOG
                                              SetTimer CB.HNDL, 101, 200, 0
                                   
                                          Case %WM_Timer
                                            ListView Set Column Cb.Hndl, %IDC_ListView, 4, -2
                                  Rgds, Dave

                                  Comment


                                  • #18
                                    Hi Dave!
                                    Yep, that would certainly do it. I was just trying to make something work and found it not to work as I expected, so was delving into the reasons.

                                    And, MCM,
                                    ...Insufficent code shown or linked
                                    Sorry, I had thought perhaps it was a common-knowledge thing (but not for me ) and full code would not be necessary.

                                    Here's an example of the code that crashes, when either of the Set Column or Fit Content lines is used under LVN_GetDispInfo. It also shows that using the Set Column once does not give the desired results.

                                    Code:
                                    'Compilable Example:
                                    #Compiler PBWin 10
                                    #Compile Exe
                                    #Dim All
                                    %Unicode=1
                                    #Include "win32api.inc"
                                    
                                    Enum Equates Singular
                                       IDC_ListView = 500
                                    End Enum
                                    
                                    Global hDlg, hListView As Dword, D() As String, z As WStringZ * 100
                                    
                                    Function PBMain() As Long
                                       Dialog New Pixels, 0, "Virtual ListView", , , 270,300, %WS_SysMenu,, To hDlg
                                       Control Add ListView, hDlg, %IDC_ListView,"", 10,10,250,280,  %WS_Child Or %LVS_Report Or %LVS_ShowSelAlways Or %WS_TabStop Or %LVS_SingleSel Or %LVS_OwnerData, %WS_Ex_ClientEdge
                                       Control Handle hDlg, %IDC_ListView To hListView
                                       ListView Insert Column hDlg, %IDC_Listview, 1, "ColA", 70,0     'set headers
                                       ListView Insert Column hDlg, %IDC_Listview, 2, "ColB", 70,0     'set headers
                                       Dialog Show Modal hDlg, Call DlgProc
                                    End Function
                                    
                                    CallBack Function DlgProc
                                       Local iRow As Long, pLVDI As LV_DISPINFOW Ptr, tempZ As WStringZ * %Max_Path
                                       Select Case Cb.Msg
                                          Case %WM_InitDialog
                                             ReDim D(100)
                                             For iRow = 0 To 100 : D(iRow) = "Line" + Str$(iRow) + " " + Repeat$(Rnd(1,10),"rst") : Next iRow
                                             ListView_SetItemCountEx(hListView, UBound(D)+1, %LVSICF_noInvalidateAll) 'max rows
                                             ListView Set Column hDlg, %IDC_ListView, 1, -2   '<--- used once here does not give desired results
                                             ListView Set Column hDlg, %IDC_ListView, 2, -2   '<--- used once here does not give desired results
                                          Case %WM_Notify
                                             Select Case Cb.NmId
                                                Case %IDC_ListView
                                                   Select Case Cb.NmCode
                                                      Case %LVN_GetDispInfo
                                                         pLVDI = Cb.LParam
                                                         iRow = @pLVDI.item.iItem
                                                         Z = D(iRow)
                                                         @pLVDI.item.pszText = VarPtr(Z)
                                                         'ListView Set Column hDlg, %IDC_ListView, 1, -2  '<---- crashes
                                                         'ListView Fit Content hDlg, %IDC_ListView, 1     '<---- crashes
                                                   End Select
                                             End Select
                                       End Select
                                    End Function

                                    Comment


                                    • #19
                                      ** OPINION ALERT ***

                                      Don't go mixing and matching DDT and SDK-style stuff.

                                      If you want to use DDT to manage your screens, better to replace
                                      Code:
                                        CONTROL ADD LISTVIEW
                                        ....
                                        LISTVIEW SET or GET
                                      .. with...
                                      Code:
                                        CONTROL ADD "Syslistview32"... 
                                        CONTROL SEND CB.HNDL, %ID_LISTVIEW, %LVM_whatever
                                      You never know when you will run into "something" in the PB runtime which controls the behavior of the proprietary "LISTVIEW" control and SDK-Style calls will be at best fruitless and at worst fatal. (to the program, not to you).

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

                                      Comment


                                      • #20
                                        Everyone,
                                        And, I might mention, that using Borje's suggestion also crashes ...
                                        Code:
                                        ListView_SetColumnWidth hListView, 1, %LVSCW_AUTOSIZE
                                        MCM,
                                        Yes, there's some merit in your suggestion. However, as is well documented, PowerBASIC DDT statements don't cover all our programming needs. So the use of API with DDT controls has to happen. One just has to be aware, when troubleshooting, of the connection you've drawn.

                                        Everyone again,
                                        Since I don't have an SDK virtual ListView example, perhaps someone has one ready-at-hand in which Borje's statement (above) could be tested to see if it crashes in SDK also?

                                        Comment

                                        Working...
                                        X