Перечисление окон Windows
От: Delphi-Beginner  
Дата: 07.08.06 12:48
Оценка:
Привет всем, не пинайте сильно за вопрос, так как я еще пока учусь программировать на Delphi.
Короче мне надо перечислить все окна в системе, title которых не равно пустой строке.
Использовал два способа — EnumWindows и GetWindow, однако эти 2 способа дают разные результаты.
Окна, которые не перечисляются в первом способе, перечисляются во втором и наоборот.
Может чего делаю не так, подскажите пожалуйста.

Способ 1: EnumWindows и EnumChieldWindows с callback- oм

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
lst :TStringList;

implementation

{$R *.dfm}

//Просто добавить строку в список
procedure AddToList (s :string);
begin
lst.Add(s);
end;


//Перечислить дочерние окна
function EnumChildProc(wdc :hwnd; Param :LongInt) :boolean; stdcall;

var
buf :array[0..250] of char;
s :string;

begin
GetWindowText(wdc, buf, sizeof(buf));
s := StrPas(buf);
if (s <> '') then
AddToList(s);
EnumChildProc := true;
end;

//Перечислить основные окна
function EnumProc (Wd: HWnd; Param: LongInt): Boolean; stdcall;

var
buf :array[0..250] of char;
s :string;

begin
GetWindowText(wd, buf, sizeof(buf));
s := StrPas(buf);
if (s <> '') and (GetWindowLong(Wd, GWL_HWNDPARENT) = 0) then
begin
AddToList(s);
end else
begin
EnumChildWindows(wd, @EnumChildProc, 0);
end;
EnumProc := true;
end;

//Основная процедура перечисления
procedure TForm1.Button1Click(Sender: TObject);

begin
EnumWindows(@EnumProc, 0);
end;


procedure TForm1.FormCreate(Sender: TObject);

begin
lst := TStringList.Create;
end;

//Сохранить список в файл
procedure TForm1.Button2Click(Sender: TObject);

begin
lst.SaveToFile('windowlist.txt');
end;

end.


Способ 2: Использование GetWindow

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
lst :TStringList;

implementation

{$R *.dfm}


procedure AddToList (s :string);
begin
lst.Add(s);
end;

//Основная процедура перечисления
procedure TForm1.Button1Click(Sender: TObject);

var
Wnd : hWnd;
buff: array [0..127] OF Char;
s :string;

begin
lst.Clear;

Wnd := GetWindow(Application.Handle, gw_HWndFirst);
while Wnd <> 0 do
begin
GetWindowText(Wnd, buff, sizeof(buff));
s := StrPas(buff);
if s <> '' then
begin
lst.add(s);
end;
Wnd := GetWindow(Wnd, gw_hWndNext);
end;
end;

procedure TForm1.FormCreate(Sender: TObject);

begin
lst := TStringList.Create;
end;

procedure TForm1.Button2Click(Sender: TObject);

begin
lst.SaveToFile('windowlist2.txt');
end;

end.
Re: Перечисление окон Windows
От: Master Yoda Великобритания  
Дата: 07.08.06 13:24
Оценка:
Здравствуйте, Delphi-Beginner, Вы писали:

<...>

Код честно говоря не смотрел, ты бы его хотя бы в [pascal][pascal] обернул

Результаты сильно разнятся? Дело в том, что на результаты GetWindow сильно полагаться не стоит. Пока идет перечисление, окна могут удаляться и создаваться заново. Более того, старые хендлы (фактически это просто число), могут задействоваться для новых окон. С другой стороны, EnumWindows делает снапшот текущих окон и такой проблемы там не существует:

EnumWindows
...
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.

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re: Перечисление окон Windows
От: Аноним  
Дата: 07.08.06 13:41
Оценка:
DB>Использовал два способа — EnumWindows и GetWindow, однако эти 2 способа дают разные результаты.

Спроси в форуме по виндам, Delphi тут практически не при чём.

DB>function EnumChildProc(wdc :hwnd; Param :LongInt) :boolean; stdcall;

DB>var
DB> buf :array[0..250] of char;
DB> s :string;

DB>begin

DB> GetWindowText(wdc, buf, sizeof(buf));
DB> s := StrPas(buf);
DB> if (s <> '') then
DB> AddToList(s);
DB> EnumChildProc := true;

устаревший способ. Лучше используй Result.

DB>end;


А отсюда ты вызываешь EnumChildWindows ? У детей тоже свои дети могут быть.


DB> Wnd := GetWindow(Application.Handle, gw_HWndFirst);


А если GetWindows(GetDesktopWindow(), GW_CHILD) ?

DB> Wnd := GetWindow(Wnd, gw_hWndNext);


А гдe ты детей перебираешь ?
Re[2]: Перечисление окон Windows
От: Delphi-Beginner  
Дата: 08.08.06 05:34
Оценка:
Здравствуйте, Аноним, Вы писали:

DB>>Использовал два способа — EnumWindows и GetWindow, однако эти 2 способа дают разные результаты.


А>Спроси в форуме по виндам, Delphi тут практически не при чём.


DB>>function EnumChildProc(wdc :hwnd; Param :LongInt) :boolean; stdcall;

DB>>var
DB>> buf :array[0..250] of char;
DB>> s :string;

DB>>begin

DB>> GetWindowText(wdc, buf, sizeof(buf));
DB>> s := StrPas(buf);
DB>> if (s <> '') then
DB>> AddToList(s);
DB>> EnumChildProc := true;

А>устаревший способ. Лучше используй Result.


DB>>end;


А>А отсюда ты вызываешь EnumChildWindows ? У детей тоже свои дети могут быть.



DB>> Wnd := GetWindow(Application.Handle, gw_HWndFirst);


А>А если GetWindows(GetDesktopWindow(), GW_CHILD) ?


DB>> Wnd := GetWindow(Wnd, gw_hWndNext);


А>А гдe ты детей перебираешь ?



Так вот в том то и вопрос, как мне прально написать цикл, чтоб перебрать всех детей, всех детей детей и всех родителей, короче всех всех окон windows. А то у меня список явно получается не полный после перечисления.
Re: Перечисление окон Windows
От: Delphi-Beginner  
Дата: 08.08.06 06:40
Оценка:
Спасибо всем, вроде разобрался, нашел ошибку )))
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.