Подключение ресурсов в исполняемые файлы Delphi
Можно включить любой файл в исполнимый файл для использования как ресурс. Некоторые виды ресурсов признаются API и могут использоваться непостредственно. Другие просто принимаются как двоичные данные. В этой статье мы рассмотрим примеры обоих видов.
Чтобы создать файл ресурса, мы начинаем с исходного файла *.RC, например, по имени Resources.rc
, который содержит виды ресурсов (имя, класс и файл).
sample_bmp BITMAP sample . bmp sample_ico ICON sample . ico sample_cur CURSOR sample . cur sample_ani ANICURSOR sample . ani sample_jpg JPEG sample . jpg sample_wav WAVE sample . wav sample_txt TEXT sample . txt |
Имена ресурсов (sample_bmp, sample_ico и т.д.) произвольны. Вид ресурса может быть поддерживаемый API (BITMAP, ICON, CURSOR) или произвольный (JPEG, WAVE, TEXT). Имена файла определяют файлы, которые будут включены в .RES, а позже .EXE.
Теперь мы должны скомпилировать .RC файл, чтобы получился .RES файл. Для этого мы можем использовать Borland Resource Compiler
(brcc32.exe).
Набрав в командной строке, мы получим:
C:\DELPHI\P0025>brcc32 resources Borland Resource Compiler Version 5.40 Copyright (c) 1990 , 1999 Inprise Corporation. All rights reserved. C:\DELPHI\P0025>_ |
Для того, чтобы присоединить файл ресурсов к нашему проекту, мы используем директиву {$R} или {$RESOURCE}:
{$R resources.res} |
Загрузка поддерживаемых ресурсов (BITMAP, CURSOR, ICON) проста, так как Windows API предоставляет нам функции LoadBitmap, LoadCursor, LoadIcon соответственно для получения дескрипторов этих элементов.
Image1 . Picture . Bitmap . Handle := LoadBitmap(hInstance, 'sample_bmp' ); Icon . Handle := LoadIcon(hInstance, 'sample_ico' ); Screen . Cursors[ 1 ] := LoadCursor(hInstance, 'sample_cur' ); |
Другие ресурсы использовать немного сложнее. Давайте начнем с изображения JPEG. Мы будем использовать функцию TResouceStream, чтобы загрузить ресурс как поток, который будет загружен в объект TJpegImage.
function GetResourceAsJpeg( const resname: string ): TJPEGImage; var Stream: TResourceStream; begin Stream := TResourceStream . Create(hInstance, ResName, 'JPEG' ); try Result := TJPEGImage . Create; Result . LoadFromStream(Stream); finally Stream . Free; end ; end ; |
Пример:
var Jpg: TJPEGImage; begin // ... Jpg := GetResourceAsJpeg( 'sample_jpg' ); Image2 . Picture . Bitmap . Assign(Jpg); Jpg . Free; // ... end ; |
Для WAV файлов мы нуждаемся в указателе на ресурс, загруженный в память, а для текстового файла мы должны загрузить ресурс в строку. Мы можем сделать это, используя TResourceStream, но давайте посмотрим пример, который использует API:
function GetResourceAsPointer(ResName: pchar ; ResType: pchar ; out Size: longword ): pointer ; var InfoBlock: HRSRC; GlobalMemoryBlock: HGLOBAL; begin InfoBlock := FindResource(hInstance, resname, restype); if InfoBlock = 0 then raise Exception . Create(SysErrorMessage(GetLastError)); size := SizeofResource(hInstance, InfoBlock); if size = 0 then raise Exception . Create(SysErrorMessage(GetLastError)); GlobalMemoryBlock := LoadResource(hInstance, InfoBlock); if GlobalMemoryBlock = 0 then raise Exception . Create(SysErrorMessage(GetLastError)); Result := LockResource(GlobalMemoryBlock); if Result = nil then raise Exception . Create(SysErrorMessage(GetLastError)); end ; function GetResourceAsString(ResName: pchar ; ResType: pchar ): string ; var ResData: PChar ; ResSize: Longword ; begin ResData := GetResourceAsPointer(resname, restype, ResSize); SetString(Result, ResData, ResSize); end ; |
Примеры вызовов:
var sample_wav: pointer ; procedure TForm1 . FormCreate(Sender: TObject); var size: longword ; begin { ... } sample_wav := GetResourceAsPointer( 'sample_wav' , 'wave' , size); Memo1 . Lines . Text := GetResourceAsString( 'sample_txt' , 'text' ); end ; |
Как только мы загрузим WAV ресурс в память, мы можем его проигрывать столько раз, сколько нужно, используя sndPlaySound, объявленную в модуле MMSystem.
procedure TForm1 . Button1Click(Sender: TObject); begin sndPlaySound(sample_wav, SND_MEMORY or SND_NODEFAULT or SND_ASYNC); end ; |
Есть некоторые ресурсы (типа шрифтов, анимированных курсоров), которые не могут использоваться из памяти. Мы обязательно должны сохранить эти ресурсы во временном файле на диске и загружать их оттуда. Следующая функция сохраняет ресурс в файл:
procedure SaveResourceAsFile( const ResName: string ; ResType: pchar ; const FileName: string ); begin with TResourceStream . Create(hInstance, ResName, ResType) do try SaveToFile(FileName); finally Free; end ; end ; |
Следующая функция использует предыдущую, чтобы сохранить ресурс во временном файле:
function SaveResourceAsTempFile( const ResName: string ; ResType: pchar ): string ; begin Result := CreateTempFile; SaveResourceAsFile(ResName, ResType, Result); end ; |
Следующая функция использует SaveResourceAsTempFile, чтобы сохранить ресурс анимированного курсора во временном файле, затем загризить этот ресурс из файла при помощи LoadImage и затем удалить временный файл. Функция возвращает дескриптор, возвращенный функцией LoadImage.
function GetResourceAsAniCursor( const ResName: string ): HCursor; var CursorFile: string ; begin CursorFile := SaveResourceAsTempFile(ResName, 'ANICURSOR' ); Result := LoadImage( 0 , PChar (CursorFile), IMAGE_CURSOR, 0 , 0 , LR_DEFAULTSIZE or LR_LOADFROMFILE); DeleteFile(CursorFile); if Result = 0 then raise Exception . Create(SysErrorMessage(GetLastError)); end ; |
Пример вызова:
Screen . Cursors[ 1 ] := GetResourceAsAniCursor( 'sample_ani' ); Form1 . Cursor := 1 ; |
Комментарии