Советы по Delphi

         

Загрузка изображения/курсора из 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.

[000840]



Содержание раздела