Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 602
  • Last Modified:

Getting Text From All TTreeView Nodes

Can someone show me how to get the text of all TTreeNodes (parents and children) from a TTreeView of another application and then place the text of each node into the Lines (1 node's text per line) of a TMemo?

Note: I already can locate the TTreeView's Handle (HWND), using FindWindow, etc, so do not worry about that part.
0
camou
Asked:
camou
1 Solution
 
simonetCommented:


Since you already know the TreeView's handle, here's a simple code that does what you want:

uses CommCtrl;

procedure TForm1.Button1Click(Sender: TObject);
var
  Ct, i : integer;
  item : TTVItem;
begin
  Ct := TreeView_GetCount(aHandle);
  for i := 0 to Ct-1 do
  begin
     with Item do
     begin
       hItem := i;
       mask := TVIF_PARAM;
     end;
     TreeView_GetItem(aHandle, item);
     Memo1.Lines.Add(item.pszText);
  end;
end;


Yours,

Alex
0
 
camouAuthor Commented:
I cannot get the code to compile. The compiler gives the error:

"Incompatable types 'Integer and HTREEITEM'"


procedure TForm1.Button1Click(Sender: TObject);
var
 Ct, i : integer;
 item : TTVItem;
begin
 Ct := TreeView_GetCount(aHandle);
 for i := 0 to Ct-1 do
 begin
    with Item do
    begin
      hItem := i;   // << Error Here
      mask := TVIF_PARAM;
    end;
    TreeView_GetItem(aHandle, item);
    Memo1.Lines.Add(item.pszText);
 end;
end;


0
 
camouAuthor Commented:
I figured out why the compiler was complaining, had to cast the i variable as a HTREEITEM. However, the code does not seem to work as it was, so i changed

hItem := HTREEITEM(i); // stops the compiler from complaining
mask := TVIF_PARAM; // doesn't add anything to the TMemo

to

hItem := HTREEITEM(i);
mask := TVIF_TEXT;

which, adds a line for each node to the TMemo, but none of the lines have the node's text.

0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
cqhallCommented:
What about this...

procedure TForm1.Memo1DblClick(Sender: TObject);
var
 i: integer;
begin
 memo1.Lines.clear;
 for i:=0 to treeview1.items.count-1 do
 begin
  memo1.lines.add(treeview1.items[i].text);
 end;
end;

You could add indents by looking at the items[i].level property and add "x" spaces per Level (0,1,2 ...)

Chuck Hall
0
 
camouAuthor Commented:
cqhall,

I think you missed part of my question -- the TTreeView is part of a separate application.
0
 
shibin78Commented:
I think you must use some methods to inject to the host application process. For you just have the handle of the treeview, when you use any API to do with the handle, you need to be in the same process. For details about how to inject to other process, please refer to <<Advanced Windows>> Forth Edition.
0
 
MadshiCommented:
shibin78 is right. These TTreeView APIs end up in messages being sent. Those messages contain pointers and pointers are private to each process. So if you call a TTreeView API which transports a pointer to the TTreeView control, this simply won't work. You won't get the text back. Instead the TTreeView control will write it's strings to wild memory, which may end up in strange behaviour/crashes or in access violations.

You have 2 choices: The usual way is to write a little dll, which you inject into the destination process. This dll can then easily call the APIs and transport the data back to your process (e.g. by using WM_COPYDATA).
A more intelligent way would be to allocate memory in the context of the other process and read it by using ReadProcessMemory. But allocating memory in another process is only possible (by documented means) in NT based systems.

In case you want to have it easy (well, I mean "less difficult", this kind of stuff is never "easy"), you might want to try my package madCodeHook. It contains a function which lets you easily inject a dll into any running 32bit process:

http://help.madshi.net/Data/DllInjecting.htm#InjectLibrary

Or alternatively you could look at my package madRemote, which offers a function, which can allocate memory in other processes in NT *and* win9x based systems:

http://help.madshi.net/Data/AllocFreeMemEx.htm#AllocMemEx

Both packages are free for non-commercial usage, don't come with sources in this version, though...

Regards, Madshi.
0
 
OryxConLaraCommented:
How bout using a global memory object? GloalLock, GlobalUnlock, etc.? it's ugly, but works.
0
 
MadshiCommented:
No, it does not work. Global* was only able to allocate shared memory in 16bit Windows. In 32bit Windows Global* memory is always private to each process...

Regards, Madshi.
0
 
JavenCommented:
Hi all,

I have followed this thread and have come across the same problem as mentioned.

I have started a new thread of my own asking for an exmaple of how to do this, with 500 points available. I am desperate to get this working, and will increase the point if necessary.

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20553406.html

Cheers,

Javen
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now