neshkov
asked on
Browse for ALL instances of an application
Hi all,
I want to know how can browse and find all instances of an application. For example: I want to find and maximize ALL windows that contains the string 'MyAppWindow'. Please include some code examples.
Thanks for your help in advance!
Best Regards
I want to know how can browse and find all instances of an application. For example: I want to find and maximize ALL windows that contains the string 'MyAppWindow'. Please include some code examples.
Thanks for your help in advance!
Best Regards
look at enumwindows in winAPI
ASKER
Example please!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
found an old sample in my paq (from january 1999)
--- paste begin
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,TextB ufPtr,100) ;
Result := strpas(TextBufPtr);
end;
Function ControlCaption(CHandle : THandle) : String;
begin
Getwindowtext(CHandle,Text BufPtr,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.AddChildOb ject(Node, TNDPtr^.Cl assName,TN DPtr);
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_HWNDN EXT); {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(T V1.TopItem ,TNDPtr^.C lassName,T NDPtr);
FindChilds(0,SHandle,ActNo de);
end;
end;
SHandle := GetActiveWindow;
while (SHandle <> 0) do
begin
SHandle := GetWindow(SHandle,GW_HWNDP REV); {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(T V1.TopItem ,TNDPtr^.C lassName,T NDPtr);
FindChilds(0,SHandle,ActNo de);
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(ehandl e.text),SW _SHOW);
end;
end.
meikl
--- paste end
matches not your needs, but may give a suggestion how to do it
meikl ;-)
hi, igor :-)
meikl ;-)
--- paste begin
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,TextB
Result := strpas(TextBufPtr);
end;
Function ControlCaption(CHandle : THandle) : String;
begin
Getwindowtext(CHandle,Text
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.AddChildOb
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
var
SHandle,
FHandle : THandle;
begin
SHandle := GetActiveWindow;
while (SHandle <> 0) do
begin
SHandle := GetWindow(SHandle,GW_HWNDN
if SHandle <> 0 then
begin
New(TNDPTr);
TNDPtr^.ClassName := MyClassName(SHandle);
TNDPtr^.Caption := ControlCaption(SHandle);
TNDPtr^.Handle := SHandle;
ActNode := TV1.Items.AddChildObject(T
FindChilds(0,SHandle,ActNo
end;
end;
SHandle := GetActiveWindow;
while (SHandle <> 0) do
begin
SHandle := GetWindow(SHandle,GW_HWNDP
if SHandle <> 0 then
begin
New(TNDPTr);
TNDPtr^.ClassName := MyClassName(SHandle);
TNDPtr^.Caption := ControlCaption(SHandle);
TNDPtr^.Handle := SHandle;
ActNode := TV1.Items.AddChildObject(T
FindChilds(0,SHandle,ActNo
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
begin
showwindow(strtoint(ehandl
end;
end.
meikl
--- paste end
matches not your needs, but may give a suggestion how to do it
meikl ;-)
hi, igor :-)
meikl ;-)
meikl :-)
hmm,
my sample doesn't use enumwindows,
it uses another alternative way,
maybe i should dig again in my paq
meikl ;-)
my sample doesn't use enumwindows,
it uses another alternative way,
maybe i should dig again in my paq
meikl ;-)
meikl,
yes, it's look like big enought :-)
-----
Igor.
yes, it's look like big enought :-)
-----
Igor.
hopefully madshi isn't angry about me
its unit at
www.madshi.net/enumStuff.zip
makes all easier
meikl ;-)
its unit at
www.madshi.net/enumStuff.zip
makes all easier
meikl ;-)
Why should I be angry? It's always nice to be referenced by other experts... :-)
Igor, your NextWindow function needs to have a "bool" result, which has to be set to true. Otherwise the enumeration may stop, depending on random.
meikl, the documentation about EnumWindows sais this: "This function is more reliable than calling the GetWindow function in a loop. An application that calls GetWindow to perform this task risks being caught in an infinite loop or referencing a handle to a window that has been destroyed.". So we should really better use EnumWindows.
Regards, Madshi.
Igor, your NextWindow function needs to have a "bool" result, which has to be set to true. Otherwise the enumeration may stop, depending on random.
meikl, the documentation about EnumWindows sais this: "This function is more reliable than calling the GetWindow function in a loop. An application that calls GetWindow to perform this task risks being caught in an infinite loop or referencing a handle to a window that has been destroyed.". So we should really better use EnumWindows.
Regards, Madshi.
ASKER
Thank you Madshi!
OK, Igor, can you please rewrite your example?
OK, Igor, can you please rewrite your example?
:-) i know, madshi, just got the wrong sample from my paq
:-)
ASKER
Thank you gays!
Ok,
here is it.
function NextWindow(H,V:Integer): Boolean; stdcall;
var
C: array[0..255] of char;
begin
GetClassName(H, C, 255);
if C = 'TForm1' then
ShowWindow(H, SW_MINIMIZE);
EnumChildWindows(H, @NextWindow, V);
Result := true;
end;
procedure TForm1.SpeedButton1Click(S ender: TObject);
begin
EnumWindows(@NextWindow, 0);
end;
Thanx for the points.
here is it.
function NextWindow(H,V:Integer): Boolean; stdcall;
var
C: array[0..255] of char;
begin
GetClassName(H, C, 255);
if C = 'TForm1' then
ShowWindow(H, SW_MINIMIZE);
EnumChildWindows(H, @NextWindow, V);
Result := true;
end;
procedure TForm1.SpeedButton1Click(S
begin
EnumWindows(@NextWindow, 0);
end;
Thanx for the points.
Ehmm... "Boolean" is 1 byte long. In fact it has to be "BOOL", which is 4 byte long. Well, it doesn't really matter much, because the result is returned in the register EAX, which is already 4 bytes long, but, hey, I'm a perfectionist... :-)
Regards, Madshi.
Regards, Madshi.
ASKER
Hey Madshi, are you a german? ;)
...Best Regards
...Best Regards