Нет общего способа получить «дескриптор окна» приложения, потому что нет гарантии, что у любой программы есть один дескриптор окна.Программа может иметь много дескрипторов верхнего уровня (т. Е. Microsoft Word, по одному для каждого документа), или у нее может не быть окон вообще.Вы можете спросить, для чего вам действительно нужен дескриптор окна;могли бы быть более эффективные способы сделать то, что вы пытаетесь сделать, не требуя какого-либо определенного дескриптора окна.
WinExec
(который устарел в течение почти 15 лет, поэтому вам следует серьезно подуматьбольше не использовать) и ShellExecute
не возвращает абсолютно никакой информации о программах, которые они запускают, если они вообще запускают какую-либо программу.(ShellExecute
может использовать DDE для отправки команды уже запущенному экземпляру приложения.) И если они запустят приложение, оно может завершиться до того, как ваша программа перестанет работать.
Вы можете использоватьCreateProcess
или ShellExecuteEx
вместо.Если они запустят программу, они дадут вам дескриптор процесса, представляющий программу, которую они запустили.Вы можете использовать это, чтобы помочь вам получить дополнительную информацию о программе, такую как список ее окон.Не беспокойтесь о FindWindow
;класс заголовка и окна не обязательно должен быть уникальным;программа может использовать одно и то же имя класса для множества разных окон, и несколько экземпляров программы будут использовать одно и то же имя класса без особого способа выбрать то, что вам действительно нужно.
EnumWindows
- это функция, которую вы можете использоватьиспользуйте, чтобы получить список возможных оконных дескрипторов.Вы даете ему указатель на функцию, и она будет вызывать эту функцию один раз для каждого окна верхнего уровня на рабочем столе.Вам понадобится способ сообщить, какой процесс вас интересует, и способ вернуть список результатов.Функция принимает только один параметр, поэтому этот параметр должен быть указателем на структуру, которая содержит больше информации:
type
PWindowSearch = ^TWindowSearch;
TWindowSearch = record
TargetProcessID: DWord;
ResultList: TWndList;
end;
TWndList
- это тип, который я составил для хранения списка HWnd
ценности.Если у вас Delphi 2009 или более поздняя версия, вы можете использовать TList<HWnd>
;для более ранних версий вы можете использовать TList
потомка или что-то еще, что вы выберете.
CreateProcess
сообщит вам новый идентификатор процесса в dwProcessID
члене записи TProcessInformation
, которую он заполняет;ShellExecuteEx
возвращает только дескриптор процесса, поэтому используйте GetProcessID
для этого.Функция перечисления окон нуждается в функции обратного вызова, соответствующей этой сигнатуре:
function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall;
. Вы можете использовать EnumWindows
, чтобы получить список дескрипторов, подобный этому:Функция обратного вызова выглядит следующим образом:
function SelectWindowByProcessID(Wnd: HWnd; Param: LParam): Bool; stdcall;
var
SearchRec: PWindowSearch;
WindowPid: DWord;
begin
SearchRec := PWindowSearch(Param);
Assert(Assigned(SearchRec));
GetWindowThreadProcessID(Wnd, WindowPid);
if WindowPid = SearchRec.TargetProcessID then
SearchRec.ResultList.Add(Wnd);
Result := True;
end;
Как только у вас есть список, вы можете проверить другие атрибуты окна, чтобы определить, какие из них действительно те, которые вы хотите.Вы можете определить его по заголовку окна или имени класса, или, возможно, по другим элементам управления, которые принадлежат этому окну.
Когда вы закончите использовать дескриптор процесса, убедитесь, что вы вызвали CloseHandle
для него, чтобыОС может очистить учетную информацию процесса.