Загрузка изображения или курсора из RES-файла

Загрузка изображений и курсоров из RES-файлов

Изображения и курсоры могут храниться в файлах ресурсов (RES) и прилинковываться (связаваться) к EXE-файлу вашего приложения. RES-файлы могут создаваться с помощью Delphi утилит Image Editor и Borland Resource Workshop, входящие в поставку Delphi RAD Pack. Изображения и курсоры, хранимые в RES-файлах (после упаковки их в EXE или DLL) могут быть извлечены с помощью API функций LoadBitmap и LoadCursor соответственно.

Загрузка изображений

Функция API LoadBitmap определена следующим образом:

function LoadBitmap(Instance: THandle; BitmapName: PChar): HBitmap;

Первый параметр должен содержать дескриптор модуля (EXE или DLL), содержащего файл RES, из которого вы хотите получить ресурс. Delphi хранит дескриптор запущенного EXE-файла в глобальной переменной с именем Hinstance. В приведенном ниже примере мы предполагаем, что модуль, из которого мы пытаемся загрузить изображение, — ваше приложение. Тем не менее, модуль мог бы быть другим EXE- или DLL-файлом. Следующий пример загружает изображение с именем BITMAP_1 из RES-файла, прилинкованного к EXE-файлу приложения:

procedure TForm1.Button1Click(Sender: TObject);

var

Bmp: TBitmap;

begin

Bmp := TBitmap.Create;

Bmp.Handle := LoadBitmap(HInstance,'BITMAP_1');

Canvas.Draw(0, 0, Bmp);

Bmp.Free;

end;

Имеется один недостаток использования API вызова LoadBitmap: LoadBitmap все же является API вызовом Windows 3.0, и грузит изображение только как DDB (Device Dependent Bitmaps). Это может вызвать проблемы с цветовой палитрой при загрузке DIB (Device Independent Bitmaps) из RES-файла. Приведенный ниже код может использоваться для извлечения DIB-ов из RES-файлов. Данный код загружает изображение как общий ресурс, передает его в поток, после чего делает Delphi вызов LoadFromStream, реализующий палитру автоматически.

procedure TForm1.Button1Click(Sender: TObject);

const

BM = $4D42; {Идентификатор типа изображения}

var

Bmp: TBitmap;

BMF: TBitmapFileHeader;

HResInfo: THandle;

MemHandle: THandle;

Stream: TMemoryStream;

ResPtr: PByte;

ResSize: Longint;

begin

BMF.bfType := BM;

{Ищем, загружаем и блокируем ресурс, содержащий BITMAP_1}

HResInfo := FindResource(HInstance, 'BITMAP_1', RT_Bitmap);

MemHandle := LoadResource(HInstance, HResInfo);

ResPtr := LockResource(MemHandle);

{Создаем Memory-поток, устанавливаем его размер, записываем

туда заголовок изображения и, наконец, само изображение }


Stream := TMemoryStream.Create;

ResSize := SizeofResource(HInstance, HResInfo);

Stream.SetSize(ResSize SizeOf(BMF));

Stream.Write(BMF, SizeOf(BMF));

Stream.Write(ResPtr^, ResSize);

{Освобождаем поток и сбрасываем его позицию в 0}

FreeResource(MemHandle);

Stream.Seek(0, 0);

{Создаем TBitmap и загружаем изображение из MemoryStream}

Bmp := TBitmap.Create;

Bmp.LoadFromStream(Stream);

Canvas.Draw(0, 0, Bmp);

Bmp.Free;

Stream.Free;

end;

Загрузка курсоров

Функция API LoadCursor определена следующим образом:

function LoadCursor(Instance: THandle; CursorName: PChar): HCursor;

Первый параметр Instance должен содержать дескриптор модуля, содержащего файл RES. Как и пример, приведенный выше, данный пример предполагает, что модуль, из которого мы пытаемся загрузить курсор, — ваше приложение. Второй параметр — имя курсора. В секции interface сделайте следующее объявление:

const

crMyCursor = 5; {Другие модули могут также использовать эту константу}

Затем добавьте следующие две строчки к обработчику события формы OnCreate:

procedure TForm1.FormCreate(Sender: TObject);

begin

Screen.Cursors[crMyCursor] := LoadCursor(HInstance, 'CURSOR_1');

Cursor := crMyCursor;

end;

или же вы можете изменить один из стандартных курсоров Delphi как показано ниже (константы Cursor описаны в электронной справке в статье Cursors Property):

procedure TForm1.FormCreate(Sender: TObject);

begin

{Данный пример изменяет курсор SQL Hourglass}

Screen.Cursors[crSQLWait] := LoadCursor(HInstance, 'CURSOR_1');

end;

Примечание: в нормальной ситуации необходимо удалить любые ресурсы курсоров с помощью DeleteCursor, тем не менее, в Delphi в этом нет необходимости, поскольку Delphi сама удаляет все курсоры из массива Cursors.