Sign in to follow this  
Followers 0
Wb-FreeKill

Anyone solved this problem?

19 posts in this topic

Has anyone solved the problem about reading a Listview from a second GUI window, when i do it now the msgbox are empty.. it works when the listview is in the main GUI

Share this post


Link to post
Share on other sites



Yes.. but its not pretty. I made a C++ function in a DLL to do it.

// given the hwnd for a listbox, put the contents into a pipe delimited string. however, if there are multiple versions of the same string, append a $$X occurance to the end of each one
const char EXPORT *ExtractListContents(HWND hwnd)
{
    static char results[4096];

    *results = '\0';

    long count = SendMessage(hwnd, LB_GETCOUNT, 0, 0);
    map<string, int> SeenList;

    for (long i = 0; i < count; ++i)
    {
        char item[256] = "";
        SendMessage(hwnd, LB_GETTEXT, i, (long) item);

        int cnt = 0;
        map<string, int>::iterator itr = SeenList.find(string(item));
        if (itr == SeenList.end())
        {
            SeenList.insert(make_pair(string(item), 1));
        } else {
            cnt = ++(*itr).second;
        }
        if (i != 0)
            strcat(results, "|");
        strcat(results, item);
        if (cnt >= 2)
        {
            char tmp[32];
            sprintf(tmp, "$$%d", cnt);
            strcat(results, tmp);
        }
    }
    return results;
}

Then some AutoIt wrapper functions for getting to the hwnd for the list:

; return the hwnd for the *active* control in the given window
Func GetActiveControl($title)
   WinActivate($title)
   return ControlGetHandle($title, "", ControlGetFocus($title))
Endfunc

Func ExtractListContents($hwnd)
    Local $foo = DllCall($g_socdll, "str", "ExtractListContents", "hwnd", $hwnd)
    If @error Then
        MsgBox(0, "Debug", "Error with DllCall(ExtractListContents)")
    Endif
    Return $foo[0]
Endfunc

I'm still working on the equivalent for a SysTreeView control...

Share this post


Link to post
Share on other sites

Hmm, wouldn't it be pretty easy to include in AutoIt so we can use it? i mean, alot of people are waiting for this to be fixed, including me... im on a large program, and have two parts of the program witch really need it, and i can't finish it because of this bug :)

Share this post


Link to post
Share on other sites

Ooops. I included the code for reading from a regular list box. To read from a ListView32 is just a *teensy* bit harder, since you cannot just grab memory across from one process to another. To work around this minor inconvience, I had to whip out the mega coding kungfu!! You have to actually attach yourself to the other process, so you can allocate memory in its process space to work with. Joy! This version put the contents in the clipboard instead of actually returning the string.

And no, sorry, I can't just give you my DLL I'm using! AutoIt Team: feel free to include this whever you like.

Example C++ code:

int EXPORT CopyListViewToClipboard(HWND hwnd, HWND hwndLV)
{
    //fprintf(stderr, "CopyListViewToClipboard(%p, %pd) called\n", hwnd, hwndLV);
    // If the window under the cursor isn't a ListView, we have nothing to do.
   if (hwndLV == NULL) return 0;


   // Get the count of items in the ListView control
   int nCount = ListView_GetItemCount(hwndLV);

   // Open a handle to the remote process's kernel object
   DWORD dwProcessId;
   GetWindowThreadProcessId(hwndLV, &dwProcessId);
   HANDLE hProcess = OpenProcess(
      PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 
      FALSE, dwProcessId);

   if (hProcess == NULL) {
      MessageBox(hwnd, __TEXT("Could not communicate with process"), 
         "CopyListViewToClipboard", MB_OK | MB_ICONWARNING);
      return 0;
   }

   // Prepare a buffer to hold the ListView's data.
   // Note: Hardcoded maximum of 10240 chars for clipboard data.
   // Note: Clipboard only accepts data that is in a block allocated with 
   //      GlobalAlloc using the GMEM_MOVEABLE and GMEM_DDESHARE flags.
   HGLOBAL hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, 
      sizeof(TCHAR) * 10240);
   LPTSTR pClipData = (LPTSTR) GlobalLock(hClipData);
   pClipData[0] = 0;

   // Allocate memory in the remote process's address space
   LV_ITEM* plvi = (LV_ITEM*) VirtualAllocEx(hProcess, 
      NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

   // Get each ListView item's text data
   for (int nIndex = 0; nIndex < nCount; nIndex++) {

      // Initialize a local LV_ITEM structure
      LV_ITEM lvi;
      lvi.mask = LVIF_TEXT;
      lvi.iItem = nIndex;
      lvi.iSubItem = 0; 
      // NOTE: The text data immediately follows the LV_ITEM structure
      //       in the memory block allocated in the remote process.
      lvi.pszText = (LPTSTR) (plvi + 1); 
      lvi.cchTextMax = 100; 

      // Write the local LV_ITEM structure to the remote memory block
      WriteProcessMemory(hProcess, plvi, &lvi, sizeof(lvi), NULL);

      // Tell the ListView control to fill the remote LV_ITEM structure
      ListView_GetItem(hwndLV, plvi);

      // If this is not the first item, add a carriage-return/linefeed
      if (nIndex > 0) lstrcat(pClipData, __TEXT("\r\n"));

      // Read the remote text string into the end of our clipboard buffer
      ReadProcessMemory(hProcess, plvi + 1, 
         &pClipData[lstrlen(pClipData)], 1024, NULL);
   }

   // Free the memory in the remote process's address space
   VirtualFreeEx(hProcess, plvi, 0, MEM_RELEASE);

   // Cleanup and put our results on the clipboard
   CloseHandle(hProcess);
   OpenClipboard(hwnd);
   EmptyClipboard();
#ifdef UNICODE
   BOOL fOk = (SetClipboardData(CF_UNICODETEXT, hClipData) == hClipData);
#else
   BOOL fOk = (SetClipboardData(CF_TEXT, hClipData) == hClipData);
#endif
   CloseClipboard();
   if (!fOk) {
      GlobalFree(hClipData);
      MessageBox(hwnd, __TEXT("Error putting text on the clipboard"), 
           "CopyListViewToClipboard", MB_OK | MB_ICONINFORMATION);
   }
   return (fOk) ? 1 : 0;
}

