how to Get itemtext of the list item out of listview with LVS_OWNERDRAWFIXED
Printable View
how to Get itemtext of the list item out of listview with LVS_OWNERDRAWFIXED
What do you mean by "Out of listview"? If you can explain exactly what do you want to do then probably it will be easier to answer your query appropriately.
Rohit:
Constant
LVS_OWNERDRAWFIXED
Description
The owner window can paint items in report view. The list-view control sends a WM_DRAWITEM message to paint each item; it does not send separate messages for each subitem. The iItemData member of the DRAWITEMSTRUCT structure contains the item data for the specified list-view item.
If you just want the item text then why not use the following?
Code:Option Explicit
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const LVM_GETNEXTITEM = (LVM_FIRST + 12)
Private Const LVNI_SELECTED = &H2
LVM_GETITEMTEXT may not work with ownerdrawn controls? May want to try LVM_GETITEM and use the LVIF_TEXT flag in the LVITEM structure. Please read the remarks of that message. If you get anything other than all zeros when you call ReadProcessMemory, then things are looking up.
is this right ???Code:Option Explicit
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, ByRef lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" (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 VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Const PAGE_READWRITE As Long = &H4
Private Const MEM_RESERVE As Long = &H2000&
Private Const MEM_RELEASE As Long = &H8000&
Private Const MEM_COMMIT As Long = &H1000&
Private Const PROCESS_VM_OPERATION As Long = &H8
Private Const PROCESS_VM_READ As Long = &H10
Private Const PROCESS_VM_WRITE As Long = &H20
Private Const LVIF_TEXT As Long = &H1
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_GETITEMCOUNT As Long = (LVM_FIRST + 4)
Private Const LVM_GETHEADER As Long = (LVM_FIRST + 31)
Private Const LVM_GETITEMTEXTA As Long = (LVM_FIRST + 45)
Private Const HDI_TEXT As Long = &H2
Private Const HDM_FIRST As Long = &H1200
Private Const HDM_GETITEMCOUNT As Long = (HDM_FIRST + 0)
Private Const HDM_GETITEMA As Long = (HDM_FIRST + 3)
Private Const LVN_FIRST As Long = -100
Private Const LVN_GETDISPINFOA As Long = (LVN_FIRST - 50)
Private Type LVITEM ' 40 bytes
mask As Long
iItem As Long
iSubItem As Long
state As Long
stateMask As Long
pszText As Long ' String pointer
cchTextMax As Long
iImage As Long
lParam As Long
iIndent As Long
End Type
Private Type HDITEM ' 36 bytes
mask As Long
cxy As Long
pszText As Long ' String pointer
hbm As Long
cchTextMax As Long
fmt As Long
lParam As Long
iImage As Long
iOrder As Long
End Type
Private Type NMHDR
hWnd As Long
idFrom As Long
code As Long
End Type
Private Type NMLVDISPINFO
hdr As NMHDR
item As LVITEM
End Type
Private Sub Form_Load()
EnumChildWindows GetDesktopWindow, AddressOf EnumDesktopWindow, ByVal 0&
If hSysListView <> 0 Then
SysListView32ToCSV hSysListView, "C:\MyFile.txt", ","
MsgBox "DONE"
Else
MsgBox "ERROR"
End If
End Sub
'----------------------
'// IF YOU LIKE LIST ALL SysListView32 THEN
Private Sub List1_DblClick()
SysListView32ToCSV List1.ItemData(List1.ListIndex), "C:\MyFileq.txt", ","
End Sub
'-------------------------------
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(260) 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
For i = 0 To ColumnCount - 1
WriteIPCMemory ProcessHandle, MemAddr1, VarPtr(HeaderItem), 36&
lRtn = SendMessage(HeaderhWnd, HDM_GETITEMA, i, ByVal MemAddr1)
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
With ListViewItem
.cchTextMax = 260&
.mask = LVIF_TEXT
.pszText = MemAddr2
End With
'doing the same to NMLVDISPINFO
With DI.item
.cchTextMax = 260&
.mask = LVIF_TEXT
.pszText = MemAddr2
End With
DI.hdr.hWnd = Me.hWnd
DI.hdr.idFrom = 0 'not sure what ID I should put here
DI.hdr.code = 0 'also not sure what code should go here
For i = 0 To ListCount - 1
sLine = vbNullString
For j = 0 To ColumnCount - 1
ListViewItem.iSubItem = j
DI.item.iSubItem = j
'DI.hdr.code = j
'WriteIPCMemory ProcessHandle, MemAddr1, VarPtr(ListViewItem), 40&
WriteIPCMemory ProcessHandle, MemAddr1, VarPtr(DI), Len(DI)
'lRtn = SendMessage(hListView, LVM_GETITEMTEXTA, i, ByVal MemAddr1)
lRtn = SendMessage(hListView, LVN_GETDISPINFOA, i, ByVal MemAddr1)
If lRtn > 0& Then
ReadIPCMemory ProcessHandle, MemAddr2, VarPtr(aText(0)), 260&
sLine = sLine & Left$(StrConv(aText, vbUnicode), lRtn) & IIf(j < ColumnCount - 1, Delimiter, vbNullString)
End If
Next
Print #FF, sLine
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
'----------By LaVolpe ---------------------
Private Function OpenIPCProcess(ByVal ProcessID As Long) As Long
OpenIPCProcess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, ProcessID)
End Function
Private Function CreateIPCMemory(ByVal nrBytes As Long, ByRef ProcessHandle As Long) As Long
If ProcessHandle Then CreateIPCMemory = VirtualAllocEx(ProcessHandle, ByVal 0&, ByVal nrBytes, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
End Function
Private Sub WriteIPCMemory(ByVal ProcessHandle As Long, ByVal MemoryAddress As Long, ByVal srcMemory As Long, ByVal srcLength As Long)
WriteProcessMemory ProcessHandle, MemoryAddress, srcMemory, srcLength, 0
End Sub
Private Sub ReadIPCMemory(ByVal ProcessHandle As Long, ByVal MemoryAddress As Long, ByVal dstMemory As Long, ByVal dstLength As Long)
ReadProcessMemory ProcessHandle, MemoryAddress, dstMemory, dstLength, 0
End Sub
Private Sub DestroyIPCMemory(ByVal ProcessHandle As Long, ByVal MemoryAddress As Long)
VirtualFreeEx ProcessHandle, ByVal MemoryAddress, 0&, MEM_RELEASE
End Sub
Private Sub CLoseIPCProcess(ByVal ProcessHandle As Long)
CloseHandle ProcessHandle
End Sub
Doesn't look right. For this test, I'd recommend rem'ing out your DI related lines and just use ListViewItem.
Per MSDN documentation I linked to, if it works, one of two things could happen:
1) The text is copied to MemAddr2
2) .pszText is changed to where the text can be found and .cchTextMax should be the text length. I am making an assumption on that last part, the documentation does not say if .cchTextMax will be changed.
Here is a modified loop for your listitems. Worth a try; worse cases: 1) crash, 2) still get no text. Changed loop to just do 1 item for the test
Edited: You'll have to change the aText(260) declaration to just aText(). Also include constant for LVM_GETITEMA As Long = (LVM_FIRST + 5)Code: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)
If lRtn <> 0& Then
ReadIPCMemory ProcessHandle, MemAddr1, VarPtr(ListViewItem), 40&
' 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)
End If
Next
Next
i tried the code u gave first with aText(260) and commenting ReDim aText(0 To ListViewItem.cchTextMax) i managed to get the column header which i was getting earlier and 1 blank line
then i tried the code with aText() and un-commenting ReDim aText(0 To ListViewItem.cchTextMax) i got a blank text file this time no column headers
The test was for the list items. You can get the column headers so I'd ignore that for now. BTW: If aText() is dynamic, just add this before your column headers loop: ReDim aText(0 to 260).
As for the blank line, what is the value of lRtn? Is it returning non-zero?
In post #9 above, what does lRtn have when this line is executed: If lRtn <> 0& Then
Again, not interested in the column headers, you know you can get those ok. It's the list items you can't get, correct? Please ensure your loop is identical to the one in post #9, especially the SendMessage call.
is this right what im doing as per ur instructions and if it is right then im getting 1 as the value for lrtnCode: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
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)
ReDim aText(0 To 260)
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
With ListViewItem
.cchTextMax = 260&
.mask = LVIF_TEXT
.pszText = MemAddr2
End With
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&
' 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)
End If
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
Just for the testing, I rem'd out stuff related to the headers. I also moved the ReDim statement up in the list. Try this version just to see if you are getting anything from the listivew items.
You may want to rename your original SysListView32ToCSV to SysListView32ToCSV_ORIGINAL and then paste the above as a new routine.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)
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
Oh, here's something that needs to be changed too. With LV_GETITEMA, lRtn is no longer the length of the string as it was with LV_GETITEMTEXTA. So your sLine line needs to be tweaked:
Assuming sLine is returning something, the listitem may not be correct and have extra characters on it. If that is the case, it is easy to fix. But the big question is, do you get anything from the listview?Code:sLine = sLine & Left$(StrConv(aText, vbUnicode), _
ListViewItem.cchTextMax) & IIf(j < ColumnCount - 1, Delimiter, vbNullString)
What was the result of the 2 Debug lines?
Debug.Print lRtn
Debug.Print vbTab; ListViewItem.pszText; MemAddr2; ListViewItem.cchTextMax
debug.print lrtn=1
Debug.Print vbTab; ListViewItem.pszText; MemAddr2; ListViewItem.cchTextMax = 46465024 46465024 260
there is a tab added in the output of Debug.Print vbTab; ListViewItem.pszText; MemAddr2; ListViewItem.cchTextMax
Well, looking at the debug.print results, it is telling me that the pzsText member of the UDT is not being changed, nor is the text length. The lRtn=1 tells me the listview responded to the SendMessage call.
In a previous thread, I asked if the listview had the LVS_OWNERDATA style set? Does it?
If not, I would think you should get something. Here's another test you can try
1. Try to locate a owner drawn listview project
2. Run it and then try your code against that one.
If you get text back from that one, then your code works.
Otherwise you may have no option but to believe the strings are maintained by the application and not the listview.
this gave me Ownerdrawn Listview? FalseCode:If Not (MemAddr1 = 0& Or MemAddr2 = 0&) Then
Debug.Print "Ownerdrawn Listview? "; CBool(GetWindowLong(hListView, GWL_STYLE) And LVS_OWNERDATA)
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)
also there is one application in vb which dose the same thing with the syslistview i want to get data from
Ok, I'm running out of ideas. And if the app is keeping the listitems and subitems separately, there is probably nothing you can do.
Example: I create a listivew I don't want people to take data out of. Hmmm, what could I do? Here's an idea. I make it owner drawn, pass null strings as list items and subitems. I then keep the real listitems and subitems in a custom class of mine. Now when the listview asks to paint a listitem, I get the text from my custom class and paint it myself. Sneaky but effective and a lot of work I would think.
Now it is possible that the code doesn't work. I'd definitely try with another owner-drawn listview if you can find one easily enough; or try to create your own owner-drawn listview for a test.
If you have the source code, sure. If its fetching data, then a listview must be providing it. So, in that case either the fetching code is wrong above or maybe you are not looking at the correct listview?
What is the return value of GetWindowLong, passing GWL_STYLE? Curious.
Edited: And this could be a player, however unlikely. Let's say everything is custom drawn and that's why you don't get the text (assuming aText() array are all zeros). It is possible with other custom C++ like dlls that one can hook common drawing APIs like TextOut, DrawText, etc. Once those are hooked in the listview's process, any strings sent to them can be interecepted and read/modified. This is truly complicated and may be out in left field.
Using Spy++ on that other VB app might show what messages it is sending to that listview. I don't know how helpful it will be.
are you there LaVolpe
Somedays, I'm not sure myself.
I don't use WinRar. Also, I was asking for the value of the GetWindowLong() call so I can see the actual style bits.
Last but not least, I'm near the end of my ability to assist. A while back I did try to download and use the app you are having issues with, but without success. So, unless someone else can help or identify anything improper with your code or a different solution, it may be up to you to do a lot of research and trial and error.
I was asking for the value of the GetWindowLong() call so I can see the actual style bits.
how do i get these
Debug.Print GetWindowLong(hListView, GWL_STYLE)
I was hoping that one of the style bits would give me another clue, but it doesn't. I have to bow out and hope someone else can assist. Maybe that log (again I don't use WinRar) might be useful as a place to start looking. You said you had another app that does get the info from that listview, maybe using Spy++ on that other app might help; maybe not.
From that GWL_STYLE value, your listview has these styles: WS_CHILD, WS_VISIBLE, LVS_OWNERDRAWFIXED, LVS_REPORT, LVS_SHOWSELALWAYS, LVS_SINGLESEL
If its possible, you'd probably invoke the items to be drawn, or redrawn, and send/or/catch the WM_DRAWITEM message, and DRAWITEMSTRUCT.
I don't think looking anywhere else will yield item text, as quoted in post #4.
I also want to find a solution if its possible, so I'll need a test app.
What application has a listview with the LVS_OWNERDRAWFIXED style?
I can't see how WM_DRAWITEM would be useful in this case. The DRAWITEMSTRUCTURE associated with that message cannot contain strings or string pointers, based on: WM_DRAWITEM is only sent with ListViews in Report style and is only sent once per list item, not for sub items. So, when received the control must draw the entire row and logic dictates that the .itemData member of the DrawItemStructure will not contain a string pointer since a single listview row can contain multiple strings.
EDITED: Using SPY++, is the listview subclassed? When looking at the window procedure for the window it will have (Subclassed) after the procedure address. I would expect the listview's parent to be subclassed so it can process WM_DrawItem messages. Just curious.
I think you would have to subclass the window, or catch the message with hook. vbaccelerator has a working example for buttons, but no luck yet.
Otherwise it may not be directly possible.
attaching the spy++ output for the thirdparty's syslistview32. the application from which i want to get dataQuote:
EDITED: Using SPY++, is the listview subclassed? When looking at the window procedure for the window it will have (Subclassed) after the procedure address. I would expect the listview's parent to be subclassed so it can process WM_DrawItem messages. Just curious.
Was that list a result of your app trying to get the data or the other app that works? Attach similar results for the other scenario: your app or the other one that works so we can see if there is any major difference.
Also, what about the subclassing (post #31)?
sorry for no replies but i was down on bad health
there is one software called screenscraper studio which does this
gurus pls help me
It's quite a while sins I wrote somethin in VB6 but I have answered a similar question a couple of years ago.
If you have retrieved a correct process id this is how I answered the question.
I hope it can help you.Code:Dim n As Long
Dim txt As String
Dim lvi As LVITEM
Dim pMem As Long
Dim pBuffer As Long
Dim lpNumberOfBytesWritten As Long
txt = Space(128)
pMem = VirtualAllocEx(hProcess, 0, Len(lvi), MEM_COMMIT, PAGE_READWRITE)
pBuffer = VirtualAllocEx(hProcess, 0, Len(txt), MEM_COMMIT, PAGE_READWRITE)
lvi.pszText = pBuffer
lvi.cchTextMax = Len(txt)
lvi.mask = LVIF_TEXT + LVIS_SELECTED
n = SendMessage(hwnd, LVM_GETNEXTITEM, -1, LVNI_SELECTED)
lvi.iItem = n
n = WriteProcessMemory(hProcess, ByVal pMem, lvi, Len(lvi), lpNumberOfBytesWritten)
n = SendMessage(hwnd, LVM_GETITEM, 0&, ByVal pMem)
n = ReadProcessMemory(hProcess, ByVal pMem, ByVal lvi, Len(lvi), lpNumberOfBytesWritten)
n = ReadProcessMemory(hProcess, ByVal pBuffer, ByVal txt, Len(txt), lpNumberOfBytesWritten)
Form1.List1.AddItem "Item " & lvi.iItem & ": " & txt
VirtualFreeEx hProcess, pMem, len(lvi), MEM_RELEASE
VirtualFreeEx hProcess, pBuffer, len(txt), MEM_RELEASE
CloseHandle hProcess
Here are several situations for owner-draw ListView where content in not stored in ListViewItem structure:
Final - vhGrid! - 1.7 (Update July 07)
http://www.planet-source-code.com/vb...67906&lngWId=1
Situation 1. Headers are stored normally but ListItems are stored in class array vs ListViewItem structure.
Situation 2. Headers are stored normally but ListView is in virutal mode where the items are requested via event.
Private Sub ucVHGrid1_eVHVirtualAccess(ByVal lRow As Long, _
ByVal lCell As Long, _
sText As String, _
lIcon As Long)
Final 2.4.6- HyperList NGEN! The last Listview control you will ever need..
http://www.planet-source-code.com/vb...66732&lngWId=1
frmDataBaseMode.frm supplies the items via callback:
Private Sub ucHyperListNG1_eHIndirect(ByVal iItem As Long, _
ByVal iSubItem As Long, _
ByVal fMask As Long, _
sText As String, _
iImage As Long)
'/* Indirect callback method:
'/* if using an external database, this
'/* is where reecords would be passed
'/* by index into the list
'/* iItem would map to the record number
'/* iSubItem 0 is the list item, and subsequent
'/* would map to record fields intended for subitems
'/* the sText is byref, pass the item text with this var
'/* iImage could correspond to a field maintaining icon indece
'* Note to all the 'database gurus' who can't figure out a callback..
'* example of usage would be something like this:
'Dim i As Long
' rs.Move iItem, 1
' i = 0
' Dim f As Variant
' For Each f In rs.Fields
' If i = iSubItem Then
' sText = f.Value
' Exit For
' End If
' i = i + 1
' Next
Has anyone attempted to implement LVS_OWNERDRAWVARIABLE in Listview? (I know it has been done in ListBox), I searched and found: [There is no LVS_OWNERDRAWVARIABLE style (does not exist) for ListView only LVS_OWNERDRAWFIXED style].
in post #24
rohitb: are you there LaVolpe
in post #25
LaVolpe: Somedays, I'm not sure myself.
:: You gotta love the fox "LaVolpe" ::
LucasMKG
paging through vbForums archives
hoping all is well with 'rohitb' ..(based on post #35...even though its an old thread)