No announcement yet.

Listview scrolls too much

  • Filter
  • Time
  • Show
Clear All
new posts

  • Listview scrolls too much

    I'm trying to use a listview as a 'rolling log file'. It must hold the last 50 or so actions of the program. So if item 50 is added, item 0 must be deleted. So far OK. In the sample (borrowed from Peter Redei with some modifications...) if you press the Add line button, everything goes well (line added, first line deleted.) But if the right scroll bar is in the lowest position, adding a line scrolls the columnheaders off screen. I can solve this by using listview_update, or invalidaterect, but that introduces a lot of screen flickering if there are many lines added to the view. Is there another way to 'freeze' the columnheaders?

    ' Testing listview routines
    ' David Morris 23/01/2000
    ' added some routines by Peter Redei
    ' ** Eliminate unnecessary macros
    '%NOLISTVIEW = 1
    #Compile Exe
    #Include "WIN32API.INC"
    #Include "COMMCTRL.INC"
    %IDOK = 1
    %IDCANCEL = 2
    %IDTEXT = 100
    %BS_DEFAULT = 1
    %IDLISTVIEW = 101
    '%LVS_EX_TRACKSELECT = &H8 'Should be in your "COMMCTRL.INC"
    '%LVS_EX_GRIDLINES = &H1 'Should be in your "COMMCTRL.INC"
    ' Global variable to recieve the user name
    Global UserName As String
    Global hListView As Long
    Global lviewSort As Integer
    Type dField
      fName As Asciiz * 80
      Size As Integer
      Alignment As Integer
    End Type
    Type ListData
      Columns As Integer
      Fields(0 To 80) As dField
    End Type
    Function HitColumn (hList As Long, xdim As Long) As Long
      Local i As Long, x As Long, sumx As Long
      sumx = 0
      i = 0
        x = ListView_GetColumnWidth(hList, i)
        sumx = sumx + x
        If xdim < sumx Then Function = i : Exit Do
        Incr i
    End Function
    Sub AppendListView (hList As Long, Rec() As String )
      Dim z As Integer, iStatus As Integer, szStr As Asciiz * 300, lvi As LV_ITEM
      Local x As Long
      'this will be the next record
      lvi.iItem = ListView_GetItemCount(hList) '+ 1
      lvi.mask = %LVIF_TEXT
      lvi.stateMask = %LVIS_FOCUSED '%LVIS_SELECTED
      lvi.pszText = VarPtr(szStr)
      For z = 0 To UBound(Rec)
        szStr = Rec(z)
        lvi.iSubItem = z
        lvi.lParam = lvi.iItem
        If z = 0 Then
          lvi.mask = %LVIF_TEXT Or %LVIF_PARAM Or %LVIF_STATE
          iStatus = ListView_InsertItem (hList, lvi)
          lvi.mask = %LVIF_TEXT
          iStatus = ListView_SetItem (hList, lvi)
        End If
    End Sub
    Sub ResetLParam(hList As Long)
      Local i As Long, recs As Long, lvi As LV_ITEM, x As Long
      lvi.mask = %LVIF_PARAM
      lvi.iSubItem = 0
      recs = ListView_GetItemCount(hList)
      For i = 0 To recs - 1
        lvi.iItem = i
        x = ListView_GetItem (hList, lvi)
        lvi.lParam = lvi.iItem
        x = ListView_SetItem (hList, lvi)
    End Sub
    Function RetrieveLVData(hList As Long, Recno As Long, Fieldno As Long) As String
    %cchTextMax = 300
    Local lvi As LV_ITEM
    Local value As Asciiz * 300
    Local x As Long
    lvi.cchTextMax = %cchTextMax
    lvi.iItem = Recno
    lvi.pszText = VarPtr(value)
    lvi.iSubItem = Fieldno
    lvi.Mask = %LVIF_TEXT
    x = ListView_GetItem (hList, lvi)
    Function = value
    End Function
    Function compare(ByVal lParam1 As Long, ByVal lParam2 As Long, _
    ByVal lParamsort As Long) As Integer
    'The lParam1 parameter is the 32-bit value associated with the first item being compared; and the
    'lParam2 parameter is the value associated with the second item. These are the values that were
    'specified In the lParam member of the items' LV_ITEM structure when they were inserted into the
    'list. The lParamSort parameter is the same value passed to the LVM_SORTITEMS message.
    'The comparison function must return a negative value if the first item should precede the second,
    'a positive value if the first item should follow the second, or zero if the two items are
    'equivalent. lParam will carry a pointer to the value in the cell
      Local value1 As Asciiz * 300, value2 As Asciiz * 300, j%
      Function = 0
      value1 = RetrieveLVData(hListView, lParam1, lParamsort)
      value2 = RetrieveLVData(hListView, lParam2, lParamsort)
      Select Case lviewSort
        Case 0 'ascending
          j = 1
        Case Else 'descending
          j = -1
      End Select
      If value1 < value2 Then
        Function = -1 * j
      ElseIf value1 = value2 Then
        Function = 0
        Function = 1 * j
      End If
    End Function
    CallBack Function OkButton()
        If ListView_GetItemCount(hListView) > 34 Then  ListView_DeleteItem hListView, 0
        Dim Rec (1) As String
        Rec(0) = "One more"
        Rec(1) = "line added!"
        AppendListView hListView, Rec()
    End Function
    CallBack Function CancelButton()
      Dialog End CbHndl, 0
    End Function
    CallBack Function ListViewProcess ()
      If CbCtlMsg = %WM_LBUTTONDBLCLK Then
      MsgBox "Double Click",48,"LISTVIEW 'NOT working
    End If
    End Function
    CallBack Function tstListView()
      Local ID As Long, hDlg As Long, lpToolTip As TOOLTIPTEXT Ptr, lData As ListData
      Local my_LpLvNm As NM_LISTVIEW Ptr, hi As LV_HITTESTINFO, itemselect As Long, reclient As rect
      Local pt As POINTAPI, i As Long, sText As String
      Static zText As Asciiz * 255
      hDlg = CbHndl
      Select Case CbMsg
        Case %WM_INITDIALOG
        Case %WM_NOTIFY
          Select Case LoWrd(CbWparam)
            Case %IDLISTVIEW
              my_LpLvNm = CbLparam
              If @my_LpLvNm.hdr.code = %LVN_COLUMNCLICK Then
                itemselect = @my_LpLvNm.iSubItem 'HitColumn(hListView,
                i = (itemselect = -1)
                If i = 0 Then
                  'toggle ascending/descending
                  lviewSort = Not lviewSort
                  ListView_SortItems hListView, CodePtr(compare), itemselect
                  'lparam was set to the original 'recordnumber'
                  'now this changed, we need to set it to the new position
                  ResetLParam hListView
                End If
              ElseIf @my_LpLvNm.hdr.code = %NM_DBLCLK Then 'Now have Mouse Clicks!
                SText = RetrieveLVData(hListView, @my_LpLvNm.iItem, 1) 'Next find where click was
                Control Set Text hDlg&, %IDTEXT, Str$(CbCtlMsg)+Str$(CbWparam)+Str$(CbLparam)' sText
              End If
    '          ElseIf @my_LpLvNm.hdr.code = %NM_DBLCLK Then 'Now have Mouse Clicks!
    '            sText = RetrieveLVData(hListView, 0, 0) 'Next find where click was
    '            MsgBox sText,48,"LISTVIEW"
    '          End If
          End Select
      End Select
    End Function
    Function PbMain () As Long
      $Register None
      Local hDlg As Long, result As Long, zText As Asciiz * 255, icc As INIT_COMMON_CONTROLSEX
      Local LVC As LV_COLUMN, i As Long,r As Long, c As Long,IStyle As Long
      %NumCols = 5:%NumRows = 30
      Dim Rec(%NumCols+1)As String
      Local LVI As LV_ITEM
      ' InitCommonControls
      icc.dwSize = SizeOf(icc)
      InitCommonControlsEx icc
      ' ** Create a new dialog template
      Dialog New 0, "What is your name?", ,, 460, 250, 0, 0 To hDlg
      ' ** Add controls to it
      Control Add Button, hDlg, %IDOK, "Add a line", 34, 32, 50, 14, %BS_DEFAULT Call OkButton
      Control Add Button, hDlg, %IDCANCEL, "Cancel", 84, 32, 40, 14, 0 Call CancelButton
      Control Add "SysListView32", hDlg, %IDLISTVIEW,"",0,50,300,180, _
      %WS_border Or %WS_Child Or %WS_visible Or _
      %WS_EX_CLIENTEDGE Call ListViewProcess
      Control Handle hDlg,%IDLISTVIEW To hListView
      IStyle = SendMessage (hListView,%LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0)
      SendMessage hListView, %LVM_SETEXTENDEDLISTVIEWSTYLE, 0, ByVal IStyle
      lvC.fmt = %LVCFMT_LEFT = 90
      LVC.cchTextMax = 255
      For c = 1 To %NumCols
        zText = "Column " + Format$(c - 1)
        LVC.pszText = VarPtr(zText)
        Control Send hDlg,%IDLISTVIEW,%LVM_INSERTCOLUMN, c, VarPtr(lvc)
      For r = 1 To %NumRows
        For c = 1 To %NumCols
          rec(c-1) = "Row " + Format$(r) + " Col " + Format$(c-1)
        Next c
        AppendListView hListView, Rec()
      Next r
      ' ** Display the dialog
      Dialog Show Modal hDlg Call tstListView To Result
      ' ** Check the result
      If result Then MsgBox "Hello " & UserName
    End Function


  • #2
    I tested your code in Win2000 and the column headers don't scroll at all, even if I add 50 items! What O/S are you using?

    While I can't duplicate your problem, when you need to "mass update" a control and don't want the visual flicker, here is a nice little trick:

    Before updating the control, set it %WM_SETREDRAW state to false. Then perform your content update, then finally set the controls %WM_SETREDRAW state back to true and call InvalidateRect(hCtrl, BYVAL %NULL, %TRUE) - with DDT, use CONTROL HANDLE to translate the ID of the control into is actual window handle value (hCtrl).

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


    • #3

      I'm using NT4 WS with sp6(a). The problem only happens if the scrollbar is completely at the bottom. Then when I add an item, the columnheaders just scroll-off together with the rest. (Maybe a bug in the commctrl DLL, solved in WIN2000?) I'll try your refresh-trick!




      • #4
        I gave it a spin on my weakling P75 Win95 notebook. The only time
        the header flickers is when I use the scroll-up key just when the high light bar is on the first viewable line and I have previously scrolled past the last viewable line. It would be nice just to invalidate the client area below the header only and leave the header alone... hint,hint,wink,wink.

        Regards, Jules

        Best regards


        • #5
          It's definitely a micro$oft bug in the Comctl32.dll (i've tested with version 4.72). I've found a version 5.80, which works beautiful! Maybe someone with an old version can confirm this?
          BTW: Is there a way to get the version of a DLL (so I can anticipate this odd behaviour?)


          [This message has been edited by Peter Lameijn (edited March 09, 2000).]


          • #6
            See VerQueryValue() - there have been examples posted to this BBS in the past.

            BTW, the version of COMCTL32.DLL installed with my Win2K is 5.81.2920.0

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