Читаем О чём не пишут в книгах по Delphi полностью

Соответственно, в Windows.pas она имеет вид

function EnumWindows(lpEnumFunc: TFNWndEnumProc; lParam: LPARAM): BOOL; stdcall;

Параметр lpEnumFunc должен содержать указатель на функцию обратного вызова. Прототип этой функции описан так:

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);

Функции с таким именем в Windows API не существует. Это так называемый прототип функции, согласно которому следует описывать функцию обратного вызова. На самом деле этот прототип предоставляет большую свободу, чем это может показаться на первый взгляд. Во-первых, имя может быть любым. Во-вторых, система не накладывает строгих ограничений на имена и типы параметров — они могут быть любыми, при условии, что новые типы совпадают по размерам с теми, которые указываются (тип TFNWndEnumProc, описанный в модуле Windows — это не процедурный тип, а просто нетипизированный указатель, поэтому компилятор Delphi не будет контролировать соответствие передаваемой функции обратного вызова ее прототипу). Что касается типа функции и типа первого параметра, то они имеют определенный смысл, и изменение их типа вряд ли может быть полезным. Но второй параметр предназначен специально для передачи значения, которое программист волен использовать но своему усмотрению, система просто передает через него в функцию обратного вызова то значение, которое имел параметр lParam при вызове функции EnumWindows. А программисту может показаться удобнее работать не с типом lParam (т.е. LongInt), а, например, с указателем или же с массивом из четырех байтов. Лишь бы были именно четыре байта, а не восемь, шестнадцать или еще какое-то число. Можно даже превратить этот параметр в параметр-переменную, т.к. при этом функции будут передаваться все те же четыре байта — адрес переменной. Впрочем, тем, кто не очень хорошо разбирается с тем, как используется стек для передачи параметров при различных моделях вызова, лучше не экспериментировать с изменением типа параметра, а строго следовать заявленному прототипу, при необходимости выполняя требуемые преобразования внутри функции обратного вызова.

Функция EnumWindows работает так: после вызова она начинает по очереди перебирать все имеющиеся в данный момент окна верхнего уровня, т.е. те, у которых нет родителя. Для каждого такого окна вызывается заданная функция обратного вызова, в качестве первого параметра ей передается дескриптор данного окна (каждый раз, естественно, новый), в качестве второго — то, что было передано самой функции EnumWindows в качестве второго параметра (каждый раз одно и то же). Получая по очереди дескрипторы всех окон верхнего уровня, функция обратного вызова может выполнить с каждым из них определенное действие (закрыть, минимизировать и т.п.). Или можно проверять все эти окна на соответствие какому-то условию, пытаясь найти нужное. А значение, возвращаемое функцией обратного вызова, влияет на работу EnumWindows. Если она возвращает False, значит, все, что нужно, уже сделано, можно не перебирать остальные окна.

Окончательный код для того случая, когда второй параметр имеет тип Pointer, иллюстрирует листинг 1.3.

Листинг 1.3. Вызов функции EnumWindows с функцией обратного вызова

function MyCallbackFunction(Wnd: HWND; Р: Pointer): BOOL; stdcall;

begin

 { что-то делаем}

end;

...............

var

 MyPointer: Pointer;

 ...............

EnumWindows(@MyCallbackFunction, LongInt(MyPointer));

Что бы мы ни делали с типом второго параметра функции обратного вызова, тип соответствующего параметра EnumWindows не меняется. Поэтому необходимо явное приведение передаваемого параметра к типу LongInt. Обратное преобразование типов при вызове MyCallbackFunction, осуществляется автоматически.

Использование EnumWindows и функций обратного вызова демонстрируется примером EnumWnd.

Отметим, что функции обратного вызова будут вызываться до того, как завершит работу функция EnumWindows. Однако это не является распараллеливанием работы. Чтобы проиллюстрировать это, рассмотрим ситуацию, когда программа вызывает некоторую функцию А, которая, в свою очередь, вызывает функцию В. Функция В, очевидно, начнет свою работу до того, как завершит работу функция А. То же самое произойдет и с функцией обратного вызова, переданной в EnumWindows: она будет вызываться из кода EnumWindows так же, как и функция В из кода функции А. Поэтому код функции обратного вызова получит управление (и не один раз, т.к. EnumWindows будет вызывать эту функцию в цикле) до завершения работы EnumWindows.

Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT
Программист-прагматик. Путь от подмастерья к мастеру
Программист-прагматик. Путь от подмастерья к мастеру

Находясь на переднем крае программирования, книга "Программист-прагматик. Путь от подмастерья к мастеру" абстрагируется от всевозрастающей специализации и технических тонкостей разработки программ на современном уровне, чтобы исследовать суть процесса – требования к работоспособной и поддерживаемой программе, приводящей пользователей в восторг. Книга охватывает различные темы – от личной ответственности и карьерного роста до архитектурных методик, придающих программам гибкость и простоту в адаптации и повторном использовании.Прочитав эту книгу, вы научитесь:Бороться с недостатками программного обеспечения;Избегать ловушек, связанных с дублированием знания;Создавать гибкие, динамичные и адаптируемые программы;Избегать программирования в расчете на совпадение;Защищать вашу программу при помощи контрактов, утверждений и исключений;Собирать реальные требования;Осуществлять безжалостное и эффективное тестирование;Приводить в восторг ваших пользователей;Формировать команды из программистов-прагматиков и с помощью автоматизации делать ваши разработки более точными.

А. Алексашин , Дэвид Томас , Эндрю Хант

Программирование / Книги по IT