Delphi`de Uygulama içerisine dosya gömmek

Programlama20/11/2008


İkonları, kursörleri, animated kursörleri, bitmap, jpeg görüntüleri, ses dosyalarını, text dosyaları veya diğer dosyaları Delphi exe`sine nasıl gömebiliriz?

Resource (*.res) dosyaları kullanarak her türlü dosyayı exe dosyanın içine gömmek mümkündür. Bazı belirli dosya türleri API tarafından tanınır ve doğrudan kullanılabilir. Bu makalede her iki türden de örnekler göreceğiz.

Resource dosyasını oluşturmak için bir source dosyası (*.rc) oluştururuz (örneklerde resources.rc). Bu dosya basit bir tekst dosyadı ve resource bilgilerini ihtiva eder (adı, türü ve dosyası).

    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

Resource`ların isimleri (sample_bmp, sample_ico, vs.) keyfidir, istediğiniz ismi verebilirsiniz.Resource`un türü API tarafından tanınan bir tür olmalıdır (BITMAP, ICON, CURSOR) ya da keyfi olabilir (JPEG, WAVE, TEXT).

Dosya isimleri *.res dosyasının içinde (daha sonra da exe dosyanın) ihtiva edilecek olan dosyaları belirtir.

Şimdi .res dosyasını üretmek için .rc dosyasını derlemeliyiz. Bunun için, muhtemelen Delphi`nin BIN folder`ında bulunan, Borland Resource Compiler`ı (brcc32.exe) kullanabiliriz. Bu basit bir komut satırı programıdır, .rc dosyasının ismini parametre olarak vermemiz yeterlidir.

    brcc32 resources

Bağlayıcıya (linker) resource dosyasını exe`nin içine gömmesini söylemek için

    {$R *.dfm}

ifadesinin hemen yanına

    {$R resources.res}

ifadesini eklemeliyiz.
Bu durumda şöyle görünecek:

    $R *.dfm}{$R resources.res}

Api tarafından tanınan resource türlerini (BITMAP, ICON ve CURSOR) yüklemek, api LoadBitmap, LoadIcon ve LoadCursor gibi fonksiyonlar sağladığı için daha kolaydır.

    Image1.Picture.Bitmap.Handle :=
    LoadBitmap(hInstance, `sample_bmp`);
    Icon.Handle := LoadIcon(hInstance, `sample_ico`);
    Screen.Cursors[1] := LoadCursor(hInstance,`sample_cur`);


Görüntü resourcelarını yüklemek için gerek değişik seçenekleri görmek için LoadImage api`sini inceleyiniz.

Diğer resource türlerini yüklemek bi parça daha zordur.JPEG dosyaları ile başlayalım. Aşağıdaki Fonksiyon, Recource`u, TJPEGImage nesnesine yüklenecek olan bir stream olarak yüklemek için TResourceStream`i kullanır (Amma kastı bu cümle offff :) çN).

    function GetResourceAsJpeg(const resname: string): JPEGImage;
    var
    Stream: TResourceStream;
    begin
    Stream := TResourceStream.Create(hInstance, ResName, `JPEG`);
    try
    Result := TJPEGImage.Create;
    Result.LoadFromStream(Stream);
    finally
    Stream.Free;
    end;
    end;

örnek:

    var
    Jpg: TJPEGImage;
    begin
    // ...
    Jpg := GetResourceAsJpeg(`sample_jpg`);
    Image2.Picture.Bitmap.Assign(Jpg);
    Jpg.Free;
    // ...
    end;

Ses dosyaları için, hafızaya yüklenmiş olan resource`u işaret eden bir pointer`a ihtiyacımız var, text dosya için ise resource`u bir string`e yüklemeliyiz. Bunu TResourceStream kullanarak da yapabiliriz ama gelin API ile yapan bir örnek görelim:

    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;
    Sample calls:

    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;

Ses kaynağını hafızaya bir kez yüklediğimizde, sndPlaySound API`sini kullanarak istediğimiz kadar çalabiliriz ancak bunun için uses kısmına MMSystem

unit`ini eklememiz gerekiyor:

    procedure TForm1.Button1Click(Sender: TObject);
    begin
           sndPlaySound(sample_wav, SND_MEMORY or SND_NODEFAULT or SND_ASYNC);
    end;

Fontlar ve animated kursörler gibi bazı resourcelar hafızadan (memory) kullanılamaz. Bunları geçici bir dosyaya kaydetmeli ve oradan kullanmalıyız. Aşağıdaki fonksiyon bir resource`u bir dosyaya kaydeder:

    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;

Aşağıdaki fonksiyon, bir önceki fonksiyonu kullanarak resource`u geçici dosyaya kaydeder.

    function SaveResourceAsTempFile(const ResName: string;ResType: pchar): string;
    begin
    Result := CreateTempFile;
    SaveResourceAsFile(ResName, ResType, Result);
    end;

CrateTempFile dosyasının tartışması bu makalenin konusunun dışındadır ve uygulaması gazeteye (newsletter) eklenmiş olan örnekte görülebilir. (Herhalde web sitesinde bi yerde bi örnek var. çN)

Aşağıdaki fonksiyon, bir animated kursör`ü geçici bir dosyaya yükler (bunun için SaveResourceAsTempFile fonksiyonunu kullanır) sonra bu kursörü loadimage ile yükler ve sonunda geçici dosyayı siler. Fonksiyon LoadImage tarafından dönderilen HANDLE`ı döndürür.

    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;
    Sample call:

    Screen.Cursors[1] :=GetResourceAsAniCursor(`sample_ani`);
    Form1.Cursor := 1;


Yazan: Mr. Ernesto De Spirito
Kaynak: http://www.howtodothings.com/ViewArticle.aspx?Article


MSDN kütüphanesinde resource dosyaları hakkında daha fazla bilgi bulabilirsiniz.
http://msdn.microsoft.com/library/en-us/winui/hh/winui/rc_6cs3.asp
Etiketler: