CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Dec 2009
    Posts
    17

    Get text of the item out of listview with LVS_OWNERDRAWFIXED

    how to Get itemtext of the list item out of listview with LVS_OWNERDRAWFIXED

    what is wrong wht the code its not getting the item text from the listview with lvs_ownerdrawfixed

    Code:
    Public Function SysListView32ToCSV(ByVal hListView As Long, ByVal DestPath As String, ByVal Delimiter As String) As Boolean
        On Error GoTo ErrHandler
        
        Dim ListCount As Long, ColumnCount As Long, HeaderhWnd As Long
        Dim ProcessID As Long, ProcessHandle As Long
        Dim MemAddr1 As Long, MemAddr2  As Long
        Dim i As Long, j As Long, lRtn As Long
        Dim sLine As String, sText As String, ItemText As String
        Dim ListViewItem As LVITEM
        Dim HeaderItem As HDITEM
        Dim aText() As Byte
        Dim FF As Integer
        
        Dim DI As NMLVDISPINFO      'trying for DISPINFO
        
        
        ListCount = SendMessage(hListView, LVM_GETITEMCOUNT, 0, ByVal 0&)
        
        HeaderhWnd = SendMessage(hListView, LVM_GETHEADER, 0, ByVal 0&)
        
        ColumnCount = SendMessage(HeaderhWnd, HDM_GETITEMCOUNT, 0, ByVal 0&)
        
    
        If Dir(DestPath) <> "" Then Kill DestPath
        
        GetWindowThreadProcessId hListView, ProcessID
        
        If ProcessID = 0 Then Exit Function
            
        ProcessHandle = OpenIPCProcess(ProcessID)
        
        If ProcessHandle Then
        
            FF = FreeFile
            Open DestPath For Append As #FF
                
    '        MemAddr1 = CreateIPCMemory(36, ProcessHandle)
            MemAddr2 = CreateIPCMemory(261, ProcessHandle)
            
    '        If Not (MemAddr1 = 0& Or MemAddr2 = 0&) Then
    '
    '            With HeaderItem
    '                .cchTextMax = 260&
    '                .mask = HDI_TEXT
    '                .pszText = MemAddr2
    '
    '            End With
    '
    '            ReDim aText(0 To 260) ' << Moved here
    '            For i = 0 To ColumnCount - 1
    '                WriteIPCMemory ProcessHandle, MemAddr1, VarPtr(HeaderItem), 36&
    '                lRtn = SendMessage(HeaderhWnd, HDM_GETITEMA, i, ByVal MemAddr1)
    '                Debug.Print lRtn
    '                If lRtn Then
    '                    ReadIPCMemory ProcessHandle, MemAddr2, VarPtr(aText(0)), 260&
    '                     ItemText = StrConv(aText, vbUnicode)
    '                    ItemText = Left$(ItemText, InStr(ItemText, vbNullChar) - 1)
    '                    sLine = sLine & ItemText & IIf(j < ColumnCount - 1, Delimiter, vbNullString)
    '                End If
    '            Next
    '
    '            Print #FF, sLine
    '
    '            ' Release virtual memory
    '            DestroyIPCMemory ProcessHandle, MemAddr1
    '
    '        End If
    
            ' Create virtual memory
             MemAddr1 = CreateIPCMemory(40, ProcessHandle)
            ' MemAddr1 = CreateIPCMemory(Len(DI), ProcessHandle)
            
            
            If Not (MemAddr1 = 0& Or MemAddr2 = 0&) Then
                
                For i = 0 To 0 ' ListCount - 1
                    sLine = vbNullString
                    For j = 0 To 0 ' ColumnCount - 1
                        With ListViewItem
                            .cchTextMax = 260&
                            .mask = LVIF_TEXT
                            .pszText = MemAddr2
                            .iItem = i
                            .iSubItem = j
                        End With
                        WriteIPCMemory ProcessHandle, MemAddr1, VarPtr(ListViewItem), 40&
                        lRtn = SendMessage(hListView, LVM_GETITEMA, 0&, ByVal MemAddr1)
        Debug.Print lRtn
                        If lRtn <> 0& Then
                            ReadIPCMemory ProcessHandle, MemAddr1, VarPtr(ListViewItem), 40&
        Debug.Print vbTab; ListViewItem.pszText; MemAddr2; ListViewItem.cchTextMax
                            ' To be safe, I'd resize aText() to .cchTextMax
                            ReDim aText(0 To ListViewItem.cchTextMax)
                            ReadIPCMemory ProcessHandle, ListViewItem.pszText, VarPtr(aText(0)), ListViewItem.cchTextMax
                           ' sLine = sLine & Left$(StrConv(aText, vbUnicode), lRtn) & IIf(j < ColumnCount - 1, Delimiter, vbNullString)
                            sLine = sLine & Left$(StrConv(aText, vbUnicode), _
           ListViewItem.cchTextMax) & IIf(j < ColumnCount - 1, Delimiter, vbNullString)
                        End If
                        Print #FF, i, j, sLine
                     Next
                Next
                
                ' Release virtual memory
                DestroyIPCMemory ProcessHandle, MemAddr1
    
            End If
            
            Close #FF
            
            ' Release virtual memory
            If MemAddr2 <> 0& Then DestroyIPCMemory ProcessHandle, MemAddr2
            
            CLoseIPCProcess ProcessHandle
            
            SysListView32ToCSV = True
        End If
            
        Exit Function
    ErrHandler:
        
    End Function
    Last edited by rohitb; June 3rd, 2010 at 11:59 PM.

  2. #2
    Join Date
    Jan 2006
    Location
    Fox Lake, IL
    Posts
    15,007

    Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED

    Please use CODE TAGS like I do below. Here is some sample ListView to Excel code. There should be a SELECTED ITEM, though:
    Code:
    Option Explicit
    
    Dim ITM As ListItem
    Dim LSI As ListSubItem
    
    Private Sub Command1_Click()
    '============================
    Dim excl As New Excel.Application
    Dim bk As Workbook
    Dim sht As Worksheet
    Dim i%
    
        Set excl = New Excel.Application
        Set bk = excl.Workbooks.Add
        Set sht = bk.ActiveSheet
        For i = 1 To ListView1.ColumnHeaders.Count
            
        Next i
        excl.Visible = True
    
    End Sub
    
    Private Sub Command2_Click()
    Dim i As Integer
    
        ListView1.MultiSelect = Not ListView1.MultiSelect
        ListView1.SetFocus
        With ListView1.ListItems
            For i = 1 To .Count
                .Item(i).Selected = True 'Index
                If .Item(i).Checked = True Then
                    'MsgBox .Item(i).Text
                End If
            Next i
            .Item(.Count).Selected = ListView1.MultiSelect
        End With
    
    End Sub
    
    
    Private Sub btnPrint_Click()
    Dim i%, j%, strLine$, strFullText$
    
    'Open App.Path & "\test.txt" For Output As #1
        For i = 1 To ListView1.ListItems.Count
            strLine = ListView1.ListItems(i).Text & vbTab
            For j = 1 To ListView1.ColumnHeaders.Count - 1
                strLine = strLine & ListView1.ListItems(i).SubItems(j) & vbTab
            Next j
            'Print #1, strLine
            strFullText = strFullText & strLine & vbNewLine
            strLine = ""
        Next i
        Printer.Print strFullText
        Printer.EndDoc
    'Close #1
    
    End Sub
    
    Private Sub Form_Load()
    Dim i&, j%
    
        With ListView1.ColumnHeaders
            .Add , "LI", "List Item"
            For j = 1 To 3
                .Add , "SI" & j, "Sub Item " & j
            Next j
            'Debug.Print ListView1.ColumnHeaders(1).Text
        End With
        
    '    Set LSI = ITM.ListSubItems.Add(, "Subitem1", "Subitem 1")
    '    LSI.ForeColor = vbBlue
    '    Set LSI = ITM.ListSubItems.Add(, "Subitem2", "Subitem 2")
    '    LSI.ForeColor = vbRed
    '    Set LSI = ITM.ListSubItems.Add(, "Subitem3", "Subitem 3")
    '    LSI.ForeColor = vbBlue
    '
    '    Set ITM = ListView1.ListItems.Add(, , "Listitem2")
    '    ITM.ForeColor = vbBlue
    '    Set LSI = ITM.ListSubItems.Add(, "Subitem1", "Subitem 1")
    '    LSI.ForeColor = vbRed
    '    Set LSI = ITM.ListSubItems.Add(, "Subitem2", "Subitem 2")
    '    LSI.ForeColor = vbBlue
    '    Set LSI = ITM.ListSubItems.Add(, "Subitem3", "Subitem 3")
    '    LSI.ForeColor = vbRed
    '
    '    Set ITM = ListView1.ListItems.Add(, , "Listitem3")
    '    ITM.ForeColor = vbGreen
    '    Set LSI = ITM.ListSubItems.Add(, "Subitem1", "Subitem 1")
    '    LSI.ForeColor = vbYellow
    '    Set LSI = ITM.ListSubItems.Add(, "Subitem2", "Subitem 2")
    '    LSI.ForeColor = vbGreen
    '    Set LSI = ITM.ListSubItems.Add(, "Subitem3", "Subitem 3")
    '    LSI.ForeColor = vbYellow
    
        For i = 1 To 20 '000
            Set ITM = ListView1.ListItems.Add(, , "Listitem " & i)
            For j = 1 To 3
                Set LSI = ITM.ListSubItems.Add(, "Subitem" & j, "Subitem " & j)
            Next j
        Next
        Set ITM = ListView1.ListItems(1)
        ITM.ForeColor = vbRed
        ListView1.Refresh
    
    End Sub
    
    Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
        ListView1.ListItems.Clear
    End Sub
    
    
    Private Sub ListView1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    Dim i%, cw&, tw$
    
        cw = ListView1.ColumnHeaders("LI").Width
        For i = 1 To ListView1.ListItems.Count
        tw = TextWidth(ListView1.ListItems(i).Text)
            'If Right(ITM.Text, 3) = "..." Then
            If cw <= tw Then
                ITM.ToolTipText = ITM.Text
                LSI.ToolTipText = ITM.Text
            End If
        Next i
    
    End Sub
    
    
    
    Public Sub TurnOffTips(frm As Form)
    '===================================
    Dim ctl As Control
    
    On Error Resume Next
    
        For Each ctl In frm.Controls
            ctl.ToolTipText = ""
        Next ctl
    
    End Sub
    David

    CodeGuru Article: Bound Controls are Evil-VB6
    2013 Samples: MS CODE Samples

    CodeGuru Reviewer
    2006 Dell CSP
    2006, 2007 & 2008 MVP Visual Basic
    If your question has been answered satisfactorily, and it has been helpful, then, please, Rate this Post!

  3. #3
    Join Date
    May 2010
    Posts
    12

    Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED

    How about this one:
    Code:
    Const LVM_FIRST As Long = &H1000
    Const LVM_GETITEMTEXT As Long = (LVM_FIRST + 45)
    
    Const LVIF_TEXT As Long = &H1
    
    Function GetItemText(hwnd As Long, Index As Long, SubItem As Long) As String
      Dim cTemp(255) As Byte
      Dim LRes As Long
      Dim mItem As LV_ITEM
      
      'ReDim cTemp(0 To 254)
      
      mItem.mask = LVIF_TEXT
      mItem.iSubItem = SubItem
      mItem.pszText = VarPtr(cTemp(0))
      mItem.cchTextMax = UBound(cTemp)
      
      LRes = SendMessageLong(hwnd, LVM_GETITEMTEXT, Index, VarPtr(mItem))
      GetItemText = Left$(StrConv(cTemp, vbUnicode), LRes)
      
    End Function

  4. #4
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED

    @David: You might have missed the fact, that only the hWnd of the ListView in question is available, not the COM interface.

    @Dagnarus: You might not have noticed, but what you propose here is about the same method as being used in the OPs posted code.
    He should have added, though, that the posted code is full functional on any other SysListView.
    The problem is to get the code working when a ListView is OWNERDRAWN, because in this case the LV_GETITEMTEXT message will not return anything.

    I was helping already struggling along for a while getting this to work, but without success, yet.

  5. #5
    Join Date
    Jun 2004
    Location
    NH
    Posts
    678

    Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED

    {msdn}"The iItemData member of the DRAWITEMSTRUCT structure contains the item data for the specified list-view item. "


    I have not ever used LVS_OWNERDRAWFIXED, but this code may be of use to at least help identify the state along the text.

    'Get the text of the selected Task Manager process item.
    Code:
    Option Explicit
    Const LVIF_TEXT As Long = 1
    Const LVIS_FOCUSED As Long = 1
    Const LVIS_SELECTED As Long = 2
    Const LVM_FIRST As Long = 4096
    Const LVM_GETITEMTEXT As Long = LVM_FIRST + 45
    Const LVM_GETITEMCOUNT As Long = LVM_FIRST + 4
    Const LVM_GETITEMSTATE As Long = (LVM_FIRST + 44)
    Const LVM_GETSELECTEDCOUNT As Long = (LVM_FIRST + 50)
    Const MAX_LVMSTRING As Long = 260
    Const MEM_COMMIT As Long = 4096
    Const MEM_DECOMMIT As Long = 16384
    Const MEM_RELEASE As Long = 32768
    Const PAGE_READWRITE As Long = 4
    Const PROCESS_VM_OPERATION As Long = 8
    Const PROCESS_VM_READ As Long = 16
    Const PROCESS_VM_WRITE As Long = 32
    Private Type LV_ITEM
       mask As Long
       iItem As Long
       iSubItem As Long
       State As Long
       stateMask As Long
       pszText As Long
       cchTextMax As Long
       iImage As Long
       lParam As Long
       iIndent As Long
    End Type
    Private Declare Function apiFindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
    Private Declare Function apiGetWindowThreadProcessId Lib "user32" Alias "GetWindowThreadProcessId" (ByVal hwnd As Long, ByRef lpdwProcessId As Long) As Long
    Private Declare Function apiOpenProcess Lib "kernel32" Alias "OpenProcess" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
    Private Declare Function apiVirtualAllocEx Lib "kernel32" Alias "VirtualAllocEx" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
    Private Declare Function apiVirtualFreeEx Lib "kernel32" Alias "VirtualFreeEx" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
    Private Declare Function apiWriteProcessMemory Lib "kernel32" Alias "WriteProcessMemory" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByRef lpBuffer As Any, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long
    Private Declare Function apiReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByRef lpBuffer As Any, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long
    Private Declare Function apiReadProcessMemoryStr Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As String, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long
    Private Declare Function apiCloseHandle Lib "kernel32" Alias "CloseHandle" (ByVal hObject As Long) As Long
    Private Declare Function apiSendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
    Private Declare Function apiSendMessageByVal Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    
    Private Sub Command1_Click()
       Me.Caption = GetSelectedListViewItem
    End Sub
    
    Public Function GetSelectedListViewItem() As String
        Dim hwnd As Long
        hwnd = GetProcessListHandle()
        If hwnd <> 0 Then
           Dim itemCount As Integer
           Dim i As Integer
           itemCount = apiSendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0)
            For i = 0 To itemCount - 1
              If GetListItemState(hwnd, i) <> 0 Then ' LVIS_SELECTED or  LVIS_FOCUSED or both
                 GetSelectedListViewItem = GetListViewText(hwnd, i, 0): Exit For
              End If
            Next
        End If
    End Function
    Private Function GetProcessListHandle() As Long
        Dim lhWndParent As Long
        Dim lhWndDialog As Long
        Dim lhWndProcessList As Long
        Dim i As Long
        lhWndParent = apiFindWindowEx(0, 0, vbNullString, "Windows Task Manager") 'get handle to the task manager
        For i = 1 To 7
            lhWndDialog = apiFindWindowEx(lhWndParent, lhWndDialog, vbNullString, vbNullString)
            If GetProcessListHandle = 0 Then GetProcessListHandle = apiFindWindowEx(lhWndDialog, 0, "SysListView32", "Processes")
        Next
    End Function
    Public Function GetListItemState(ByVal hwnd As Long, ByVal i As Long) As Long
        GetListItemState = apiSendMessageByVal(hwnd, LVM_GETITEMSTATE, i, LVIS_SELECTED)
    End Function
    Private Function GetListViewText(ByVal hwnd As Long, ByVal iItem As Long, ByVal subItem As Long) As String
        Dim pId As Long
        Dim pHandle As Long
        Dim pStrBufferMemory As Long
        Dim pMyItemMemory As Long
        Dim strLength As Long
        Dim strBuffer As String
        Dim LV As LV_ITEM
        Call apiGetWindowThreadProcessId(hwnd, pId)
        pHandle = apiOpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, pId)
        
        pStrBufferMemory = apiVirtualAllocEx(pHandle, 0, MAX_LVMSTRING, MEM_COMMIT, PAGE_READWRITE)
        
        LV.mask = LVIF_TEXT
        LV.iSubItem = subItem
        LV.pszText = pStrBufferMemory
        LV.cchTextMax = MAX_LVMSTRING
        
        pMyItemMemory = apiVirtualAllocEx(pHandle, 0, LenB(LV), MEM_COMMIT, PAGE_READWRITE)
        Call apiWriteProcessMemory(pHandle, pMyItemMemory, LV, Len(LV), 0)
        strLength = apiSendMessage(hwnd, LVM_GETITEMTEXT, iItem, ByVal pMyItemMemory)
        strBuffer = Space(strLength)
        Call apiReadProcessMemoryStr(pHandle, pStrBufferMemory, strBuffer, strLength, 0)
        Call apiVirtualFreeEx(pHandle, pStrBufferMemory, 0, MEM_DECOMMIT) 'important for complete release!!!
        Call apiVirtualFreeEx(pHandle, pMyItemMemory, 0, MEM_DECOMMIT)
        Call apiCloseHandle(pHandle)
        GetListViewText = strBuffer
    End Function
    
    Public Function GetSelectedListItems(ByVal hwnd As Long) As Long
         GetSelectedListItems = apiSendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, ByVal 0)
    End Function

    You must be an administrator to access listviews of other apps, and explorer, and task magager, especially on Vista/7.
    You may need to enable the SE_DEBUG_PRIVILEGE too.

  6. #6
    Join Date
    Jan 2006
    Location
    Fox Lake, IL
    Posts
    15,007

    Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED

    +1 (next time around)
    David

    CodeGuru Article: Bound Controls are Evil-VB6
    2013 Samples: MS CODE Samples

    CodeGuru Reviewer
    2006 Dell CSP
    2006, 2007 & 2008 MVP Visual Basic
    If your question has been answered satisfactorily, and it has been helpful, then, please, Rate this Post!

  7. #7
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED

    Right.
    It's amazing in how many different robes the same routine comes up again and again.
    To say again:
    Code:
    strLength = apiSendMessage(hwnd, LVM_GETITEMTEXT, iItem, ByVal pMyItemMemory)
    does not work on this specific Listview. we think because it is LVS_OWNERDRAWFIXED .
    That's the crux of this post.

    Concerning the consideration if we were running as an Administrator, I for my part WAS sure to run as Admin under my winXP when trying to read the ListView's Text items.
    Does not seem to be the reason.

  8. #8
    Join Date
    Jun 2004
    Location
    NH
    Posts
    678

    Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED

    Wof,
    I am aware of his question and the solution to use DRAWITEMSTRUCT.
    Did you try using that structure with that robe? That's the crux.

    The example was not meant to directly solve or show that structure, obviously, as stated.
    'Get the text of the selected Task Manager process item.
    Last edited by TT(n); June 9th, 2010 at 11:46 AM.

  9. #9
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED

    I see.
    We used LVM_GETITEMTXT, tried LVM_GETITEMA and read the text and tried LVN_GETDISPINFOA, all without succes.
    The latter, however, was possibly not correctly implemented, what still has to be checked.
    Your sample does not mention the DRAWITEMSTRUCT. I'm not sure of how to use that structure... maybe I should read up on that.

  10. #10
    Join Date
    Jun 2004
    Location
    NH
    Posts
    678

    Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED

    Yup, my sample didn't but the first sentence in that post did.
    I would try and combine the sample with that structure. Thats what was meant.

    If its possible, you'd probably invoke the items to be drawn, or redrawn, and send/or/catch the WM_DRAWITEM message, and DRAWITEMSTRUCT.

    Since the item data is contained within the DRAWITEMSTRUCT, then it's best to give up looking anywhere else at this point.

    This thread is discussed over at vbforums, but with no solution, or real mention of DRAWITEMSTRUCT, and WM_DRAWITEM.

    EDIT: On a side note, my sample uses MEM_DECOMMIT, instead of MEM_RELEASE, which works better, as in many cases to release commited memory.
    Last edited by TT(n); June 9th, 2010 at 11:48 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured