Solved

Getting Text From All TTreeView Nodes

Posted on 2002-03-03
10
562 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
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
 
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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.

911 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now