Solved

Getting Text From All TTreeView Nodes

Posted on 2002-03-03
10
561 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
Comment Utility


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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
cqhall,

I think you missed part of my question -- the TTreeView is part of a separate application.
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 1

Expert Comment

by:shibin78
Comment Utility
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
Comment Utility
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
Comment Utility
How bout using a global memory object? GloalLock, GlobalUnlock, etc.? it's ugly, but works.
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
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
Comment Utility
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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
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…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

772 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

10 Experts available now in Live!

Get 1:1 Help Now