Чтение онлайн

ЖАНРЫ

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

Что касается самих результатов, то они, конечно, сильно зависят от конфигурации компьютера. По первым двум тестам время выполнения для DDB-растра может быть как в два-три раза меньше, чем для DIB, так и несколько превышать его. В третьем тесте DIB-растр, разумеется, существенно опережает по скорости DDB, хотя отношение и здесь зависит от компьютера. Также наблюдается некоторая зависимость от версии Delphi, под которой откомпилирован проект. Например, первый тест и для DIB, и для DDB выполняется несколько быстрее под Delphi 2007, чем под Delphi 5, а вот третий тест под Delphi 2007 выполняется несколько медленнее.

1.3. Обобщающие примеры

Рассмотрев основы работы с функциями API. мы переходим к обобщающим примерам — программам, использующим разные средства API

для создания простого законченного примера.

1.3.1. Обобщающий пример 1 — Информация о процессах

Первым обобщающим примером станет программа для получения информации о процессах системы и об окнах, которые они открывают. На компакт-диске, прилагаемом к книге, эта программа называется ProcInfo. Окно программы ProcInfo показано на рис 1.13.

Рис. 1.13. Окно программы ProcInfo

1.3.1.1. Получение списка процессов

Исторически сложилось так, что существует два способа получить список процессов: с помощью функций Tool Help и посредством функций PSAPI. Эти две группы функций использовались в разных линиях Windows: функции Tool Help появились в Windows 95, функции PSAPI — в Windows NT 4. Windows 2000 XP также поддерживают функции Tool Help, в то время как Windows 98/ME не поддерживают PSAPI. Поэтому мы выберем функции Tool Help, что даст нашему примеру возможность работать во всех версиях Windows, кроме NT 4 (впрочем, в Windows 95 пример тоже не будет работать, но по другой причине: из-за функций

GetWindowInfo
и
RealGetWindowClass
, отсутствующих в этой версии). Функции Tool Help объявлены в модуле
TlHelp32

Для получения списка процессов необходимо сделать "снимок" состояния системы с помощью функции

CreateToolhelp32Snapshot
. Эта функция создает специальный объект, который может хранить информацию о процессах, модулях, нитях и кучах, созданных в системе. Этот объект называется снимком потому, что информация, хранящаяся в нем, актуальна на момент вызова функции
CreateToolhelp32Snapshot
; дальнейшие изменения списка процессов, модулей и т.п. не приводят к изменению снимка. Доступ к снимку, как и к большинству объектов системы, осуществляется через его дескриптор. В данном случае функция
CreateToolhelp32Snapshot
вызывается с параметром
TH32CS_SNAPPROCESS
для получения списка процессов.

Навигация по списку процессов, сохраненных в снимке, осуществляется с помощью функций

Process32First
и
Process32Next
. Они позволяют получить ряд параметров процесса, главный среди которых — идентификатор процесса (Process Identifier, PID). Это уникальный идентификатор процесса, с помощью которого можно отличать один процесс от другого. 

Примечание

Не следует путать идентификатор процесса и дескриптор объекта процесса, который используется, например, в функции

SetPriorityClass
. Объект процесса — это специальный объект, связанный с процессом, но не тождественный ему. В частности, объект процесса может продолжать существовать уже после того, как сам процесс завершит работу (это позволяет, например, корректно синхронизироваться с уже завершенным процессом при помощи функции
WaitForSingleObject
). Через объект процесса можно управлять многими свойствами процесса. Поучить дескриптор объекта процесса по идентификатору процесса можно с помощью функции
OpenProcess
.

Код для получения списка процессов показан в листинге 1.42.

Листинг 1.42. Получение списка процессов с помощью Tool Help

procedure TProcessesInfoForm.FillProcessList;

var

 SnapProc: THandle;

 ProcEntry: TProcessEntry32;

 Item: TListItem;

begin

 ClearAll;

 //
Создаем снимок, в котором сохраняем все процессы, а

 // затем в цикле получаем информацию о каждом из этих

 // процессов, перенося ее в ListProcesses

 SnapProc := CreateToolhelp32Snapshot(TH32CS_SNAPROCESSES, 0);

 if SnapProc <> INVALID_HANDLE_VALUE then

 try

ProcEntry.dwSize := SizeOf(TProcessEntry32);

if Process32First(SnapProc, ProcEntry) then repeat

Item := ListProcesses.Items.Add;

Item.Caption := ProcEntry.szExeFile;

Item.SubItems.Add(IntToStr(ProcEntry.tb32ProcessID);

Item.SubItems.Add(IntToStr(ProcEntry.th32ParentProcessID));

Item.SubItems.Add(IntToStr(ProcEntry.cntThreads));

// Сохраняем PID в поле Data соответствующего

// элемента списка. Вообще, поле Data имеет тип

// Pointer, а PID - это целое число, но т.к. оба этих

// типа 32-битные, их можно приводить друг к другу

Item.Data := Pointer(ProcEntry.th32ProcessID);

until not Process32Next(SnapProc, ProcEntry);

 finally

CloseHandle(SnapProc);

 end

 else

 begin

ListProcesses.Visible := False;

LabelProcessError.Caption :=

'Невозможно получить список процессов:'#13#10'Ошибка №' +

IntToStr(GetLastError);

 end;

end;

Для получения списка модулей данного процесса также используется снимок. Функция

CreateToolhelp32Snapshot
вызывается с параметром
TH32CS_SNAPMODULE
, в качестве второго параметра ей передается PID процесса, модули которого требуется получить. Навигация по снимку модулей осуществляется с помощью функций
Module32First
и
Module32Next
. В остальном код получения списка модулей совпадает с кодом, приведенным в листинге 1.42.

1.3.1.2. Получение списка и свойств окон

Список окон, созданных процессом, формируется с помощью функции

EnumWindows
, которая позволяет получить список всех окон верхнего уровня (т.е. расположенных непосредственно на рабочем столе). Для каждого из этих окон с помощью функции
GetWindowThreadProcessID
определяется идентификатор процесса. Окна, не принадлежащие выбранному процессу, отсеиваются.

Для каждого из окон верхнего уровня, принадлежащих процессу, с помощью функции

EnumChildWindows
ищутся дочерние окна, а для каждого из найденных таким образом дочерних окон — его дочерние окна. Здесь следует учесть, что
EnumChildWindows
возвращает не только дочерние окна заданного окна, но и все окна, которыми владеют эти дочерние окна. Чтобы в дереве окон не было дублирования, при построении очередного уровня дерева окон отбрасываются все окна, непосредственным родителем которых не является данное окно. Код, выполняющий построение дерева, приведен в листинге 1.43.

Поделиться с друзьями: