А. Григорьев - О чём не пишут в книгах по Delphi Страница 2
А. Григорьев - О чём не пишут в книгах по Delphi читать онлайн бесплатно
Программированию в Windows на основе API посвящено много книг, а также материалов в Интернете. Но если все делать только с помощью API, то даже для того, чтобы создать пустое окно, потребуется написать несколько десятков строк кода, а о визуальном проектировании такого окна придется вообще забыть. Поэтому желательно как-то объединить мощность API и удобство VCL. О том, как это сделать, мы и поговорим в этой главе. В первой части главы рассматриваются общие принципы использования API и интеграции этого интерфейса с VCL. Во второй части разбираются простые примеры, иллюстрирующие теорию. В третьей части представлено несколько обобщающих примеров использования API — небольших законченных приложений, использующих различные функции API для решения комплексных задач.
1.1. Основы работы Windows API в VCL-приложениях
В данном разделе будет говориться о том. как совместить Windows API и компоненты VCL. Предполагается, что читатель владеет основными методами создания приложений с помощью VCL а также синтаксисом языка Delphi, поэтому на этих вопросах мы останавливаться не будем. Так как "официальные" справка и примеры работы с API предполагают работу на С или C++, и это может вызвать трудности у человека, знакомого только с Delphi, здесь также будет уделено внимание тому, как правильно читать справку и переводить содержащийся в ней код с C/C++ на Delphi.
1.1.1. Что такое Windows API
Windows API — это набор функций, предоставляемых операционной системой каждой программе. Данные функции находятся в стандартных динамически компонуемых библиотеках (Dynamic Linked Library. DLL), таких как kernel32.dll, user32.dll, gdi32.dll. Указанные файлы располагаются в системной директории Window. Вообще говоря, каждая программа должна самостоятельно заботиться о том. чтобы подключить эти библиотеки. DLL могут подключаться к программе статически и динамически. В первом случае связь с библиотекой прописывается в исполняемом файле программы, и система при запуске этой программы сразу же загружает в ее адресное пространство и библиотеку. Если требуемая библиотека на диске не найдена, запуск программы будет невозможен. В случае динамического подключения программа загружает библиотеку в любой удобный для нее момент времени с помощью функции LoadLibrary. Если при этом возникает ошибка из-за того, что библиотека не найдена на диске, программа может самостоятельно решить, как на это реагировать.
Статическая загрузка проще динамической, но динамическая гибче. При динамической загрузке программист может, во-первых, выгрузить библиотеку, не дожидаясь окончания работы программы. Во-вторых, программа может продолжить работу, даже если библиотека не найдена. В-третьих, возможна загрузка тех DLL, имена которых неизвестны на момент компиляции. Это позволяет расширять функциональность приложения после передачи его пользователю с помощью дополнительных библиотек (в англоязычной литературе такие библиотеки обычно называются plug-in).
Стандартные библиотеки необходимы самой системе и всем программам, они всегда находятся в памяти, и поэтому обычно они загружаются статически. Чтобы статически подключить в Delphi некоторую функцию Windows API. например, функцию GetWindowDC из модуля user32.dll, следует написать конструкцию вида
function GetWindowDC(Wnd: HWnd); HDC; stdcall;
external 'user32.dll' name 'GetWindowDC';
В результате в специальном разделе исполняемого файла, который называется таблицей импорта, появится запись, что программа импортирует функцию GetWindowDC из библиотеки user32.dll. После такого объявления компилятор будет знать, как вызывать эту функцию, хотя ее реальный адрес будет внесен в таблицу импорта только при запуске программы. Обратите внимание, что функция GetWindowDC, как и все функции Windows API, написана в соответствии с моделью вызова stdcall, а в Delphi по умолчанию принята другая модель — register (модель вызова определяет, как функции передаются параметры). Поэтому при импорте функций из стандартных библиотек необходимо явно указывать эту модель (подчеркнем, что это относится именно к стандартным библиотекам; другие библиотеки могут использовать любую другую модель вызова, разработчик библиотеки свободен в своем выборе). Далее указывается, из какой библиотеки импортируется функция и какое название в ней она имеет. Дело в том, что имя функции в библиотеке может не совпадать с тем, под которым она становится известной компилятор). Это может помочь разрешить конфликт имен при импорте одноименных функций из разных библиотек, а также встречается в других ситуациях, которые мы рассмотрим позже. Главным недостатком DLL следует считать то. что в них сохраняется информация только об именах функций, но не об их параметрах. Поэтому если при импорте функции указать не те параметры, которые подразумевались автором DLL, то программа будет работать неправильно (вплоть до зависания), а ни компилятор, ни операционная система не смогут указать на ошибку.
Обычно программе требуется много различных функций Windows API. Декларировать их все довольно утомительно. К счастью. Delphi избавляет программиста от этой работы: многие из этих функций уже описаны в соответствующих модулях, достаточно упомянуть их имена в разделе uses. Например, большинство общеупотребительных функций описаны в модулях Windows и Messages.
Функции API, которые присутствуют не во всех версиях Windows, предпочтительнее загружать динамически. Например, если программа статически импортирует функцию SetLayeredWindowsAttributes, она не запустится в Windows 9x, где этой функции нет — система, встретив ее упоминание в таблице импорта, прервет загрузку программы. Поэтому, если требуется, чтобы программа работала и в Windows 9x, эту функцию следует импортировать динамически. Отметим, что компоновщик в Delphi помещает в таблицу импорта только те функции, которые реально вызываются программой. Поэтому наличие декларации SetLayeredWindowsAttributes в модуле Windows не помешает программе запускаться в Windows 9x, если она не вызывает эту функцию.
1.1.2. Как получить справку по функциям Windows API
Для тех, кто решит работать с Windows API, самым необходимым инструментом становится какая-либо документация по этим функциям. Их так много, что запомнить все совершенно нереально, поэтому работа без справочника под рукой просто невозможна.
Первоисточник информации по технологиям Microsoft для разработчика Microsoft Developer's Network (MSDN). Это отдельная справочная система, не входящая в комплект поставки Delphi. MSDN можно приобрести отдельно или воспользоваться online-версией, находящейся по адресу: http://msdn.microsoft.com (доступ к информации свободный, регистрация не требуется). MSDN содержит не только информацию об API, но и все, что может потребоваться программисту, использующему различные средства разработки от Microsoft. Кроме справочного материала, MSDN включает в себя спецификации стандартов и технологий, связанных с Windows, статьи из журналов, посвященных программированию, главы из некоторых книг. И вся эта информация крайне полезна разработчику. Кроме того, MSDN постоянно обновляется, информация в нем наиболее актуальна. Пример справки из MSDN показан на рис. 1.1.
Рис. 1.1. Online-вариант MSDN (показана справка по функции DeleteObject)
ПримечаниеОтметим, что MSDN содержит также описание функций операционной системы Windows СЕ. Интерфейс Windows СЕ API на первый взгляд очень похож на Windows API, но различия между ними есть, и иногда весьма значительные. Поэтому при использовании MSDN не следует выбирать раздел API Reference — он целиком посвящен WinCE API.
В комплект поставки Delphi входит справочная система, содержащая описание функций Windows API. Справочная система в Delphi до 7-й версии включительно была построена на основе hlp-файлов. Применительно к справке по Windows API это порождало две проблемы. Во-первых, hlp-файлы имеют ограничение по числу разделов в справочной системе, поэтому объединить в одной справке информацию и по Delphi, и по Windows API было невозможно, — эти две справки приходилось читать по очереди. Чтобы открыть файл справки по Windows API, нужно было в редакторе кода поставить курсор на название какой-либо функции API и нажать клавишу <F1>— в этом случае вместо справки по Delphi открывалась справка по Windows API. Второй вариант — в меню Программы найти папку Delphi, а в ней — папку Help\MS SDK Files и выбрать требуемый раздел. Можно также вручную открыть файл MSTools.hlp. В ранних версиях Delphi он находится в каталоге $(Delphi)\Help, в более поздних его нужно искать в $(Program Files)\Common Files. Окно старой справки показано на рис. 1.2.
Вторая проблема, связанная со справкой на основе hlp-файлов,— это то обстоятельство, что разработчики Delphi, разумеется, не сами писали эту справку, а взяли ту, которую предоставила Microsoft. Microsoft же последнюю версию справки в формате НLР выпустила в тот момент, когда уже вышла Windows 95, но еще не было Windows NT 4. Поэтому про многие функции, прекрасно работающие в NT 4, там написано, что в Windows NT они не поддерживаются, т.к. в более ранних версиях они действительно не поддерживались. В справке, поставляемой с Delphi 7 (и, возможно, с некоторыми более ранними версиями), эта информация подправлена, но даже и там отсутствуют функции, которые появились только в Windows NT 4 (как, например, CoCreateInstanceEx). И уж конечно, бесполезно искать в этой справке информацию о функциях, появившихся в Windows 98, 2000, XР. Соответственно, при работе в этих версиях Delphi даже не возникает вопрос, что предпочесть для получения информации о Windows API, — справку, поставляемую с Delphi, или MSDN. Безусловно, следует выбрать MSDN. Справка, поставляемая с Delphi, имеет только одно преимущество по сравнению с MSDN: ее можно вызывать из среды нажатием клавиши <F1>. Но риск получить неверные сведения слишком велик, чтобы это преимущество могло быть серьезным аргументом. Единственная ситуация, когда предпочтительна справка, поставляемая с Delphi, — это случай, если у вас нет достаточно быстрого доступа к Интернету для работы с online-версией MSDN и нет возможности приобрести и установить его offline-версию.
Жалоба
Напишите нам, и мы в срочном порядке примем меры.