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?
Peter.
Code:
'============================================================================== ' ' Testing listview routines ' David Morris 23/01/2000 ' added some routines by Peter Redei '============================================================================== ' ** Eliminate unnecessary macros %NOANIMATE = 1 : %NODRAGLIST = 1 : %NOHEADER = 1 : %NOIMAGELIST = 1 '%NOLISTVIEW = 1 %NOTABCONTROL = 1 : %NOTRACKBAR = 1 : %NOTREEVIEW = 1 : %NOUPDOWN = 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 Do x = ListView_GetColumnWidth(hList, i) sumx = sumx + x If xdim < sumx Then Function = i : Exit Do Incr i Loop 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) Else lvi.mask = %LVIF_TEXT iStatus = ListView_SetItem (hList, lvi) End If Next 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) Next 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 Else 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 tbab AS TBADDBITMAP 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 'STATIC hBmp AS LONG 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, hi.pt.x) 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 '%LVS_EX_TRACKSELECT = &H8 ' InitCommonControls icc.dwICC = %ICC_DATE_CLASSES Or %ICC_BAR_CLASSES Or %ICC_LISTVIEW_CLASSES 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 '$WC_LISTVIEW Control Add "SysListView32", hDlg, %IDLISTVIEW,"",0,50,300,180, _ %WS_border Or %WS_Child Or %WS_visible Or _ %LVS_REPORT Or %LVS_SHOWSELALWAYS, _ %WS_EX_CLIENTEDGE Call ListViewProcess Control Handle hDlg,%IDLISTVIEW To hListView IStyle = SendMessage (hListView,%LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0) IStyle = IStyle Or %LVS_EX_FULLROWSELECT Or %LVS_EX_TRACKSELECT Or %LVS_EX_GRIDLINES SendMessage hListView, %LVM_SETEXTENDEDLISTVIEWSTYLE, 0, ByVal IStyle lvC.mask = %LVCF_FMT Or %LVCF_WIDTH Or %LVCF_TEXT Or %LVCF_SUBITEM lvC.fmt = %LVCFMT_LEFT lvC.cx = 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) Next 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
Comment