Практика
Хранение ресурсов внутри исполняемого файла и их использование

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика


Надеюсь, из заголовка вы уже поняли, о чем пойдет речь. Если нет, то я коротко расскажу. Файл(ы) ресурсов позволяет хранить внутри созданного вами приложения другие файлы, такие как картинки, музыку, видео, html-страницы и т.д. и т.п., короче все, что вашей душе угодно. Из выше сказанного очевидна область применения - вы можете сделать свой собственный, ни на чей не похожий, инсталлятор, или впарить другу трояна под видом вполне невинной программы. Одним словом, вы ограничены только собственной фантазией.

Демонстрационный пример, который я приготовил, будет включать в себя набор картинок, последовательное воспроизведение которых создаст эффект анимации, и один звуковой файл, которым будет сопровождаться закрытие формы. Создадим два файла - MyPicture.rc и MyWave.rc. В первом файле перечислим по порядку все картинки:

1 RCDATA "radar000.jpg"
2 RCDATA "radar001.jpg"
3 RCDATA "radar002.jpg"
4 RCDATA "radar003.jpg"
5 RCDATA "radar004.jpg"
6 RCDATA "radar005.jpg"

Это не полный листинг файла, так как он слишком велик (127 строк), но думаю, вы поняли его принцип. Отмечу одно, в виду того, что с таким количеством картинок удобнее всего работать в цикле, то я их проиндексировал по порядку, однако вместо индекса ресурсу можно дать и имя. Так и поступим со вторым файлом:

MyWave RCDATA LOADONCALL ir_end.wav

Теперь откомпилируем их при помощи утилиты brcc32.exe (она есть в Delphi), запустив ее с параметром, указывающим путь к файлу *.rc - brcc32.exe MyPicture.rc и brcc32.exe MyWave.rc. Чтобы встроить эти ресурсы в наш исполняемый файл, напишем следующее:

uses
  {...}, JPEG, MMSystem;

{...}

implementation

{$R *.dfm}
{$R MyPicture.res}
{$R MyWave.res}

Теперь, когда все приготовления закончены, начнем работу со встроенными ресурсами. Сначала решим задачу с анимацией - напишем функцию, которая по переданному ей индексу, вернет нам соответствующую картинку:

function LoadJPEGfromEXE( Number: integer ): TJPEGImage;
var
  ResStream: TResourceStream;
begin
   Result := TJPEGImage.Create;
   ResStream := TResourceStream.CreateFromID( HInstance, Number, RT_RCDATA );
   Result.LoadFromStream( ResStream );
   ResStream.Free;
end;

Функция очень проста и в комментариях не нуждается. Теперь осталось воспроизвести все картинки по порядку, например, так:

procedure TForm1.AutoPlayClick(Sender: TObject);
var
  i: integer;
  tmpJPG: TJPEGImage;
begin
   for i := 1 to 127 do
   begin
      TrackBarNum.Position := i;
      tmpJPG := LoadJPEGfromEXE( i );
      PaintBox.Canvas.Draw( 0, 0, tmpJPG );
      Application.ProcessMessages;
      tmpJPG.Free;
      Sleep( TrackBarSpeed.Position );
      if Application.Terminated then Break;
   end;
end;

TrackBarNum отображает номер воспроизводимой в данный момент картинки, а TrackBarSpeed задает интервал паузы. Теперь осталось разобраться только со звуком. Пишем следующее:

procedure RetrieveMyWave;
var
  WaveHandle: THandle;
  WavePointer: Pointer;
begin
   WaveHandle := FindResource( hInstance, 'MyWave', RT_RCDATA );
   if WaveHandle <> 0 then
   begin
      WaveHandle := LoadResource( hInstance, WaveHandle );
      if WaveHandle <> 0 then
      begin
         WavePointer := LockResource( WaveHandle );
         sndPlaySound( WavePointer, SND_MEMORY or SND_ASYNC );
         UnlockResource( WaveHandle );
         FreeResource( WaveHandle );
      end;
   end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   RetrieveMyWave;
   Sleep( 350 );
end;

Небольшая задержка при закрытии формы нужна для того, чтобы воспроизводимый звук успел проиграть до конца, иначе мы его просто не услышим. И последнее, допустим, мы захотели извлечь файлы из ресурса, и сохранить их (например ты решил порадовать друга трояном) на харде, нет ничего проще, пишем:

// Сохранение текущей картинки
procedure TForm1.SavePicClick(Sender: TObject);
begin
   LoadJPEGfromEXE( TrackBarNum.Position ).SaveToFile(
                    Format( 'Pic%.3d.jpg', [TrackBarNum.Position-1] ) );
end;

// Сохранение звука
procedure TForm1.SaveSoundClick(Sender: TObject);
var
  ResStream: TResourceStream;
begin
   ResStream := TResourceStream.Create( HInstance, 'MyWave', RT_RCDATA );
   ResStream.SaveToFile( 'ir_end.wav' );
   ResStream.Free;
end;

Вот и все. Главное понять принцип, и тогда работа с файлами других типов не вызовет у вас затруднений, ведь по сути там все делается идентично, хотя, как вы понимаете, могут быть и нюансы. Удачи вам в программировании.

.: Пример к данной статье :.
.: Все необходимое для создания файлов ресурсов :.


При использовании материала - ссылка на сайт обязательна