Working example of getting external listview items/text
Sorry but this seems neverending, I have not yet come accross a proper working example (code). Please somebody put up an example (code) that actually works! thankyou
Re: Working example of getting external listview items/text
I have tried everything, hax0rs function looked most promising but returns null strings. Its not owner drawn. This just simply cant be done, nobody can put up working code for this, only reaons why it wont work or code that doesnt work! sucks
Re: Working example of getting external listview items/text
You need to be a little more specific about what does not work.
I've read throught the other threads and simply stating that it returns null strings is not of any help.
Do you examine the return code from each API call to determine if any of your functions are returning an error?
The code posted does work, it is just not working in your situation so something specific about your program is not working.
Re: Working example of getting external listview items/text
From what i've read from others, they say you need to do it from within the external app's process memory. So I made this code that did just that. I tried it on Windows Explorer and it gave me the correct text.
i used c++ and vb.net
for the c++ dll:
Code:
#include "stdafx.h"
#include "Commctrl.h"
#pragma data_seg(".shared")
HWND _hTarget = 0;
HHOOK hook=0;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")
LVITEM *lvItem;
char lpText[255];
HINSTANCE hInst;
bool flag = true;;
//send LVM_GETITEMTEXT message from within external app's process
int getLVText(HWND hTarget)
{
lvItem = new LVITEM;
lvItem->iSubItem = 0;
lvItem->cchTextMax = 255;
lvItem->pszText = lpText;
int res = SendMessage(hTarget, LVM_GETITEMTEXT, 0, (long)lvItem);
if (res != 0)
{
flag = false;
MessageBox(NULL, lvItem->pszText, "", MB_OK); //messagebox shows the listview item string
return 1;
}
return 0;
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hInst = (HINSTANCE)hModule;
return TRUE;
}
LRESULT CALLBACK hookproc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(flag) //I put the flag so it only calls getLVText once
{
getLVText(_hTarget);
}
return ::CallNextHookEx(hook, nCode, wParam, lParam);
}
//these codes injects the dll into external app's process
__declspec(dllexport) int _stdcall installHook(HWND hTarget)
{
_hTarget = hTarget;
DWORD tid;
tid = ::GetWindowThreadProcessId(hTarget, 0);
hook = ::SetWindowsHookEx(WH_GETMESSAGE, hookproc, hInst, tid);
if (hook != NULL)
return 1;
return 0;
}
now for the vb.net code that calls the dll function installHook():
VB Code:
Public Declare Function installHook Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal hwnd As Integer) As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim hTarget As Integer 'the handle to the target ListView control, Im sure you could implement the code to get the handle
Dim res As Integer = installHook(hTarget)
End Sub
I hope getting the text of the listview items is what you wanted because it took me a while to do this. This is probably not the exact code you'll be using in your program, but it should give you an idea of how to get the text of the listview item.
Re: Working example of getting external listview items/text
My last comment was for anyone looking to do this.
You have shown one way to do it and I was commenting that the original way works well too and does not require C++.
Re: Working example of getting external listview items/text
oh. Well, I was just curious how that other way works. If you write the structure in the external process, then you sendmessage() using the pointer that you get from the writeprocessmemory(), which process memory is that pointer pointing to? The calling process or the external process? I'm a bit confused. When I sendmessage(), lets say WM_SETTEXT, the pointer to the buffer containing the string is pointing to an address in the calling process. But the method with WriteProcessMemory() appear to be pointing at an address in the external process.
Re: Working example of getting external listview items/text
You are correct, when you call SendMessage with the WM_SETTEXT message, the operating system recognizes the message and marshals the data for you from one process to the next as required.
User-defined messages are not marshalled since the OS does not know about them (since they are user defined).
Many messages that are specific to certain controls like the listview and RichTextbox are user-defined messages and the OS does not marshal them for you.
Re: Working example of getting external listview items/text
I attached the project with the dll.
Here is the vb.net code to call and use the dll.
VB Code:
Imports System.Runtime.InteropServices
Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Public Const WM_CHAR = &H102
Public Declare Function installHook Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal hwnd As Integer, ByVal vbhwnd As Integer) As Integer
Public Declare Function getItemText Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal index As Integer) As IntPtr
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim res As Integer = installHook(listViewHandle, Me.Handle.ToInt32)
PostMessage(child, WM_CHAR, 0, 0)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim strPtr As IntPtr = getItemText(itemIndex) '0 based
Dim str As String = Marshal.PtrToStringAnsi(strPtr)
Re: Working example of getting external listview items/text
its integer instead of long because in vb6, long is 4 bytes, while long in vb.net is 8 bytes. To make it work, substitute long with vb.net's integer, which is 4 bytes. The "child" part, you should replace that with the handle of your target listview.
Re: Working example of getting external listview items/text
I made changes to dll, so I attach new version.
Here is vb6 code:
VB Code:
Private Const WM_CHAR = &H102
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx 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 installHook Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal hwnd As Long) As Long
Private Declare Function getItemText Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal index As Long) As Long
Private Declare Function getItemCount Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" () As Long
Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" ( _
ByVal lpString1 As String, _
ByVal lpString2 As Long _
) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" ( _
ByVal lpString As Long _
) As Long
Private Sub Command1_Click()
Dim lvHwnd As Long 'handle to listview
Dim res As Integer
res = installHook(lvHwnd)
PostMessage lvHwnd, WM_CHAR, 0, 0 'this triggers dll to load
End Sub
Private Sub Command2_Click()
Dim lpString As Long
Dim strVal As String
Dim lenstr As Long
Dim itemCount As Long
itemCount = getItemCount() 'to get total item in listview
lpString = getItemText(0) 'to get text of item; 0-based
Re: Working example of getting external listview items/text
I attached a vb project that should let you understand how to make it work. Try it on a windows explorer folder and you'll see it works.(Make sure you drag that icon to the "listview" window and not just the parent window) If you use this program and still not get the listview items, then that listview class your trying to access is different from what i've been trying to access.
Re: Working example of getting external listview items/text
Whoooo hoooooooooooo after some messing got it to work!!!! wow I have to say a huge well done to you, I never thought I would see this working (getting listview items)
Heres a few more questions... (do forgive me)
Ok firstly how can I make the dll smaller?
Also, is there a away to get the tooltip text of the listview item as well as the text???
Can you get the listviews item image index ?
Thanksyou so much for all your time and effort and skill!!!!!
Re: Working example of getting external listview items/text
Yes, that's a bug that i've noticed. If you restart your computer, it goes back to normal. Can't really tell why, but as long as you get the idea of getting the item's text.
Re: Working example of getting external listview items/text
Sorry moeur just used spy++ and it works great, the above bug doesnt happen either (not getting new items), great code and thankyou. Do you know much about the lvmgettooltips? I did a search and only found one post about it (a post I made a while ago), just wondering how to get the items tooltip text and even get the icon it uses maybe.
Re: Working example of getting external listview items/text
I tried both the programs posted, they both work for me.. I was wondering if theres anyway to use them on other applications that have things that look like listboxes, but apparently they arent... they dont have the class SystemListView or whatever, and niether code workson them..
Re: Working example of getting external listview items/text
Originally Posted by bail3yz
The classname of the 'listbox' i want this to work on is "Afx:400000:28:10011:0:0" if that helps
Afx controls were created before Windows existed. Instead of using a Windows text property, the text is owner-drawn by the control. As far as Windows is concerned, the control has no text--just a picture that happens to look to you like text. I've seen attempts to monitor windows messages to try to detect what characters are being written, but nothing successful. As far as I know, the only way to read the text of an Afx control is using mouse or keyboard events to raise a copy event in the Afx control so that you can get the text from the clipboard or through optical character recognition.
Re: Working example of getting external listview items/text
Originally Posted by benmartin101
I attached a vb project that should let you understand how to make it work. Try it on a windows explorer folder and you'll see it works.(Make sure you drag that icon to the "listview" window and not just the parent window) If you use this program and still not get the listview items, then that listview class your trying to access is different from what i've been trying to access.
Many thanks for sharing this code. I tried to drag the icon to external listview to obtain the list but i get the follwoing error: