[окна / диалоги] пример получения указателя окна по его pid
CreatoR
Довольно долго я не отвечал, извините, но… лучше поздно, чем никогда.
Дело в том, что я использую аддон Akelpad, так что Notepad у меня отсутствует, но в процессах при открытии блокнота висят оба (и Akelpad.exe, и Notepad.exe). И открыть блокнот можно любым из них, но открывается Akelpad. У него другие параметры, поэтому (я так думаю) практически все примеры с Notepad у меня не работают. Переустановлю систему со штатным Notepad и потом отпишусь.
PS
Все работает. 
§
CreatoR
Довольно долго я не отвечал, извините, но… лучше поздно, чем никогда.
Дело в том, что я использую аддон Akelpad, так что Notepad у меня отсутствует, но в процессах при открытии блокнота висят оба (и Akelpad.exe, и Notepad.exe). И открыть блокнот можно любым из них, но открывается Akelpad. У него другие параметры, поэтому (я так думаю) практически все примеры с Notepad у меня не работают. Переустановлю систему со штатным Notepad и потом отпишусь.
PS
Все работает. 
Как получить хендл окна по pid процесса?
Допустим, я нашел все процессы системы и получил их PID, юзая “OpenProcess()” с первым параметром “PROCESS_QUERY_INFORMATION or PROCESS_VM_READ or PROCESS_TERMINATE“.
Как теперь “пробраться вглубь”, то есть добраться до окна? Например, обратное действие можно произвести с использованием “GetWindowThreadProcessID()“.
Можно ли по id просесса узнать хендл окна этого просесса ?
-=SS=- ©
(2004-12-15 18:17)
[0]
Собственно ИМХО может кто знает какие – то апишные функции
зараннее благодарен
![]()
![]()
← →
Суслик ©
(2004-12-15 18:19)
[1]
можно по хандлу окна узнать принадлежит ли он процесу
The GetWindowThreadProcessId function retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the process that created the window.
т.е. можно все окна пребрать.
Может иначе можно, я не знаю.
![]()
![]()
← →
Юрий Зотов ©
(2004-12-15 18:31)
[2]
> -=SS=- © (15.12.04 18:17)
> Можно ли по ID просесса узнать хендл окна этого просесса?
Задумайтесь на минутку – а что, если процесс породил несколько окон? Какое из них Вам нужно? А ведь такое бывает очень часто.
Как сказано в [1], можно перебрать все окна процесса. Но для того, чтобы выделить из них нужное Вы должны знать об этом окне еще что-то, кроме того, что оно принажлежит данномк процессу.
![]()
![]()
← →
-=SS=- ©
(2004-12-15 19:18)
[3]
Огромное спасибо за направление но всё же
DWORD GetWindowThreadProcessId(
HWND hWnd, // handle of window
LPDWORD lpdwProcessId // address of variable for process identifier
);
что опередавать в hWnd если у меня никакого окна нету предаю 0 ноль и возвращает 🙁
![]()
![]()
← →
Суслик ©
(2004-12-15 19:21)
[4]
Ну напрагись, задай вопрос нормально :)) С знаком вопроса, с запятыми и пр.
Я не издеваюсь, я вопроса не понял. Честно. 🙂
![]()
![]()
← →
-=SS=- ©
(2004-12-15 19:36)
[5]
Функция GetWindowThreadProcessId требует handle окна.
Что туда передавать ? если я не знаю handl-ов окон мне их нужно получить.
Для теста передаю туда 0 на выходе получаю 0.
Что делать ?
Зараннее спасибо!
![]()
![]()
← →
Суслик ©
(2004-12-15 19:49)
[6]
1. Ты знаешь id процесса.
2. Для того, чтобы найти все окна, принадлежащие данному процессу, нужно перебрать все окна в системе. Т.е. получить последовательно handle всех окон.
3. Получив handle очередного окна ты используя указанную мной функцию проверяешь принадлежит ли окно процессу (заметь, что нужно передавать указатель на id процесса, а не брать результат функции – это стандратная ошибка).
Теперь о том, как перебрать окна. Ответ – не знаю, т.к. никогда не делал этого. Но уверен, что если начать копать, начиная с функции win api enumwindows, то обязательно добъешься успеха.
![]()
![]()
← →
-=SS=- ©
(2004-12-15 20:09)
[7]
Теперь понял … Большое спасибо за наводку
![]()
![]()
← →
Leonid Troyanovsky ©
(2004-12-15 21:20)
[8]
> -=SS=- © (15.12.04 19:36) [5]
> Функция GetWindowThreadProcessId требует handle окна.
> Что туда передавать ? если я не знаю handl-ов окон мне их
> нужно получить.
var
h: HWND;
pid: DWord;
h := FindWindowEx(0, 0, nil, nil);
while (h <> 0) do
begin
GetWindowThreadProcessId(h, @pid);
if (pid = pi.dwProcessId) then
{окно принадлежит потоку запущенного процесса}
h := FindWindowEx(0, h, nil, nil); // ищем следующее окно
end;
—
С уважением, LVT.
![]()
![]()
← →
GuAV ©
(2004-12-15 21:56)
[9]
IMHO лучше найти все потоки процесса и искать окно в потоках с помощью EnumThreadWindows. Тем более что не всегда у процесса больше одного потока и не всегда во вторичных потоках есть окна – задача может упростися.
![]()
![]()
← →
Piter ©
(2004-12-15 22:14)
[10]
procedure SearchHandle(ProcessId: DWORD; CallbackFunction: TFNWndEnumProc;
UnicID: LPARAM);
var
HSnapShot: THandle;
te: TThreadEntry32;
begin//нам нужен снимок потоков
HSnapShot:=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
try//перед использованием TThreadEntry32 нужно заполнить поле dwSize
te.dwSize := sizeof(TThreadEntry32);// если первая запись о потоках получена - продолжаем
if Thread32First(HSnapShot, te) then
repeat// если этот поток относится к интересующему нас процессу, то// перечисляем все окна, созданные этим потоком
if te.th32OwnerProcessID = ProcessId then
EnumThreadWindows(te.th32ThreadID, CallbackFunction, UnicID);// получаем запись о следующем потоке, если не получаем - выходим из цикла
until ( not Thread32Next(HSnapShot,te) );
finally
closehandle(HSnapShot); // закрываем описатель снимка
end;
end;
function EnumWnd(Handle: hwnd; UnicID: LPARAM): boolean; stdcall;
begin
Result := True;
PostMessage(Handle, WM_CLOSE, 0, 0);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SearchHandle(GetCurrentProcessId, @EnumWnd, 0);
end;
————————————————————-
SearchHandle ищет все окна заданного процесса. При нахождении очередного окна вызывается функция CallbackFunction, которой в данном случае является EnumWnd. Она посылает WM_CLOSE всем окнам.
Так как вызывается:SearchHandle(GetCurrentProcessId, @EnumWnd, 0);
то код приводит к посылке сообщений WM_CLOSE всем окнам данного процесса…
![]()
![]()
← →
Leonid Troyanovsky ©
(2004-12-15 23:03)
[11]
> Piter © (15.12.04 22:14) [10]
> function EnumWnd(Handle: hwnd; UnicID: LPARAM): boolean;
> stdcall;
BOOL CALLBACK EnumThreadWndProc
Хотя, в данном случае это, возможно, не принципиально,
но, вообще-то, надо поаккуратней с хидерами.
—
С уважением, LVT.
PS Кстати, Toolhelp32 отсутствует в NT4.
![]()
![]()
← →
Piter ©
(2004-12-16 00:42)
[12]
Leonid Troyanovsky © (15.12.04 23:03) [11]BOOL CALLBACK EnumThreadWndProc
Хотя, в данном случае это, возможно, не принципиально,
но, вообще-то, надо поаккуратней с хидерами.
а что не так? Я не понял…
![]()
![]()
← →
Игорь Шевченко ©
(2004-12-16 10:43)
[13]
Piter © (16.12.04 00:42) [12]
> а что не так? Я не понял…
Я бы написал вместо
> function EnumWnd(Handle: hwnd; UnicID: LPARAM): boolean;
> stdcall;
function EnumWnd(Handle: hwnd; UnicID: LPARAM): BOOL; stdcall;
С уважением,
![]()
![]()
← →
-=SS=- ©
(2004-12-16 10:46)
[14]
> Piter © (15.12.04 22:14) [10]
Толково…. спасибо…
Осталась маленькая проблемка … ну это я думаю что порывшись в хелпе найду что – то подходящее … Теперь надо будет определять если процесс имеет окна, то как определить главное окно ?
![]()
![]()
← →
Piter ©
(2004-12-16 20:16)
[15]
Ах да, для моего примера [10] нужно подключить юнит TLHelp32
Leonid Troyanovsky © (15.12.04 23:03) [11]
Игорь Шевченко © (16.12.04 10:43) [13]
понял
-=SS=- © (16.12.04 10:46) [14]Теперь надо будет определять если процесс имеет окна, то как определить главное окно ?
не знаю. И вообще сомневаюсь, что в WinApi есть понятие “главное окно”.
Лучше объясни задачу – зачем тебе главное окно? Видимо, ты что-то не так понимаешь…
![]()
![]()
← →
Leonid Troyanovsky ©
(2004-12-16 21:17)
[16]
> Piter © (16.12.04 20:16) [15]
> Ах да, для моего примера [10] нужно подключить юнит TLHelp32
Это само собой. Но, этим ты не отвертишься 😉
Формально, NT4 еще имеет право на жизнь, а там такого
понятия, как ToolHelp functions, нет.
Т.е., включаешь ремарку “исключая NT4”.
—
С уважением, LVT
![]()
![]()
← →
-=SS=- ©
(2004-12-16 22:34)
[17]
Незнаю почему но под DELPHI 7 TollHelp32 не работает … а вот на 5 Delphi работает … и даже неизвестно почему
![]()
![]()
← →
Piter ©
(2004-12-16 23:09)
[18]
-=SS=- © (16.12.04 22:34) [17]Незнаю почему но под DELPHI 7 TollHelp32 не работает
все работает…
![]()
![]()
← →
Piter ©
(2004-12-16 23:12)
[19]
И вместо абстрактного “не работает” почему бы не сказать где именно затык?
P.S. Так как у меня уровень телепатии уже второго уровня, попробую сказать – ты точно в function EnumWnd поставил директиву stdcall;
![]()
![]()
← →
-=SS=- ©
(2004-12-17 10:37)
[20]
Я конечно извеняюсь но причем тут EnumWnd.
begin
H := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Memo1.Clear;
If Process32First(H, P) then
Memo1.Lines.Add(P.szExeFile)
until Process32Next(H, P) = False;
Этот код на D5 работает т.е показывает всё процессы, а на D7 не работает т.е не показывает ни одной записи (WIN XP)
кстати Директива stdcall стоит но она используется пожже, но всё равно все работает (Под D5)
![]()
![]()
← →
Piter ©
(2004-12-17 19:30)
[21]
Ну и какой смысл в молчанку играть? Почему информацию надо вытягивать, как будто это мне нужно? 🙂
ЧТО возвращает CreateToolhelp32Snapshot? Если ошибочный Handle – что возвращает GetLastError?
а-а-а-а-а-а-а-а…. гы гы.
begin
H := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Memo1.Clear;
If Process32First(H, P) then
Memo1.Lines.Add(P.szExeFile)
until Process32Next(H, P) = False;
Нда, я плакаль. Предлагаю найти самому ошибку.
P.S. А также неплохо было бы узнать – откуда ты это собственно взял, если в [10] я привел рабочий код? Из моего FAQ”а что ли?
Тупой Copy-Paste приводит к ошибкам 🙂
![]()
![]()
← →
Piter ©
(2004-12-17 20:50)
[22]
Сори, это я уже лажанулся. Ты просто переделал пример для поиска процессов. Ок, тогда остаются вопросы:
Piter © (17.12.04 19:30) [21]Ну и какой смысл в молчанку играть? Почему информацию надо вытягивать, как будто это мне нужно? 🙂
ЧТО возвращает CreateToolhelp32Snapshot? Если ошибочный Handle – что возвращает GetLastError?
![]()
![]()
← →
GuAV ©
(2004-12-17 23:22)
[23]
-=SS=- © (16.12.04 10:46) [14]Теперь надо будет определять если процесс имеет окна, то как определить главное окно ?
Если под “главным окном” понимать окно для которого создаётся кнопка на панели задач, то можно проверить (с пом GetWindowLong) extended style на наличие признака кнопки на панели задач (WS_EX_APPWINDOW).
![]()
![]()
← →
Игорь Шевченко ©
(2004-12-17 23:53)
[24]
GuAV © (17.12.04 23:22) [23]
У окон, отображаемых на Taskbar не обязательно имеется стиль WS_EX_APPWINDOW. Точнее, большинство отображаемых на таскбаре окон этого стиля не имеет 🙂
С уважением,
![]()
![]()
← →
Piter ©
(2004-12-18 00:44)
[25]
GuAV © (17.12.04 23:22) [23]
имхо, первое окно, созданное приложением и есть “главное”, то есть отображается на Панели Задач
![]()
![]()
← →
GuAV ©
(2004-12-18 00:44)
[26]
Игорь Шевченко © (17.12.04 23:53) [24]
Да..
А как тогда определить отображается окно на taskbar ?
WS_EX_APPWINDOW
Forces a top-level window onto the taskbar when the window is visible.
![]()
![]()
← →
Игорь Шевченко ©
(2004-12-18 00:54)
[27]
GuAV © (18.12.04 00:44) [26]
> А как тогда определить отображается окно на taskbar ?
http://www.schevchenko.net.ru/SRC/EnumFunctions_60.zip
(Только сделал апгрейд, файлы черт знает где, прошу прощения, что приходится ссылку на сайт давать)
С уважением,
![]()
![]()
← →
GuAV ©
(2004-12-18 01:28)
[28]
> http://www.schevchenko.net.ru/SRC/EnumFunctions_60.zip
Мой склероз. Я это смотрел несколько дней назад.
Кстати, Ваш критерий тоже неточен 🙂
Проверку из EnumFunctions_60 if (WindowOwner = 0) AND
((ExStyle AND WS_EX_TOOLWINDOW) = 0) AND
((WinStyle AND WS_VISIBLE) <> 0) then
не проходит такое окно
CreateWindowEx(WS_EX_APPWINDOW or WS_EX_TOOLWINDOW,
"BUTTON", "I""m on taskbar", WS_VISIBLE, 0, 0, 0, 0, HWND_DESKTOP, 0, 0, 0);
![]()
![]()
← →
Игорь Шевченко ©
(2004-12-18 01:56)
[29]
GuAV © (18.12.04 01:28) [28]
Спасибо. К сожалению, я практически не обновляю сайт.
Проверка, очевидно должна выглядеть так (надо проверить):
if (WindowOwner = 0) and ((WinStyle and WS_VISIBLE) <> 0) and
(((ExStyle and WS_EX_TOOLWINDOW) = 0) or ((ExStyle and WS_EX_APPWINDOW) <> 0)) then
С уважением,
![]()
![]()
← →
Piter ©
(2004-12-18 02:21)
[30]
GuAV © (18.12.04 1:28) [28]
а что ты скажешь на:
Piter © (18.12.04 0:44) [25]имхо, первое окно, созданное приложением и есть “главное”, то есть отображается на Панели Задач
![]()
![]()
← →
Leonid Troyanovsky ©
(2004-12-18 13:56)
[31]
> Игорь Шевченко © (18.12.04 01:56) [29]
> Проверка, очевидно должна выглядеть так (надо проверить):
>
> if (WindowOwner = 0) and ((WinStyle and WS_VISIBLE) <> 0)
> and
> (((ExStyle and WS_EX_TOOLWINDOW) = 0) or ((ExStyle and
> WS_EX_APPWINDOW) <> 0)) then
Проверка должна выглядеть так (можешь проверить):
function IsTaskbarBtnExist(h: HWND): Boolean;
var
exstyle: Longint;
begin
Result:= IsWindowVisible(h);
if Result then
begin
exstyle := GetWindowLong(h, GWL_EXSTYLE);
Result := exstyle and WS_EX_APPWINDOW <> 0;
if not Result and
(exstyle and WS_EX_TOOLWINDOW = 0) then
Result := GetWindowLong(h, GWL_HWNDPARENT) = 0;
end;
end;
—
С уважением, LVT.
![]()
![]()
← →
Leonid Troyanovsky ©
(2004-12-18 14:04)
[32]
> Piter © (18.12.04 02:21) [30]
> GuAV © (18.12.04 1:28) [28]>
> а что ты скажешь на:
>
> Piter © (18.12.04 0:44) [25]> имхо, первое окно, созданное приложением и есть “главное”,
> то есть отображается на Панели Задач
В отсутствии определения “главное окно” любое высказывание
может быть представлено как истинное.
—
С уважением, LVT.
PS Собс-но, проще руководстваться целью: “что нужно от
этого окна”.
![]()
![]()
← →
GuAV ©
(2004-12-18 17:45)
[33]
Piter © (18.12.04 2:21) [30]а что ты скажешь на:
Piter © (18.12.04 0:44) [25]имхо, первое окно, созданное приложением и есть “главное”, то есть отображается на Панели Задач
То что имеет значение не порядок, а стили и владалец.
В VCL приложении обычно ни одна форма не видна на TaskBar, для этого исспользуется окно Application.Handle.
type
TForm1 = class(TForm)
private
{ Private declarations }
protected
procedure CreateParams(var Params: TCreateParams); override;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited;
// любая из нижеследуючих строк приводит к появлению формы на taskbar
Params.WndParent := HWND_DESKTOP;
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;
Немного поэксперементировав пришел к выводу, что проверка должна выглядеть так:if (WindowOwner = 0) and ((WinStyle and WS_VISIBLE) <> 0) and ((WinStyle and WS_CHILD) = 0) and
(((ExStyle and WS_EX_TOOLWINDOW) = 0) or ((ExStyle and WS_EX_APPWINDOW) <> 0)) then
![]()
![]()
← →
GuAV ©
(2004-12-18 18:06)
[34]
GuAV © (18.12.04 17:45) [33], что проверка должна выглядеть так:
Хотя нет, правильно в [29]
![]()
![]()
← →
Leonid Troyanovsky ©
(2004-12-18 18:31)
[35]
> GuAV © (18.12.04 17:45) [33]
..
> Немного поэксперементировав пришел к выводу, что проверка
> должна выглядеть так:
От:Tomas Restrepo (winder@bigfoot.com)
Тема:Re: How to EnumWindows…
Группы новостей:microsoft.public.win32.programmer.kernel
Дата:1999/04/06
Maurizio,
You have to do some test on each of the windows returned by EnumWindows() to
decide wheter to show it or not. The test were described by Jeffrey Richter in
the Nov “97 issue of MSJ. Quoting:
“The rules the taskbar uses to decide whether a button should be shown
for a window are really quite simple, but are not well documented.
When you create a window, the taskbar examines the window”s extended
style to see if either the WS_EX_APPWINDOW (defined as 0x00040000) or
WS_EX_TOOLWINDOW (defined as 0x00000080) style is turned on. If
WS_EX_APPWINDOW is turned on, the taskbar shows a button for the
window, and if WS_EX_ TOOLWINDOW is turned on, the taskbar does not
show a button for the window. You should never create a window that
has both of these extended styles.
You can create a window that doesn”t have either of these styles. If a
window has neither style, the taskbar decides to create a button if
the window is unowned and does not create a button if the window is
owned.
One final note: before making any of the above tests, the taskbar
first checks to see if a window has the standard WS_VISIBLE window
style turned on. If this style bit is off, the window is hidden; the
taskbar never shows a button for a hidden window. Only if the
WS_VISIBLE style bit is on will the taskbar check the WS_EX_APPWINDOW,
WS_ EX_TOOLWINDOW, and window ownership information.”
Which, BTW, David Lowndes has posted in this group several times in the past
—
Tomas Restrepo
—
С уважением, LVT.
![]()
![]()
← →
GuAV ©
(2004-12-18 18:43)
[36]
Leonid Troyanovsky © (18.12.04 18:31) [35]
Неточность в том, что если окно WS_CHILD, то никакие WS_EX_APPWINDOW не помогут – можете проверить.
PS: интересный спор ни о чём.
![]()
![]()
← →
Piter ©
(2004-12-18 18:51)
[37]
Leonid Troyanovsky © (18.12.04 14:04) [32]В отсутствии определения “главное окно” любое высказывание
может быть представлено как истинное
не в этом суть:
> > имхо, первое окно, созданное приложением и есть
>”главное”,
> > то есть отображается на Панели Задач
![]()
![]()
← →
GuAV ©
(2004-12-18 19:01)
[38]
2 Piter © (18.12.04 18:51) [37]
GuAV © (18.12.04 17:45) [33]
![]()
![]()
← →
GuAV ©
(2004-12-18 19:02)
[39]
GuAV © (18.12.04 17:45) [33]То что имеет значение не порядок, а стили и владалец.
![]()
![]()
← →
Leonid Troyanovsky ©
(2004-12-18 19:05)
[40]
> GuAV © (18.12.04 18:43) [36]
> Неточность в том, что если окно WS_CHILD, то никакие WS_EX_APPWINDOW
> не помогут – можете проверить.
А причем тут WS_CHILD?
Речь шла про EnumWindows & top-level windows.
> PS: интересный спор ни о чём.
Это называется обсуждением, IMHO.
—
С уважением, LVT.
![]()
![]()
Работа с чужими процессами
unit Unit1;
{©Drkb v.3}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;
PTokenUser = ^TTokenUser;
TTokenUser = record
User: array[0..0] of TSIDAndAttributes;
end;
procedure ConvertSidToStringSid(SID: PSID; var StringSid: LPSTR); stdcall;
external advapi32 name‘ConvertSidToStringSidA’;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetCurrentUserSID: String;
var
TokenHandle: THandle;
TokenInformationClass: TTokenInformationClass;
TokenInformation: PTokenUser;
ReturnLength: DWORD;
StringSid: LPSTR;
begin
Result := ”;
if OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, TokenHandle) then
try
TokenInformationClass := TokenUser;
GetTokenInformation(TokenHandle, TokenInformationClass, nil, 0, ReturnLength);
if GetLastError = ERROR_INSUFFICIENT_BUFFER then
begin
TokenInformation := GetMemory(ReturnLength);
if TokenInformation <> nilthen
try
if GetTokenInformation(TokenHandle, TokenInformationClass,
TokenInformation, ReturnLength, ReturnLength) then
begin
ConvertSidToStringSid(TokenInformation^.User[0].Sid, StringSid);
Result := StringSid;
end;
finally
FreeMemory(TokenInformation);
end;
end;
finally
CloseHandle(TokenHandle);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(GetCurrentUserSID);
end;
end.
Список окон определение приложения, создавшего эти окна
Code: |
//////////////////////////////////////////////////////////////////////////////// // // Автор: Александр (Rouse_) Багель // Данный код приведен лишь для демонстрации // А простой вариант поиска Handle Ричедита выглядит так // var // Handle : HWND; // begin // Handle:= FindWindowEx(FindWindow(Название формы например ‘Form1’,nil), 0, Название элемента например ‘Button1’, nil), 0, true); unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls; type TMainForm = class(TForm) TreeView1: TTreeView; procedure FormCreate(Sender: TObject); procedure Sys_Windows_Tree(Node: TTreeNode; Handle: HWND); end; var MainForm: TMainForm; implementation {$R *.DFM} //////////////////////////////////////////////////////////////////////////////// // // Стартовая функция, запускаем рекуссию используя хэндл рабочего стола // procedure TMainForm.FormCreate(Sender: TObject); var StartHandle : THandle; begin //Если требуется найти только данные по одному приложению //замени 2 строки в функциях их закоментированными аналогами StartHandle := GetDeskTopWindow; //StartHandle := 67324;//FindWindow(PChar(Caption), nil); //На примере Винампа Sys_Windows_Tree(nil, StartHandle); end; //////////////////////////////////////////////////////////////////////////////// // // Рекурсивная функция, строит дерево всех открытых окон, кнопок, едитов и т.д. // В качестве входных данных получает узел дерева и Хэндл окна // procedure TMainForm.Sys_Windows_Tree(Node: TTreeNode; Handle: HWND); const MAX = 128; var TmpArray : array[0..MAX – 1] of Char; Result : String; szFileName : array[0..255] of Char; iSize : Integer; PID: Cardinal; begin //Запускаем цикл пока не закончатся окна while Handle <> 0do begin //Получаем имя класса окна GetClassName(Handle, @TmpArray, MAX); Result := String(TmpArray); //Получаем текст (Его Caption) окна GetWindowText(Handle, @TmpArray, MAX); // Получаем имя модуля if GetwindowModuleFilename(Handle, szFileName, SizeOf(szFileName)) = 0then ZeroMemory(@szFileName[0], 256); GetWindowThreadProcessId(Handle, PID); Result := Result ‘ [‘ String(szFileName) ‘] (‘ String(TmpArray) ‘): Handle = ‘ IntToStr(Handle) ‘, PID = ‘ IntToStr(PID); //В следующей процедуре, в скобках, добавляем результат //в дерево, получаем хэндл дочернего окна и с результатами //выполнения этих двух функций выполняем процедуру Sys_Windows_Tree Sys_Windows_Tree(TreeView1.Items.AddChild(Node, Result), GetWindow(Handle, GW_CHILD)); //Получаем хэндл следующего (не дочернего) окна Handle := GetNextWindow(Handle, GW_HWNDNEXT); //Handle := 0; end; end; end. |


