Solved

Applist

Posted on 1999-01-14
39
193 Views
Last Modified: 2010-04-06
the findwindow() funcion finds the handle of window by given caption.
what if there are 2 or more such windows?
by this chance, also : How to list all the task that are listed in alt+ctrl+del menu?
0
Comment
Question by:duke_n
  • 14
  • 11
  • 10
  • +1
39 Comments
 
LVL 20

Expert Comment

by:Madshi
ID: 1356490
Do you have Delphi 4? I hope so...
Then you can download the enumStuff unit from my homepage "http://www.madshi.com" in the "sources" section.
If you don't have Delphi 4:   :-(((
Perhaps you should download the unit nevertheless, you should be able to find out how it is done.
With my unit you can enumerate Windows and Processes and Threads (and other stuff).

When there are more than 1 window with the same caption, FindWindow returns the first one it finds. If you want to know all windows with that caption, you'll have to enumerate all windows...

To list all the tasks in the alt+ctrl+del menu you must
(1) list all processes, then
(2) find the caption of the main window of each process.

You can do both with my unit...

Any questions? Please ask...   :-)

Regards, Madshi.
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356491
I have delphi3 and need to know how to do it "nakely", w/o no units.
Some code pls
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1356492
here is a little unit which collects windows and childwindows (handle, Caption ControlClass) and displayed it in a treeview, not ready, not perfect, of course but it shows a way

unit fw_tree_u;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Grids, ComCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    TV1: TTreeView;
    Splitter1: TSplitter;
    Panel2: TPanel;
    EClass: TEdit;
    EText: TEdit;
    EHandle: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure TV1Click(Sender: TObject);
    procedure TV1Change(Sender: TObject; Node: TTreeNode);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

type
 TTextBuf = array[0..100] of Char;
 TTNData = Record
             ClassName : String[100];
             Caption   : String[100];
             Handle    : LongInt;
           end;

var
 TNDPtr : ^TTNData;
 TextBuf: TTextBuf;
 TextBufPtr: PChar = TextBuf;
 ActNode : TTreeNode;

Function MyClassName(CHandle : THandle) : String;
begin
  GetClassName(CHandle,TextBufPtr,100);
  Result := strpas(TextBufPtr);
end;

Function ControlCaption(CHandle : THandle) : String;
begin
  Getwindowtext(CHandle,TextBufPtr,100);
  Result := strpas(TextBufPtr);
end;

Procedure FindChilds(Depth : Integer; ParentW: THandle; Node : TTreeNode);
var
  ch1: THandle;
  s : String;
  i : Integer;
  TActNode : TTreeNode;
begin
  s := '';
  for i := 0 to depth do s := s + ':-';
  ch1 := GetWindow(ParentW, GW_Child);
  while not(ch1=0) do
  begin
    New(TNDPTr);
    TNDPtr^.ClassName := MyClassName(ch1);
    TNDPtr^.Caption := ControlCaption(ch1);
    TNDPtr^.Handle := ch1;
    TActNode := Form1.TV1.Items.AddChildObject(Node,TNDPtr^.ClassName,TNDPtr);
    ch1 := GetNextWindow(ch1, GW_HWNDNEXT);
  end;
  ch1 := GetWindow(ParentW, GW_Child);
  while not(ch1=0) do
  begin
    if GetWindow(ch1, GW_Child)<>0 then FindChilds(depth + 1,ch1,TactNode);
    ch1 := GetNextWindow(ch1, GW_HWNDNEXT);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  SHandle,
  FHandle : THandle;
