-
June 3rd, 2010, 10:24 PM
#1
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.
-
June 3rd, 2010, 11:32 PM
#2
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
-
June 4th, 2010, 04:26 AM
#3
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
-
June 4th, 2010, 09:44 AM
#4
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.
-
June 7th, 2010, 07:08 PM
#5
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.
-
June 7th, 2010, 07:39 PM
#6
Re: Get text of the item out of listview with LVS_OWNERDRAWFIXED
-
June 8th, 2010, 09:52 AM
#7
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.
-
June 8th, 2010, 01:45 PM
#8
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.
-
June 9th, 2010, 10:29 AM
#9
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.
-
June 9th, 2010, 10:41 AM
#10
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|