AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Reading ListView of another app
Goto page 1, 2  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
Rajat



Joined: 28 Mar 2004
Posts: 1687

PostPosted: Thu Jun 07, 2007 11:36 pm    Post subject: Reading ListView of another app Reply with quote

The target control is TListView1 and the app is probably written in delphi.

This doesn't help:
ControlGet, ret, List,, TListView1, WindowName

The below cmd gives me the no. of rows:
SendMessage, 0x1004, 1, 0, TListView1, WindowName

I want to read the contents of that control as well.

I was looking into LVM_GETITEMTEXT but that probably gives the length of string.

any ideas?

Thanks!
_________________
Back to top
View user's profile Send private message
Helpy
Guest





PostPosted: Fri Jun 08, 2007 10:02 am    Post subject: Re: Reading ListView of another app Reply with quote

Rajat wrote:
This doesn't help:
ControlGet, ret, List,, TListView1, WindowName
I what sense? You get empty value?
Using SendMessage probably won't help, I suppose that's what Chris uses internally anyway.
And since the messages are above WM_USER, you have to use remote procedure access (RPA) methods to get the data.
But if ControlGet fails, it might be because user data is stored internally, not in the control. Is the list view owner drawn?
Back to top
Rajat



Joined: 28 Mar 2004
Posts: 1687

PostPosted: Fri Jun 08, 2007 11:49 am    Post subject: Re: Reading ListView of another app Reply with quote

Helpy wrote:
I what sense? You get empty value?
Using SendMessage probably won't help, I suppose that's what Chris uses internally anyway.
And since the messages are above WM_USER, you have to use remote procedure access (RPA) methods to get the data.
But if ControlGet fails, it might be because user data is stored internally, not in the control. Is the list view owner drawn?

yes i get empty value.

though TextCatch from http://www.skesoft.com/ catches the contents of the same control.
does that help?
_________________
Back to top
View user's profile Send private message
Helpy
Guest





PostPosted: Fri Jun 08, 2007 12:31 pm    Post subject: Reply with quote

I meant "In what sense", of course...
TextCatch is interesting, but I see it has a Scan mode, which might be an OCR module: if it can't get data by classical means, perhaps it scan it.
Or perhaps it can handle more components than AHK, Delphi components are quite commonplace anyway. I don't how much they differ from standard Windows components (wrappers).
Back to top
Rajat



Joined: 28 Mar 2004
Posts: 1687

PostPosted: Fri Jun 08, 2007 2:37 pm    Post subject: Reply with quote

another approach.. is there a way to make the control copy its contents to clipboard?
i read somewhere that for the apps that keep this in their own memory , its difficult to grab the control's contents... but the clipboard approach might work.
any ideas on this?
_________________
Back to top
View user's profile Send private message
Helpy
Guest





PostPosted: Fri Jun 08, 2007 3:13 pm    Post subject: Reply with quote

Only if the application allows this, there is no way to force it.
Back to top
Rajat



Joined: 28 Mar 2004
Posts: 1687

PostPosted: Fri Jun 08, 2007 3:50 pm    Post subject: Reply with quote

Sad
_________________
Back to top
View user's profile Send private message
Tigerite
Guest





PostPosted: Thu Aug 23, 2007 10:50 am    Post subject: Reply with quote

Hey, I have some code to read the text from an item in a TListView, maybe it'll help?

