Solved

Getting Text From All TTreeView Nodes

Posted on 2002-03-03
10
574 Views
Last Modified: 2010-04-05
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
Comment
Question by:camou
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
10 Comments
 
LVL 15

Expert Comment

by:simonet
ID: 6838217


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
 

Author Comment

by:camou
ID: 6838301
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
 

Author Comment

by:camou
ID: 6838354
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 2

Expert Comment

by:cqhall
ID: 6838368
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
 

Author Comment

by:camou
ID: 6838386
cqhall,

I think you missed part of my question -- the TTreeView is part of a separate application.
0
 
LVL 1

Expert Comment

by:shibin78
ID: 6838540
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
 
LVL 20

Accepted Solution

by:
Madshi earned 300 total points
ID: 6838550
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
 
LVL 1

Expert Comment

by:OryxConLara
ID: 6839378
How bout using a global memory object? GloalLock, GlobalUnlock, etc.? it's ugly, but works.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6840926
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
 

Expert Comment

by:Javen
ID: 8157765
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

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

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.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…

735 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question