Applist

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?
LVL 1
duke_nAsked:
Who is Participating?
 
kretzschmarCommented:
no prob duke_n,

this is my answer agian,

meikl ;-)
0
 
MadshiCommented:
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
 
duke_nAuthor Commented:
I have delphi3 and need to know how to do it "nakely", w/o no units.
Some code pls
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

 
kretzschmarCommented:
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
 
MadshiCommented:
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
 
duke_nAuthor Commented:
95/98
0
 
duke_nAuthor Commented:
//to meikl.
No, man.
I didn't wanna list every stupid edit or combo-box.
only the windows in <ALT>+<CTRL>+<DEL>.
0
 
MadshiCommented:
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
 
MadshiCommented:
Hmm. Another thing would be to list only the buttons in the taskbar. That's possible, too, of course.
0
 
viktornetCommented:
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
 
kretzschmarCommented:
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
 
duke_nAuthor Commented:
say, what about the handles of thy windows?
0
 
MadshiCommented:
What do you mean?
0
 
MadshiCommented:
Please explain it in detail. What do you need? And for which purpose?
0
 
viktornetCommented:
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
 
duke_nAuthor Commented:
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
 
viktornetCommented:
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
 
MadshiCommented:
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
 
duke_nAuthor Commented:
//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
 
kretzschmarCommented:
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
 
duke_nAuthor Commented:
//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
 
MadshiCommented:
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
 
duke_nAuthor Commented:
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
 
duke_nAuthor Commented:
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
 
MadshiCommented:
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
 
viktornetCommented:
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
 
kretzschmarCommented:
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
 
MadshiCommented:
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
 
kretzschmarCommented:
Hi madshi,

thanks for the tips, i will take them over.

meikl ;-)

0
 
MadshiCommented:
No prob... I'm just glad that you're writing the code. I've not much time at the moment...   :-)

Regards, Madshi.
0
 
kretzschmarCommented:
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
 
duke_nAuthor Commented:
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
 
duke_nAuthor Commented:
Adjusted points to 200
0
 
duke_nAuthor Commented:
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
 
kretzschmarCommented:
Hi duke_n,

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

meikl
0
 
kretzschmarCommented:
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
 
duke_nAuthor Commented:
pHEW !!!
this is finally it!!!

only one last thing: on exit it frees the resources taken for storing the handles, DOESN'T IT?
0
 
kretzschmarCommented:
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
 
duke_nAuthor Commented:
whoops, sorry!!!
I accidentally choose "reject".
plz submit an answer again
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.

All Courses

From novice to tech pro — start learning today.