Завантаження бібліотеки в пам'ять
Щоб програма змогло викликати бібліотечну функцію, ця бібліотека повинна бути заздалегідь завантажена в оперативну пам'ять. Точніше, вона повинна знаходитися в адресному просторі даного програма, тобто бути прикомпонована до нього. Існують два способи динамічної компоновки: явний і неявний.
Неявна компоновка, яка працювала у всіх прикладах цього розділу, виконується автоматично, і програмістові додатково піклуватися про неї не потрібно. Delphi додає посилання на функції із завантажуваної DLL в зухвалий (виконуваний) файл, і при запуску такого файлу операційна система підключає всі вказані в нім бібліотеки. Перевагою такого способу компоновки є його простота, але є і недоліки: по-перше, автоматично завантажуються всі бібліотеки, функції з яких можуть коли-небудь знадобитися, навіть якщо в даному сеансі роботи додаток жодного разу до них не звернеться. Внаслідок цього програма не може запуститися, якщо одна з необхідних DLL відсутня, хоч би її відсутність і було некритичне для його виконання. По-друге, кожна потрібна програмам бібліотека повинна знаходитися в одному із стандартних місць: у теці, що містить виконуваний файл; у поточній теці; у системних теках Windows\System32 або Windows; у теках, перерахованих в змінній PATH. Щоб задати інший шлях пошуку, потрібно внести до системного реєстру зміни, які подіють на всі процеси, що працюють в системі.
Явна компоновка усуває ці недоліки за рахунок додаткових зусиль програміста. Цей спосіб дозволяє підвантажувати DLL в міру необхідності і самостійно приймати вирішення у разі відсутності необхідної бібліотеки. Рекомендується явно компонувати всі динамічні бібліотеки, окрім бібліотек, життєво необхідних для роботи програма, функції з яких обов'язково викликаються в кожному сеансі його роботи.
Явну компоновку бібліотеки реалізують функції з Windows API: LoadLibrary і LoadLibraryEx (завантаження) і FreeLibrary (вивантаження). Функція LoadLibrary успадкована від 16-бітової версії Windows, а LoadLibraryEx вперше з'явилася в Win32 і пропонує ширші можливості управління завантаженням бібліотеки.
Заголовок функції LoadLibrary виглядає таким чином:
HINSTANCE LoadLibrary(LPCTSTR lpLibFileName);
Її єдиний аргумент — ім'я файлу або шлях до файлу бібліотеки, тип аргументу — посилання на нуль-завершенную рядок (у Delphi це тип PChar). Функція повертає дескриптор (handle) завантаженої бібліотеки або значення 0, якщо бібліотека не знайдена.
Функція LoadLibraryEx приймає більше аргументів:
HINSTANCE LoadLibraryEx(
LPCTSTR lpLibFileName
HANDLE hFile
DWORD dwFlags );
Перший аргумент має той же сенс, що для функції LoadLibrary. Розгляд два інших виходить за рамки цієї книги; ми лише стисло вкажемо, що вони дозволяють, наприклад, відключити перевірку залежності завантажуваної бібліотеки від інших бібліотек, вказати спосіб пошуку бібліотек на диску і тому подібне
Для вивантаження з пам'яті динамічної бібліотеки служить функція FreeLibrary, що повертає логічне значення (True у разі успішного виконання, False у разі помилки):
BOOL FreeLibrary(HMODULE hLibModule);
Зберігання ресурсів в динамічній бібліотеці
Читання ікон з динамічної бібліотеки
Як вже мовилося, в динамічних бібліотеках можуть міститися не тільки процедури і функції, але і так звані ресурси Windows (зображення, значки, строкові константи і т. п.). У системній теці Windows є безліч DLL-библиотек, що зберігають значки (ікони). Залежно від використовуваної версії Windows ці файли називаються по-різному і розташовані в різних місцях. Наступний приклад покаже, яким чином рахувати всі значки з DLL-библиотеки Shell32.dll, яка знаходиться в системній теці. Шлях до системної теки можна отримати, викликавши функцію GetSystemDirectory.
Якщо створити нове програма і помістите на форму одну кнопку, після натиснення на яку програма прочитає і намалює в своєму головному вікні всі значки, що зберігаються в бібліотеці Shell32.dll.
Для витягання значків служить функція Extract Icon, реалізована в модулі SHELLAPI. Додайте цей модуль в секцію Uses.
uses
..., SHELLAPI;
procedure TForml.ButtonlClick(Sender: TObject); const
// ширина значка в пікселах ICONWIDTH = 3 4; var
Icon: TIcon;
Count, Columns, i, X, Y: Integer; FileName: String; SysDir: PAnsiChar; begin
// виділяємо пам'ять для рядка - шляхи до системної теки
GetMem(SysDir, Мах_ратн);
// отримуємо повний шлях до системної теки
GetSystemDirectory(SysDir, MAX_PATH);
// дописуємо до нього зворотний слэш і ім'я файлу 'shell32.dll'
FileName := IncludeTrailingPathDelimiter( String(SysDir))+
'shell32.dll'; // кількість значків, що відображаються, в ряду залежить від ширини вікна Columns := ClientWidth div ICONWIDTH; // отримуємо кількість значків в бібліотеці
Count := Extractlcon(Handle, PAnsiChar(FileName), Cardinal(-1)); Caption := 'Файл ' + FileName + ' містить ' +
IntToStr(Count)+ ' значків'; Icon := TIcon.Create; // створюємо об'єкт класу TIcon for i := 0 to Count-1 do begin // отримуємо дескриптор значка
Icon.Handle := Extractlcon(Handle, PChar(FileName), i); if Icon <> nil then begin // якщо він ненульовий // обчислюваний координати для виведення значка X := (i mod Columns); Y := (i div Columns);
// виводимо, вважаючи отриману крапку верхнім лівим кутом Canvas.Draw(X * ICONWIDTH, Y * ICONWIDTH, Icon); Destroylcon(Icon.Handle); end;
// звільняємо пам'ять Icon.Free; FreeMem(SysDir); end;
Для доступу до значків з бібліотеки служить функція Extraction Fp аргументами є дескриптор вікна, ім'я файлу бібліотеки і номер значка в нім. Якщо як номер вказати значення - 1, то функція поверне кількість значків у файлі.
Для малювання значка ми викликаємо метод Canvas . Draw, який спосо бен вивести на полотно будь-яке зображення - об'єкт класу, похідного від TGraphic Клас TIcon, призначений для зберігання зображай ікон, є спадкоємцем TGraphic.