begin
  SHandle := GetActiveWindow;
  while (SHandle <> 0) do
  begin
    SHandle :=  GetWindow(SHandle,GW_HWNDNEXT);  {Looking Foward the Z-Order}
    if SHandle <> 0 then
    begin
      New(TNDPTr);
      TNDPtr^.ClassName := MyClassName(SHandle);
      TNDPtr^.Caption := ControlCaption(SHandle);
      TNDPtr^.Handle := SHandle;
      ActNode := TV1.Items.AddChildObject(TV1.TopItem,TNDPtr^.ClassName,TNDPtr);
      FindChilds(0,SHandle,ActNode);
    end;
  end;
  SHandle := GetActiveWindow;
  while (SHandle <> 0) do
  begin
    SHandle := GetWindow(SHandle,GW_HWNDPREV); {Looking Backward the Z-Order}
    if SHandle <> 0 then
    begin
      New(TNDPTr);
      TNDPtr^.ClassName := MyClassName(SHandle);
      TNDPtr^.Caption := ControlCaption(SHandle);
      TNDPtr^.Handle := SHandle;
      ActNode := TV1.Items.AddChildObject(TV1.TopItem,TNDPtr^.ClassName,TNDPtr);
      FindChilds(0,SHandle,ActNode);
    end;
  end;
end;


procedure TForm1.TV1Click(Sender: TObject);
begin
  If TV1.Selected = TV1.TopItem then
  begin
    EClass.Text := '';
    EText.Text := '';
    EHandle.Text := '0';
  end
  else
  begin
    if TV1.Selected <> nil then
    begin
      TNDPtr := TV1.Selected.Data;
      EClass.Text := TNDPtr^.ClassName;
      EText.Text := TNDPtr^.Caption;
      EHandle.Text := inttostr(TNDPtr^.Handle);
    end
    else
    begin
      EClass.Text := '';
      EText.Text := '';
      EHandle.Text := '0';
    end;
  end;
end;

procedure TForm1.TV1Change(Sender: TObject; Node: TTreeNode);
begin
  TV1Click(self);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  showwindow(strtoint(ehandle.text),SW_SHOW);
end;

end.


