TVITEM auslesen

greggy80

Mitglied
Ich möchte aus einer TreeView aus einer Fremdanwendung ein Element (TVITEM) auslesen und insbesondere eigentlich nur die Bezeichnung des Elements ermitteln (pszText).

Testweise habe ich erstmal das aktuell markierte Element ermittelt.

Das HWND zu dem Tree existiert schon in dem Code, ist auch korrekt (mit WinSpy Adressen überprüft und schon einige andere SendMessage's erfolgreich ausprobiert).

Code:
        char szBuffer[100];
        TVITEM item;

        HTREEITEM t = TreeView_GetSelection(tree);
        cout << "Pointer zum Element: " << t << "\n\n";
        item.hItem = t;
        item.mask = TVIF_TEXT;
        item.pszText = szBuffer;
        item.cchTextMax = 100;
        cout << TreeView_GetItem(tree, &item);
        cout << "Text:" << item.pszText << "\n\n";
        cout << "Text:" << szBuffer << "\n\n";

Das Problem ist, dass kein Text ausgelesen wird. Die Funktion TreeView_GetItem liefert auch false, was mich etwas verwirrt. In HTREEITEM stehen aber Adressen drin, die sich auch ändern, wenn ich in der Liste im Fremdprogramm andere Elemente markiere.

Ist es vielleicht durch eine Sicherheitseinstellung nicht möglich, die Werte auszulesen?
Hab ich irgendetwas falsche gemacht?

Ich benutze WinXP SP2.

Vielen Dank schon mal für eure Hilfe,

David
 
Ich meine, da gibt es ein Problem, weil der Pointer für den Text in deinem Programmbereich liegt. Da hat das andere aber keinen Zugriff drauf.

Alloziiere einen Speicherbereich über GlobalAlloc, auf den Pointer sollte das andere Programm dann auch Zugriff haben. Nicht vergessen, danach wieder mit GlobalFree freigeben.
 
Kannst Du diese Geschichte mit GlobalAlloc etwas präzisieren. Ich weiß nicht genau, wie das dann funktionieren soll.

Ich habe hier einen weiteren Ansatz, der aber irgendwie auch nicht funktioniert:

Code:
    DWORD procid;
    HANDLE hproc;
    LPVOID pt, pt2;
    char buffer[BUFFER_LENGTH];
    TVITEM tv_item;
    HTREEITEM it;
    
    GetWindowThreadProcessId(tree, &procid);
    hproc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, procid);
    cout << "hProcess: " << hproc << endl;
    pt = VirtualAllocEx(hproc, NULL, sizeof(tv_item), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 
    pt2 = VirtualAllocEx(hproc, NULL, sizeof(buffer), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 
    cout << "VirtualAlloc address: " << pt << endl;
    cout << "VirtualAlloc address: " << pt2 << endl;
    
    tv_item.mask = TVIF_TEXT | TVIF_HANDLE ;
    tv_item.pszText = buffer;
    tv_item.cchTextMax = BUFFER_LENGTH;
    it=(HTREEITEM)SendMessage(tree, TVM_GETNEXTITEM, TVGN_ROOT, 0);
    tv_item.hItem = it; 
    
    WriteProcessMemory(hproc, pt, &tv_item, sizeof(tv_item), NULL);
    SendMessage(tree, TVM_GETITEM, 0, (LONG)pt);
    ReadProcessMemory(hproc, pt, &tv_item, sizeof(tv_item), NULL);
    ReadProcessMemory(hproc, pt2,&buffer, sizeof(buffer), NULL);
    VirtualFreeEx(hproc, pt, 0, MEM_RELEASE);
    CloseHandle(hproc);
    
    cout << "\"" << buffer << "\"";

Wäre auch ne super Hilfe, wenn jemand da den Fehler findet. Ich kenn mich mit dieser Geschichte "auf fremde Speicher-Adressen oder fremden Speicherplatz zugreifen" nicht so wirklich aus.
 
Ich hab mein Glück jetzt nochmal mit GlobalAlloc versucht, aber das klappt auch nicht. Bestimmt wieder so ein formaler dummer Fehler:

Code:
    HGLOBAL h_space = GlobalAlloc(0, 256);
    cout << h_space << endl << endl;
    tv_item.mask = TVIF_PARAM | TVIF_HANDLE | TVIF_TEXT;
    tv_item.pszText = (char*)h_space;
    tv_item.cchTextMax = 256;
    it=(HTREEITEM)SendMessage(hWnd3, TVM_GETNEXTITEM, TVGN_ROOT, 0);
    tv_item.hItem = it; 
    TreeView_GetItem(tree, &tv_item);
    
    cout << tv_item.pszText << endl;
    
    GlobalFree(h_space);


Da stehen dann immer ein paar merkwürdige Dinge in der Konsole, die aber nichts mit der Bezeichnung in der externen Anwendung zu tun haben...
 
Gleiches Problem in grün:

TreeView_GetItem ist nur ein Macro, daß ein SendMessage verpackt. Dabei wird das tv_item wieder als Pointer durchgereicht. Das tv_item müsste meine ich auch wieder in den global Speicher gepackt sein.
 
So, ich habe jetzt eine Lösung entwickelt. Für alle, die das gleiche Problem haben:

Code:
struct MY_TVITEM
{
   TVITEM it;
   char buf[BUFFER_LENGTH];
};

char* getTreeViewItemCaption(HWND tree, HTREEITEM item)
{
    DWORD procid;
    HANDLE hproc;
    MY_TVITEM tv_item;
    MY_TVITEM* ps;
    
    GetWindowThreadProcessId(tree, &procid);
    hproc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, procid);
    if (hproc == 0)
    {
        return 0;
    }
    
    ps = (MY_TVITEM*)VirtualAllocEx(hproc, NULL, sizeof(MY_TVITEM), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 
    if (ps == 0)
    {
        return 0;
    }
    
    tv_item.it.hItem = item;
    tv_item.it.mask = TVIF_HANDLE | TVIF_TEXT;
    tv_item.it.pszText = LPSTR(LPBYTE(ps)+(LPBYTE(tv_item.buf)-LPBYTE(&tv_item)));
    tv_item.it.cchTextMax = sizeof(tv_item.buf);
    
    if (!WriteProcessMemory(hproc, ps, &tv_item, sizeof(tv_item), NULL))
    {
        return 0;
    }
    
    if (!TreeView_GetItem(tree, ps))
    {
        return 0;
    }
    if (!ReadProcessMemory(hproc, ps, &tv_item, sizeof(tv_item), NULL))
    {
        return 0;
    }
    
    VirtualFreeEx(hproc, ps, 0, MEM_RELEASE);
    CloseHandle(hproc);
    
    return tv_item.buf;
}
 

Neue Beiträge

Zurück