Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#1 GetListViewContents() broken for SysListView32 controls

open
nobody
5
2005-04-30
2005-04-30
Anonymous
No

Win32::GuiTest does not properly return the contents of
a SysListView32 with multiple columns using
GetListViewContents(). This subroutine only returns
the contents of the first column.

It would be nice if I could specify a column number
when using GetListViewContents() and get a list of the
contents of the specified column. Then I could get the
entire contents of the SysListView32 by making several
calls to GetListViewContents(). Of course, there would
need to be a way to figure out how many columns there
are in the SysListView32, maybe a GetColumnCount()
subroutine.

Discussion

  • PaulD
    PaulD
    2006-05-22

    Logged In: YES
    user_id=1413436

    is there any chance of getting this fixed soon? It seems
    that there has been no activity on this project for over a
    year. I'm guessing there's no chance but asking to be sure.

     
  • PaulD
    PaulD
    2006-05-22

    Logged In: YES
    user_id=1413436

    Two functions need to be changed. Here is the source if
    someone can (or wants to) apply it to CVS.

    Both are in GuiTest.xs

    // The following several routines all inject "ourself" into
    a remote process
    // and performs some work.
    int GetLVItemText(HWND hWnd, int iItem, int iColumn, char
    *lpString)
    {
    if (SetHook(hWnd,
    WM_LV_GETTEXT, "WM_LV_GETTEXT_RM") == NULL) {
    *lpString = NUL;
    return 0;
    }

    LVITEM lvitem;

    DWORD pid = 0;
    GetWindowThreadProcessId( hWnd, &pid );
    HANDLE hProcHnd = OpenProcess( PROCESS_ALL_ACCESS,
    FALSE, pid );

    LPVOID pLVI = VirtualAllocEx( hProcHnd, NULL, sizeof
    ( LVITEM ), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    LPVOID pBuffer = VirtualAllocEx( hProcHnd, NULL,
    MAX_DATA_BUF, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

    memset( &lvitem, '\0', sizeof(LVITEM) );
    lvitem.iItem = iItem;
    lvitem.iSubItem = iColumn;
    lvitem.pszText = ( char *)pBuffer;
    lvitem.cchTextMax = MAX_DATA_BUF;
    DWORD copied = 0;
    WriteProcessMemory( hProcHnd, pLVI, &lvitem, sizeof
    ( LVITEM ), &copied );
    SendMessage( hWnd, LVM_GETITEMTEXT, (WPARAM)iItem,
    (LPARAM)pLVI );
    ReadProcessMemory( hProcHnd, pBuffer, (LPVOID)
    g_szBuffer, MAX_DATA_BUF, &copied );
    VirtualFreeEx( hProcHnd, pBuffer, 0, MEM_RELEASE );
    VirtualFreeEx( hProcHnd, pLVI, 0, MEM_RELEASE );
    lstrcpy( lpString, g_szBuffer );

    return (int)strlen(lpString);
    }

    SV*
    GetListViewContents(hWnd)
    HWND hWnd;
    INIT:
    char szItem[MAX_DATA_BUF+1] = "";
    AV* results;

    results = (AV *)sv_2mortal((SV *)newAV());
    CODE:
    int iCount = GetLVItemCount(hWnd);
    int iCols = SendMessage(hWnd, LVM_GETITEMCOUNT, 0,
    0 );

    for (int i = 0; i < iCount; i++)
    {
    AV* pOneRow = newAV();
    for ( int j = 0; j < iCols; j++ )
    {
    GetLVItemText(hWnd, i, j, szItem);
    av_push( pOneRow, newSVpv(szItem,
    0) );
    }
    av_push( results, newRV((SV*) pOneRow));
    }
    RETVAL = newRV((SV *)results);
    OUTPUT:
    RETVAL

    There is a small problem in that it is one level of array
    more than I wanted. But it's better than having no access
    to the other columns.

    print $foo[0][0][0], "\n";
    print $foo[0][0][1], "\n";

    print $foo[0][1][0], "\n";
    print $foo[0][1][1], "\n";

    If you're good with perlguts, you could fix that.

    Is anyone reading this?