meikl
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356493
Ok, duke_n, you want to have a list of processes like in the ctrl+alt+del tasklist. I will do that for you for Delphi 3 :-(((, please tell me for win95 or for winNT?

Regards, Madshi.
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356494
95/98
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356495
//to meikl.
No, man.
I didn't wanna list every stupid edit or combo-box.
only the windows in <ALT>+<CTRL>+<DEL>.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356496
Ok, here comes my solution. It shows more than the processes in the tasklist, because the tasklist hides all those processes that have called "RegisterServiceProcess". I can't check that. (At least I don't know how). But I hope that doesn't matter.
Just add a TListBox and a TButton component on a new form and assign the OnClick event handler for the button.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    procedure RefreshListBox;
    function GetMainWindowCaption(pid: cardinal) : string;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

type  TProcessEntry32 = record
                          dwSize              : DWORD;
                          cntUsage            : DWORD;
                          th32ProcessID       : DWORD;        // this process
                          th32DefaultHeapID   : DWORD;
                          th32ModuleID        : DWORD;        // associated exe
                          cntThreads          : DWORD;
                          th32ParentProcessID : DWORD;        // this process's parent process
                          pcPriClassBase      : integer;      // Base priority of process's threads
                          dwFlags             : DWORD;
                          szExeFile           : array [0..MAX_PATH-1] of char;    // Path
                        end;
const TH32CS_SnapProcess = 2;
var   CreateToolhelp32Snapshot :
        function (dwFlags,th32ProcessID: cardinal) : cardinal; stdcall
        = nil;
      Process32First :
        function (hSnapshot: cardinal; var lppe: TProcessEntry32) : bool; stdcall
        = nil;
      Process32Next :
        function (hSnapshot: cardinal; var lppe: TProcessEntry32) : bool; stdcall
        = nil;

function TestToolhelpFunctions : boolean;
var c1 : cardinal;
begin
  c1:=GetModuleHandle('kernel32');
  @CreateToolhelp32Snapshot:=GetProcAddress(c1,'CreateToolhelp32Snapshot');
  @Process32First          :=GetProcAddress(c1,'Process32First'          );
  @Process32Next           :=GetProcAddress(c1,'Process32Next'           );
  result:=(@CreateToolhelp32Snapshot<>nil) and (@Process32First<>nil) and (@Process32Next<>nil);
end;

procedure TForm1.RefreshListBox;
var c1    : cardinal;
    pe    : TProcessEntry32;
    s1,s2 : string;
begin
  listBox1.Clear;
  if not TestToolhelpFunctions then begin
    MessageBox(0,'Toolhelp functions not available.','Error...',0);
    exit;
  end;
  c1:=CreateToolHelp32Snapshot(TH32CS_SnapProcess,0);
  try
    pe.dwSize:=sizeOf(pe);
    if Process32First(c1,pe) then
      repeat
        s1:=ExtractFileName(pe.szExeFile);
        s2:=ExtractFileExt(s1);
        Delete(s1,length(s1)+1-length(s2),maxInt);
        s2:=GetMainWindowCaption(pe.th32ProcessID);
        if s2='' then listBox1.items.add(s1) else listBox1.items.add(s2);
      until not Process32Next(c1,pe);
  finally CloseHandle(c1) end;
end;

var ew_pid : cardinal;
    ew_mwc : string;
function EnumWindowsProc(hwnd: cardinal; lParam: integer) : LongBool; stdcall;
var cpid : cardinal;
begin
  result:=true;
  GetWindowThreadProcessID(hwnd,@cpid);
  if (ew_pid=cpid) and (GetWindow(hwnd,GW_OWNER)=0) and (GetParent(hwnd)=0) and IsWindowVisible(hwnd) then begin
    SetLength(ew_mwc,MAX_PATH);
    SetLength(ew_mwc,GetWindowText(hwnd,pchar(ew_mwc),MAX_PATH));
    result:=false;
  end;
end;

function TForm1.GetMainWindowCaption(pid: cardinal) : string;
begin
  ew_pid:=pid; ew_mwc:='';
  EnumWindows(@EnumWindowsProc,0);
  result:=ew_mwc;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  RefreshListBox;
end;

end.

Regards, Madshi.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356497
Hmm. Another thing would be to list only the buttons in the taskbar. That's possible, too, of course.
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1356498
YOu can use EnumWindows() and or FindWindow(nil, nil);

 TWindowInfo = class(TObject)
  public
    Handle : HWND;
  end;

var WindowsList : TStringList; //Don't forget to create this TStringList..

Procedure GetVisibleWindowsProc(WinHandle : HWND);
Var
  P : Array[0..256] Of Char;
  WinObj : TWindowInfo;
Begin
  P[0] := #0;
  GetWindowText(WinHandle, P, 255);
  WinObj := TWindowInfo.Create;
  WinObj.Handle := WinHandle;
  if P[0] <> #0 and IsWindowVisible(WinHandle) then
    fWindowsList.AddObject(P, WinObj);
End;

procedure GetVisibleWindows;
Var
  WindowHandle2 : HWND;
Begin
  fWindowsList.Clear;
  WindowHandle2 := FindWindow(nil, nil);
  GetVisibleWindowsProc(WindowHandle2);
  While (WindowHandle2 <> 0) do begin
    WindowHandle2 := GetWindow(WindowHandle2, GW_HWNDNEXT);
    GetVisibleWindowsProc(WindowHandle2);
  end;
end;

Then you can do something like this...

GetVisibleWindows;
ListBox1.Items.Assign(WindowsList);

That's all...

-Viktor
--Ivanov
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1356499
Well duke_n,

that was only a sample how to get, and not the code which you want to get, of course.
the other experts now have better comments/answers as my comment.

meikl
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356500
say, what about the handles of thy windows?
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356501
What do you mean?
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356502
Please explain it in detail. What do you need? And for which purpose?
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1356503
well here it goes...

Handles : array[1..100] of HWND;

Handles[i] := TheHandle;

That's all...

Please give more details so we know what you need...
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356504
kretzschmar's answer was the closest.
I'd like to put'em all in a tree-view,
and I want to be able to retrieve the handle of the window,
when I click on the acoording item in the treeview.

and ofcourse I don't want to list every stupid combobox (and dialogbox if possible): only the forms(and I don't mean only delphi forms)

Regards,
 Nukem
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1356505
You can add objects to the TTreeView, so you can create your own object like so...

type
  THandleInfo = object
    Handle : HWND;
  end;

now when you add each caption of the window to the TreeView you just add your object at that place also... when someone click on the treeview you just extract that object and there you have the handle to the window....

Hope this helps...

-Viktor
--Ivanov
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356506
DukeNukem,

not every process does have a window handle. That means if you enumerate only the window handles, you would miss some processes. Is that really ok for your?
If not, you'll have to use process enumeration function (see my last answer). It would be no problem to enhance this answer to add the window handles (of the programs that have any) to the list.

Regards, Madshi.
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356507
//to viktornet
I don't understand a bit in this area, so gimme some code please.

//to madshi
I don't want to enumerate handles(errr),
but the windows in alt+ctrl+del menu with their sub-windows(I mean: branch "delphi 3" will have subbranches:"Delphi 3 - Project1", "Object Inspector", "Form1", and "unit1.pas"),

and a possibility to retrieve the handles of the windows(when clickin' on an item in treeview).
am I askin' for too much?
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1356508
hi duke_n,

look at my example,
the handle (and some other) will be stored in the Node.Data to each node.
Be free to experiment with this.

But remember Madhis comment, some processes shown by alt+ctrl+del have no window-handle.

meikl

meikl
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 1

Author Comment

by:duke_n
ID: 1356509
//TO kretzschmar
as I said I don't understand a bit of this code, so I can't play with it :-(((.

so my only hope that you will write me some code.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356510
DukeNukem,

the problem is that we all (Viktor, meikl and me) are not so sure what you want to have exactly (or am I wrong, Viktor and meikl?).
You're speaking all the time about the ctrl+alt+del tasklist. But then you speak about the windows you want to have. That are two pair of shoes! In the ctrl+alt+del tasklist are PROCESSES listed. Each process can have NO, one or more windows.
So I could easily adjust my last answer in a way that it shows all processes and shows for each process, if it has a window and which one (title and handle). No problem. But then you're speaking of a TREEVIEW with windows. But you don't want to have all the edit windows etc.
So please tell is in detail what you really want to know:
(1) Do you want a list of processes (with the main window for each process that has one) or
(2) A tree kind of list of all "real" windows (note, that some processes don't have windows at all, or at least no "real" windows, so these processes would not appear in such a list.)

I guess, you want to have (2), but that has almost nothing to do with the ctrl+alt+del tasklist...

You understand our problems now?

Regards, Madshi.
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356511
OK.
I don't want a list, I want a tree.
main branches will represent main windows(and handles) of alt+ctrl+del processes. and if these processes will have more than one windows(not windowed controls!!!) then they will be represented in sub-branches of main branches.
If they don't have windows at all then I don't need'em.

capeesh?

Regards,
 Duke Nukem
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356512
I mean for example:if there is a branch "Delphi 3" it will have following sub-branches:

"Delphi 3 - Project1"
"Object Inspector"
"Form1"
"unit1.pas"

//if I just opened delphi or didn't for example change unit's name
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356513
meikl, Viktor,

does anyone of you want to write the code for Duke? I've not much time in the moment. But if you don't want to do that, I'll see what I can do...   :-)

Regards, Madshi.
0
 
LVL 10

Expert Comment

by:viktornet
ID: 1356514
Well, I sure don't have time... and I will have even less time from now on, since I gotta study harder for school... I had some minimal time last semeter and I didn't study for my school studies... ****... i hate school, when it's not about programming... well that's life...

-Viktor
--Ivanov
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1356515
Well friends,

i will see what i can do in the coming week, my little example-code lists all windows-handles, which will be found in the z-order, too much for duke_n. i will search for a way, which will filters only windows and reject controls.

meikl
0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356516
Hi meikl,

some tips for you:
(1) List only windows with "GetParent(wnd)=0" (that should filter the windows and reject controls)
(2) I would suggest something like:
    process1 - window1
             - window2
    process2 - window1
             - window2
             - window3
    You can determine which windows belong to the same process by using GetWindowThreadProcessID (the processID must be the same).

Regards, Madshi.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1356517
Hi madshi,

thanks for the tips, i will take them over.

meikl ;-)

0
 
LVL 20

Expert Comment

by:Madshi
ID: 1356518
No prob... I'm just glad that you're writing the code. I've not much time at the moment...   :-)

Regards, Madshi.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1356519
Hi,

here is my first try,
i go following way (its like a way which Madshi last answered), collect processes, (addon : collect Modules (mostly Dlls) used by Process), collect threads, collect windows from the threads. The WindowsFilter is to simple at the Moment, there is some work to do (any suggestions?), i do here only remove the windows without text, so that some real windows could  be removed, which have no title, and some controls could be stand, which have a title.

well then tried it out

unit enumw_u;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, tlhelp32, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    TreeView1: TTreeView;
    procedure Button1Click(Sender: TObject);
  private
    Procedure GetThreads(ProcessID : DWord; ANode : TTreenode);
    Procedure GetModules(ProcessID : DWord; ANode : TTreenode);
    Procedure GetProcesslist;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

Var
  WNode : TTreeNode;
  WName : Array[0..100] of char;


Function TWCallBack(H : THandle; V : Longint) : longBool; stdcall;
begin
  if GetParent(H) = 0 then
  begin
    GetwindowText(H,@WName[0],100);
    Form1.TreeView1.Items.AddChild(WNode,StrPas(@WName[0]));
  end;
  Result := True;
end;

Procedure TForm1.GetThreads(ProcessID : DWord; ANode : TTreenode);
var
  ThreadEntry32 : TThreadEntry32; {Defined in TlHelp32}
  TLHandle : THandle;
begin
  TLHandle := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  if Thread32First(TLHandle,ThreadEntry32) then
  begin
    if ThreadEntry32.th32OwnerProcessID = ProcessID then
    Begin
      WNode := TreeView1.Items.AddChild(Anode,IntToStr(ThreadEntry32.th32ThreadID));
      EnumThreadWindows(ThreadEntry32.th32ThreadID,@TWCallBack,0);
    end;
    while Thread32Next(TLHandle,ThreadEntry32) do
    begin
      if ThreadEntry32.th32OwnerProcessID = ProcessID then
      begin
        WNode := TreeView1.Items.AddChild(Anode,IntToStr(ThreadEntry32.th32ThreadID));
        EnumThreadWindows(ThreadEntry32.th32ThreadID,@TWCallBack,0);
      end;
    end;
  end;
  CloseHandle(TLHandle);
end;


Procedure TForm1.GetModules(ProcessID : DWord; ANode : TTreenode);
var
  MLHandle : Thandle;
  ModuleEntry32 : TModuleEntry32; {Defined in TlHelp32}
begin
  MLHandle := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessID);
  if Module32First(MLHandle,ModuleEntry32) then
  begin
    TreeView1.Items.AddChild(Anode,strPas(@ModuleEntry32.szModule[0]));
    while Module32Next(MLHandle,ModuleEntry32) do
      TreeView1.Items.AddChild(Anode,strPas(@ModuleEntry32.szModule[0]))
  end;
  CloseHandle(MLHandle);
end;

Procedure TForm1.GetProcesslist;
var
  ANode, ANode2 : TTreeNode;
  PLHandle : Thandle;
  ProcessEntry32 : TProcessEntry32; {Defined in TlHelp32}
begin
  PLHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if Process32First(PLHandle,ProcessEntry32) then
  begin
    Anode := TreeView1.Items.Add(Nil,strPas(@ProcessEntry32.szExeFile[0]));
    ANode2 := TreeView1.Items.AddChild(Anode,'Modules');
    GetModules(ProcessEntry32.th32ProcessID,ANode2);
    ANode2 := TreeView1.Items.AddChild(Anode,'Threads');
    GetThreads(ProcessEntry32.th32ProcessID,ANode2);
    while Process32Next(PLHandle,ProcessEntry32) do
    begin
      Anode := TreeView1.Items.Add(Nil,strPas(@ProcessEntry32.szExeFile[0]));
      ANode2 := TreeView1.Items.AddChild(Anode,'Modules');
      GetModules(ProcessEntry32.th32ProcessID,ANode2);
      ANode2 := TreeView1.Items.AddChild(Anode,'Threads');
      GetThreads(ProcessEntry32.th32ProcessID,ANode2);
    end;
  end;
  CloseHandle(PLHandle);
end;

Procedure CleanUpTree(Nodes : TTreeNodes);
Var TmpNode : TTreeNode;
begin
  {CleanUp Windows without Text (most Controls)}
  WNode := Nodes.GetFirstNode;
  While WNode <> Nil do
  begin
    If WNode.Text = '' then
    begin
      TmpNode := WNode.Getnext;
      WNode.Delete;
      WNode := TmpNode;
    end
    else
      WNode := WNode.GetNext;
  end;
  {Cleanup Threads without windows}
  WNode := Nodes.GetFirstNode;
  while WNode <> Nil do
  begin
    If (WNode.Parent <> NIL) then
      If (WNode.Parent.Text = 'Threads') and
         (WNode.GetFirstChild = Nil) then
      begin
        TmpNode := WNode.Getnext;
        WNode.Delete;
        WNode := TmpNode;
      end
      else
        WNode := WNode.GetNext
    else WNode := WNode.GetNext;
  end;
    {Cleanup ThreadBranch without Threads}
  WNode := Nodes.GetFirstNode;
  while WNode <> Nil do
  begin
    If (WNode.Text = 'Threads') and
       (WNode.GetFirstChild = Nil) then
    begin
      TmpNode := WNode.Getnext;
      WNode.Delete;
      WNode := TmpNode;
    end
    else
      WNode := WNode.GetNext
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Treeview1.Items.Clear;
  GetProcessList;
  CleanUpTree(TreeView1.Items);
end;

end.

meikl ;-)
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356520
This is closer.
except:
1.when I press the button twice or more it somewhy stucks...???

2.How to get handles of those who have'em(btw: I don't need the others unless they are processes with windows(all windows have handles- right???))  ?
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356521
Adjusted points to 200
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356522
that's it...
here are the changes I ask you to do:
1.I don't need the "Modules" branch.
2.Only the contents of ""Thread"--><some interesting number>" branch, w/o the ""Thread"--><some interesting number>" branches themselves.
3.and ofcourse the ability to get their handles.

Shall I increase the points once again?
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1356523
Hi duke_n,

the changes comes today.
Points, this is your own decission.

meikl
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1356524
Hi Duke_n,

here are the changes, requested on your last comment, the Handle is stored in the DataOption of the Node.

Your questions above

1. couldn't reproduce this, it is stable on my pc.
2. yes all windows have a handle

unit enumw2_u;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, tlhelp32, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    TreeView1: TTreeView;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure TreeView1Click(Sender: TObject);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
  private
    Procedure GetThreads(ProcessID : DWord);
    Procedure GetProcesslist;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

Var
  WNode2: TTreeNode = Nil; {intern Global defined for multiple use}
  WNode : TTreeNode = Nil; {intern Global defined for multiple use}
  WName : Array[0..100] of char;
  TheWinHandle : THandle = 0; {intern Global defined for intern global Access}

Function TWCallBack(H : THandle; V : Longint) : longBool; stdcall;
begin
  if GetParent(H) = 0 then
  begin
    GetwindowText(H,@WName[0],100);
    WNode2 := Form1.TreeView1.Items.AddChild(WNode,StrPas(@WName[0]));
    WNode2.Data := Ptr(H); {Store the Handle in the DataOption}
  end;
  Result := True;
end;

Procedure TForm1.GetThreads(ProcessID : DWord);
var
  ThreadEntry32 : TThreadEntry32; {Defined in TlHelp32}
  TLHandle : THandle;
begin
  TLHandle := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  if Thread32First(TLHandle,ThreadEntry32) then
  begin
    if ThreadEntry32.th32OwnerProcessID = ProcessID then
      EnumThreadWindows(ThreadEntry32.th32ThreadID,@TWCallBack,0);
    while Thread32Next(TLHandle,ThreadEntry32) do
      if ThreadEntry32.th32OwnerProcessID = ProcessID then
        EnumThreadWindows(ThreadEntry32.th32ThreadID,@TWCallBack,0);
  end;
  CloseHandle(TLHandle);
end;

Procedure TForm1.GetProcesslist;
var
  PLHandle : Thandle;
  ProcessEntry32 : TProcessEntry32; {Defined in TlHelp32}
begin
  PLHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if Process32First(PLHandle,ProcessEntry32) then
  begin
    Wnode := TreeView1.Items.Add(Nil,strPas(@ProcessEntry32.szExeFile[0]));
    GetThreads(ProcessEntry32.th32ProcessID);
    while Process32Next(PLHandle,ProcessEntry32) do
    begin
      Wnode := TreeView1.Items.Add(Nil,strPas(@ProcessEntry32.szExeFile[0]));
      GetThreads(ProcessEntry32.th32ProcessID);
    end;
  end;
  CloseHandle(PLHandle);
end;

Procedure CleanUpTree(Nodes : TTreeNodes);
begin
  {CleanUp Windows without Text (most Controls)}
  WNode := Nodes.GetFirstNode;
  While WNode <> Nil do
  begin
    If WNode.Text = '' then
    begin
      WNode2 := WNode.Getnext;
      WNode.Delete;
      WNode := WNode2;
    end
    else
      WNode := WNode.GetNext;
  end;
  {CleanUp Processes with no windows}
  WNode := Nodes.GetFirstNode;
  While WNode <> Nil do
  begin
    If (WNode.Parent = Nil) and (WNode.GetFirstChild = Nil) then
    begin
      WNode2 := WNode.Getnext;
      WNode.Delete;
      WNode := WNode2;
    end
    else
      WNode := WNode.GetNext;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Treeview1.Items.Clear;
  GetProcessList;
  CleanUpTree(TreeView1.Items);
end;

procedure TForm1.TreeView1Click(Sender: TObject);
begin
  If Treeview1.selected.Level = 1 then {Level 1 entrys Only}
  begin
    TheWinHandle := THandle(Treeview1.selected.Data); {Get the Handle from the DataOption}
    { Do Something with the Handle, must not be in this Procedure }
    edit1.text := IntToStr(TheWinHandle);
  end;
end;

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
  TreeView1Click(Self);
end;

end.

meikl
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356525
pHEW !!!
this is finally it!!!

only one last thing: on exit it frees the resources taken for storing the handles, DOESN'T IT?
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1356526
Hi duke_n,

there is no additional to free, before or after the treeview is destroyed. i do so that the handlevalue is a pointervalue. i get no extra-mem for this, its only a conversion. Both are 32-Bit Wide DataTypes. It is no more to do.

If you want to store more than the handle, then must be a record added and a really pointer points from the data-property to this record, by this, the record must be explicit freed by destroying the tree.

i will post this as an answer, because i mean this question will now be answered and i'm glad that i helped you.

meikl ;-)
0
 
LVL 1

Author Comment

by:duke_n
ID: 1356527
whoops, sorry!!!
I accidentally choose "reject".
plz submit an answer again
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 250 total points
ID: 1356528
no prob duke_n,

this is my answer agian,

meikl ;-)
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

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…
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…
This video discusses moving either the default database or any database to a new volume.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

759 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

20 Experts available now in Live!

Get 1:1 Help Now