Code:

    GetListViewItemText(item_index, sub_index, ctrl_id, win_id)
    {
        ;const
        MAX_TEXT = 260

        VarSetCapacity(szText, MAX_TEXT, 0)
        VarSetCapacity(szClass, MAX_TEXT, 0)
        ControlGet, hListView, Hwnd, , %ctrl_id%, ahk_id %win_id%
        DllCall("GetClassName", UInt,hListView, Str,szClass, Int,MAX_TEXT)
        if (DllCall("lstrcmpi", Str,szClass, Str,"SysListView32") == 0 || DllCall("lstrcmpi", Str,szClass, Str,"TListView") == 0)
        {
            GetListViewText(hListView, item_index, sub_index, szText, MAX_TEXT)
        }

        return %szText%
    }

    GetListViewText(hListView, iItem, iSubItem, ByRef lpString, nMaxCount)
    {
        ;const
        NULL = 0
        PROCESS_ALL_ACCESS = 0x001F0FFF
        INVALID_HANDLE_VALUE = 0xFFFFFFFF
        PAGE_READWRITE = 4
        FILE_MAP_WRITE = 2
        MEM_COMMIT = 0x1000
        MEM_RELEASE = 0x8000
        LV_ITEM_mask = 0
        LV_ITEM_iItem = 4
        LV_ITEM_iSubItem = 8
        LV_ITEM_state = 12
        LV_ITEM_stateMask = 16
        LV_ITEM_pszText = 20
        LV_ITEM_cchTextMax = 24
        LVIF_TEXT = 1
        LVM_GETITEM = 0x1005
        SIZEOF_LV_ITEM = 0x28
        SIZEOF_TEXT_BUF = 0x104
        SIZEOF_BUF = 0x120
        SIZEOF_INT = 4
        SIZEOF_POINTER = 4

        ;var
        result := 0
        hProcess := NULL
        dwProcessId := 0

        if lpString <> NULL && nMaxCount > 0
        {
            DllCall("lstrcpy", Str,lpString, Str,"")
            DllCall("GetWindowThreadProcessId", UInt,hListView, UIntP,dwProcessId)
            hProcess := DllCall("OpenProcess", UInt,PROCESS_ALL_ACCESS, Int,false, UInt,dwProcessId)
            if hProcess <> NULL
            {
                ;var
                lpProcessBuf := NULL
                hMap := NULL
                hKernel := DllCall("GetModuleHandle", Str,"kernel32.dll", UInt)
                pVirtualAllocEx := DllCall("GetProcAddress", UInt,hKernel, Str,"VirtualAllocEx", UInt)
   
                if pVirtualAllocEx == NULL
                {
                    hMap := DllCall("CreateFileMapping", UInt,INVALID_HANDLE_VALUE, Int,NULL, UInt,PAGE_READWRITE, UInt,0, UInt,SIZEOF_BUF, UInt)
                    if hMap <> NULL
                        lpProcessBuf := DllCall("MapViewOfFile", UInt,hMap, UInt,FILE_MAP_WRITE, UInt,0, UInt,0, UInt,0, UInt)
                }
                else
                {
                    lpProcessBuf := DllCall("VirtualAllocEx", UInt,hProcess, UInt,NULL, UInt,SIZEOF_BUF, UInt,MEM_COMMIT, UInt,PAGE_READWRITE)
                }

                if lpProcessBuf <> NULL
                {
                    ;var
                    VarSetCapacity(buf, SIZEOF_BUF, 0)

                    InsertIntegerSL(LVIF_TEXT, buf, LV_ITEM_mask, SIZEOF_INT)
                    InsertIntegerSL(iItem, buf, LV_ITEM_iItem, SIZEOF_INT)
                    InsertIntegerSL(iSubItem, buf, LV_ITEM_iSubItem, SIZEOF_INT)
                    InsertIntegerSL(lpProcessBuf + SIZEOF_LV_ITEM, buf, LV_ITEM_pszText, SIZEOF_POINTER)
                    InsertIntegerSL(SIZEOF_TEXT_BUF, buf, LV_ITEM_cchTextMax, SIZEOF_INT)
   
                    if DllCall("WriteProcessMemory", UInt,hProcess, UInt,lpProcessBuf, UInt,&buf, UInt,SIZEOF_BUF, UInt,NULL) <> 0
                        if DllCall("SendMessage", UInt,hListView, UInt,LVM_GETITEM, Int,0, Int,lpProcessBuf) <> 0
                            if DllCall("ReadProcessMemory", UInt,hProcess, UInt,lpProcessBuf, UInt,&buf, UInt,SIZEOF_BUF, UInt,NULL) <> 0
                            {
                                DllCall("lstrcpyn", Str,lpString, UInt,&buf + SIZEOF_LV_ITEM, Int,nMaxCount)
                                result := DllCall("lstrlen", Str,lpString)
                            }
                }

                if lpProcessBuf <> NULL
                    if pVirtualAllocEx <> NULL
                        DllCall("VirtualFreeEx", UInt,hProcess, UInt,lpProcessBuf, UInt,0, UInt,MEM_RELEASE)
                    else
                        DllCall("UnmapViewOfFile", UInt,lpProcessBuf)
   
                if hMap <> NULL
                    DllCall("CloseHandle", UInt,hMap)
   
                DllCall("CloseHandle", UInt,hProcess)
            }
        }
        return result
    }

; *********************************
; Required functions - ExtractInteger, InsertInteger
; - original versions from Version 1.0.44.06 of the AutoHotkey help file
; by Chris Mallett
; // Renamed in case someone is using a modified version of these functions
; // somewhere else in their code
; *********************************
ExtractIntegerSL(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
   Loop %pSize%  ; Build the integer by adding up its bytes.
      result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
   if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
      return result  ; Signed vs. unsigned doesn't matter in these cases.
   ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
   return -(0xFFFFFFFF - result + 1)
}
; *********************************
InsertIntegerSL(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
   Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
      DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}
; *********************************


Back to top
Rajat



Joined: 28 Mar 2004
Posts: 1687

PostPosted: Tue Aug 28, 2007 10:16 am    Post subject: Reply with quote

thanks Tigerite for your help, but it doesn't work for me Sad
(i was out of town for a few days hence the late reply)
_________________
Back to top
View user's profile Send private message
Tigerite
Guest





PostPosted: Wed Aug 29, 2007 4:53 pm    Post subject: Reply with quote

Really, that's most odd, could you tell me which app you're trying to read the ListView of? I tried this with a pretty complicated one and it read it alright (although only the text, it didn't read checkboxes and the like within it)
Back to top
Rajat



Joined: 28 Mar 2004
Posts: 1687

PostPosted: Fri Aug 31, 2007 5:56 am    Post subject: Reply with quote

Tigerite,
its a custom s/w designed for my workplace. its definitely delphi, and the control is TListView1.

plz let me know if i'm using the script correctly. for testing i just added the following at top of your script :

x := GetListViewItemText(1, 1, "0x402be", "0x20318")
msgbox %x%

the hwnd values i took from my win-spy just before filling them in... i'd have scripted the code if this'd worked for me.

Thanks
_________________
Back to top
View user's profile Send private message
Tigerite
Guest





PostPosted: Fri Aug 31, 2007 4:15 pm    Post subject: Reply with quote

No, that's not quite how you use it; the ctrl_id should be the ClassNN, for example, TListView1.
Back to top
Tigerite
Guest





PostPosted: Fri Aug 31, 2007 4:16 pm    Post subject: Reply with quote

Or in other words, for your control:

x := GetListViewItemText(1, 1, "TListView1", "0x20318")
Back to top
Tigerite
Guest





PostPosted: Fri Aug 31, 2007 4:24 pm    Post subject: Reply with quote

Oh, one more thing; the indexes are zero-based.

Sorry the code isn't clearer, it does need a little tidying up.
Back to top
Rajat



Joined: 28 Mar 2004
Posts: 1687

PostPosted: Fri Aug 31, 2007 6:18 pm    Post subject: Reply with quote

thanks a lot Tigerite, it works perfectly now!
that was great help! Smile
_________________
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group