Node.Data:= Pointer(Wnd);
// Вызываем EnumChildWindows, передавая функцию
// EnumWindowsProc в качестве параметра, а указатель на
// созданный узел — в качестве параметра этой функции.
// При этом EnumWindowsProc будет вызываться из
// EnumChildWindows, т. е. получается рекурсия.
EnumChildWindows(Wnd, @EnumWindowsProc, LParam(Mode));
end;
Как мы помним, первый параметр функции обратного вызова для EnumWindows
EnumWindows
или EnumChildWindows
. Мы задействуем этот параметр для передачи ссылки на узел дерева, соответствующий родительскому окну. Также договоримся, что в свойство Data каждого узла будем записывать дескриптор связанного с ним окна. Для окон верхнего уровня ссылка будет иметь значение nil
— это обеспечивается тем, что при вызове EnumWindows второй параметр равен нулю (см. листинг 1.21).Работа функции начинается с проверки того, что родительским окном для данного окна действительно является то окно, чей дескриптор связан с узлом родительского окна. Эта проверка нужна потому, что функция EnumChildWindows
EnumChildWindows
для дочерних окон, поэтому и отсеиваем лишнее.Следующий шаг — получение заготовка окна. Для этого мы используем сообщение WM_GETTEXT
GetWindowText
обсуждается в Text
типа string
. Сначала с помощью сообщения WM_GETTEXTLENGTH
мы узнаем длину заголовка окна, а затем выделяем под строку Text
требуемое количество памяти с помощью SetLength
. После этого можно получить строку с помощью сообщения WM_GETTEXT
. Второй параметр этого сообщения — адрес буфера, в который будет помещена строка. Так как переменная типа string
и есть указатель на буфер строки (это детально обсуждается в Text
к типу LParam
и передать получившееся значение.Строго говоря, у нас здесь нигде нет параметра типа LPTSTR
LPTSTR
, в качестве параметра.Далее получаем название класса окна. Для этого мы используем статический массив ClassName
WM_SETTEXTLENGTH
, т. е. API не дает возможности получить длину имени класса, что делает бессмысленными все манипуляции с размером буфера во время работы программы. Поэтому мы определяем размер буфера еще на этапе компиляции, исходя из того, что слишком уж длинные имена классов встречаются редко. При вызове функции с параметром типа LPTSTR
можно просто передавать массив без приведения типа, т. к. LPTSTR
— это PChar
, а массивы символов Char
, индексирующиеся с нуля, компилятор полагает совместимыми с этим типом и все необходимые преобразования делает неявно.