Share this post


Link to post
Share on other sites

O well, then i have to wait for someone to fix this damn problem.. i REALLY need it!

Share this post


Link to post
Share on other sites

Has anyone solved the problem about reading a Listview from a second GUI window, when i do it now the msgbox are empty.. it works when the listview is in the main GUI

<{POST_SNAPBACK}>

ControlListView won't work ?

Share this post


Link to post
Share on other sites

why can't we use the Dll, if we can view the source?? usually it's vice versa...


FootbaG

Share this post


Link to post
Share on other sites

why can't we use the Dll, if we can view the source?? usually it's vice versa...

<{POST_SNAPBACK}>

Without any understandig of c++, i tried to compile the code, and some code are missing, thats why

Share this post


Link to post
Share on other sites

ControlListView won't work ?

<{POST_SNAPBACK}>

@Wb-FreeKill

Have you even tried ControlListView ?

It should work.

Share this post


Link to post
Share on other sites

@Wb-FreeKill

Have you even tried ControlListView ?

It should work.

<{POST_SNAPBACK}>

O im sorry, didn't see your post, ill take a look at it, thx :)

Share this post


Link to post
Share on other sites

O im sorry, didn't see your post, ill take a look at it, thx  :)

<{POST_SNAPBACK}>

I don't really know how to use this in this case, i do not understand the help file..

Share this post


Link to post
Share on other sites

I don't really know how to use this in this case, i do not understand the help file..

<{POST_SNAPBACK}>

What are you trying to retreive from the ListView ?

Share this post


Link to post
Share on other sites

What are you trying to retreive from the ListView ?

<{POST_SNAPBACK}>

Okay, i have two GUI's, Main GUI and Second GUI. The Listview is created in the second GUI, so i would like to have a msgbox telling me what thay Listviewitem im clicking on contains.

Like:

If $Button Then

Msgbox(0,"Test",$GuiCtrlRead($Listview)) ; from the second GUI

EndIf

Share this post


Link to post
Share on other sites

Here is a quick example on how to get the Items from a First and second GUI with ControlListview

#include <GUIConstants.au3>

$GUI_1 = GUICreate("listview items",220,250, 0,0,-1,$WS_EX_ACCEPTFILES)
GUISetBkColor (0x00E0FFFF) ; will change background color

$listviewGUI1 = GuiCtrlCreateListView ("col1  |col2  |col3  ",10,10,200,150);,$LVS_SORTDESCENDING)
$button1 = GuiCtrlCreateButton ("GUI1GetAllItems",10,170,100,20)
$button2 = GuiCtrlCreateButton ("GUI2GetAllItems",110,170,100,20)
$item1=GuiCtrlCreateListViewItem("GUI1item1|GUI1item2|GUI1item3",$listviewGUI1)
$item2=GuiCtrlCreateListViewItem("GUI1item2_1|GUI1item2_2|GUI1item2_3",$listviewGUI1)
$item3=GuiCtrlCreateListViewItem("GUI1item3_1|GUI1item3_2|GUI1item3_3",$listviewGUI1)
GuiSetState()

$GUI_2 = GUICreate("listview items",220,250, 300,0,-1,$WS_EX_ACCEPTFILES)
GUISetBkColor (0x00E0FFFF) ; will change background color

$listviewGUI2 = GuiCtrlCreateListView ("col1  |col2  |col3  ",10,10,200,150);,$LVS_SORTDESCENDING)
GuiCtrlCreateListViewItem("GUI2item1|GUI2item2|GUI2item3",$listviewGUI2)
GuiCtrlCreateListViewItem("GUI2item2_1|GUI2item2_2|GUI2item2_3",$listviewGUI2)
GuiCtrlCreateListViewItem("GUI2item3_1|GUI2item3_2|GUI2item3_3",$listviewGUI2)
GuiSetState()

Do
  $msg = GuiGetMsg ()    
   Select
      Case $msg = $button1
         $ItemCount = ControlListView ( $GUI_1, "", "SysListView321","GetItemCount")
         For $i = 0 To $ItemCount -1
            MsgBox(0,"",ControlListView ( $GUI_1, "", "SysListView321","GetText", $i))
         Next
      Case $msg = $button2
         $ItemCount = ControlListView ( $GUI_2, "", "SysListView321","GetItemCount")
         For $i = 0 To $ItemCount -1
            MsgBox(0,"",ControlListView ( $GUI_2, "", "SysListView321","GetText", $i))
         Next
   EndSelect
Until $msg = $GUI_EVENT_CLOSE

Share this post


Link to post
Share on other sites

Try this:

#include <GUIConstants.au3>

$GUI_1 = GUICreate("listview items",220,250, 0,0,-1,$WS_EX_ACCEPTFILES)
GUISetBkColor (0x00E0FFFF) ; will change background color

$listviewGUI1 = GuiCtrlCreateListView ("col1  |col2  |col3  ",10,10,200,150);,$LVS_SORTDESCENDING)
$button1 = GuiCtrlCreateButton ("GUI1GetSelected",10,170,100,20)
$button2 = GuiCtrlCreateButton ("GUI2GetSelected",110,170,100,20)
GuiCtrlCreateListViewItem("GUI1item1|GUI1item2|GUI1item3",$listviewGUI1)
GuiCtrlCreateListViewItem("GUI1item2_1|GUI1item2_2|GUI1item2_3",$listviewGUI1)
GuiCtrlCreateListViewItem("GUI1item3_1|GUI1item3_2|GUI1item3_3",$listviewGUI1)
GuiSetState()

$GUI_2 = GUICreate("listview items",220,250, 300,0,-1,$WS_EX_ACCEPTFILES)
GUISetBkColor (0x00E0FFFF) ; will change background color

$listviewGUI2 = GuiCtrlCreateListView ("col1  |col2  |col3  ",10,10,200,150);,$LVS_SORTDESCENDING)
GuiCtrlCreateListViewItem("GUI2item1|GUI2item2|GUI2item3",$listviewGUI2)
GuiCtrlCreateListViewItem("GUI2item2_1|GUI2item2_2|GUI2item2_3",$listviewGUI2)
GuiCtrlCreateListViewItem("GUI2item3_1|GUI2item3_2|GUI2item3_3",$listviewGUI2)
GuiSetState()

Do
    $msg = GuiGetMsg ()
    Select
        Case $msg = $button1
            If ControlListView ( $GUI_1, "", "SysListView321","GetSelectedCount") > 0 Then
                MsgBox(0,"",ControlListView ( $GUI_1, "", "SysListView321","GetText", ControlListView ( $GUI_1, "", "SysListView321","GetSelected")))
            EndIf
        Case $msg = $button2
            If ControlListView ( $GUI_2, "", "SysListView321","GetSelectedCount") > 0 Then
                MsgBox(0,"",ControlListView ( $GUI_2, "", "SysListView321","GetText", ControlListView ( $GUI_2, "", "SysListView321","GetSelected")))
            EndIf
    EndSelect
Until $msg = $GUI_EVENT_CLOSE

Share this post


Link to post
Share on other sites

Well that looks pretty easy, thx for your help! :)

Share this post


Link to post
Share on other sites

all i do is save the data added to the list into an array, then i read from the array and not the list.

works for me.


Valik Note Added 19 October 2006 - 08:38 AMAdded to warn level I just plain don't like you.

Share this post


Link to post
Share on other sites

No need to do that anymore, the problem has been fixed, see my previous post for example.


SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0