Delphi'de Dosyaları EXE dosyanın içine gömmek (Embed etmek)

Yazdığınız makaleleri ve üyelerimizin işine yarayacağını düşündüğünüz kodlarınızı gönderebilirsiniz. Bu foruma soru sormayın!
Cevapla
Kullanıcı avatarı
hdayi
Kıdemli Üye
Mesajlar: 1284
Kayıt: 29 Oca 2004 01:53
Konum: Erciyes'in eteklerinden.

Delphi'de Dosyaları EXE dosyanın içine gömmek (Embed etmek)

Mesaj gönderen hdayi »

Bir ses dosyasını EXE'nin içine gömmek için uğraşırken aşağıdaki makaleyi buldum ve tercüme ettim.
Umarım faydası olur.

**************************************
Delphi'de Dosyaları EXE dosyanın içine gömmek:
Yazan:Mr. Ernesto De Spirito
Kaynak:http://www.howtodothings.com/ViewArticl ... rticle=415

İ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;
Evet, hepsi bu. Umarım faydalı olur. MSDN kütüphanesinde

resource dosyaları hakkında daha fazla bilgi

bulabilirsiniz.
http://msdn.microsoft.com/library/en-us ... c_6cs3.asp
Pascal Newletter (Pascal Dergisi) sayı 25'e eşlik eden arşivin içinde bu makalenin tüm kaynak kodlarınıbulabilirsiniz.
Bişnev in ney çün hikâyet mîküned
Ez cüdâyîhâ şikâyet mîküned
Resim
Kullanıcı avatarı
futbolcu
Üye
Mesajlar: 129
Kayıt: 02 Tem 2003 08:33
Konum: Ankara

Mesaj gönderen futbolcu »

Teşekkürler bu makaleye ihtiyacım vardı. Eline emeğine yüreğine sağlık.
Bilgi çoğaldıkça krallar ölür
Kullanıcı avatarı
nitro
Üye
Mesajlar: 1112
Kayıt: 23 Ağu 2004 01:18
Konum: Çanakkale
İletişim:

Mesaj gönderen nitro »

cursorları exe içine gömmek için arama yapıyordum bu yazıya rastladım. ama
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ı).
kısmını anlamadım.
bilen birisi bu rc dosyaları falan oluşturma kısmını adım adım anlatırsa çok sevinirim.
saygılarımla
Kullanıcı avatarı
husonet
Admin
Mesajlar: 2962
Kayıt: 25 Haz 2003 02:14
Konum: İstanbul
İletişim:

Mesaj gönderen husonet »


Gazete manşetleri
* DİKKAT :Lütfen forum kurallarını okuyalım ve uyalım...!
* Warez,crack vs. paylaşımı kesinlikle yasaktır.
Kullanıcı avatarı
Trial_Cooder
Üye
Mesajlar: 236
Kayıt: 17 Nis 2006 04:44

Mesaj gönderen Trial_Cooder »

Kullanıcı avatarı
SHURZAN
Üye
Mesajlar: 73
Kayıt: 06 Eki 2007 05:34
Konum: İstanbul

Mesaj gönderen SHURZAN »

Ne zamandan beri BCB ve BDS C++ ile program yazmaktayım
Taktirinizdirki BCB ve BDS c++ için yeterince kaynak yok en azından Delphi kadar.
Son çalışmamda avi ve ico dosyalarını uygulamama gömmem gerekiyordu. res dosyası hazrlama konusunda olan bu makale her ne kadar eski bir tarihte yazılmış olsada eskimiyecek değerde.
Arkadaşın emeğenine sayıgı teşekkürler.
makale her ne kadar delphi için yazılmış olsada Cpp ile yazılmış uygulamaya uygulamak mümkün.
Kendi uygulamada kullandım.
Tekrar teşekkürler...
aXéNT

Re: Delphi'de Dosyaları EXE dosyanın içine gömmek (Embed etmek)

Mesaj gönderen aXéNT »

Ses dosyasını anlamadım ben kodlardada bi sorun var galiba. Ben alarm programı yapıyorum wav dosyasını anlattığınız gibi gömdüm ama nasıl çaldırıcamı anlamadım
aXéNT

Re: Delphi'de Dosyaları EXE dosyanın içine gömmek (Embed etmek)

Mesaj gönderen aXéNT »

Yine kendi sorumu kendim cevaplicam :D Yukardaki gibi gömme işlemini yaptıktan sonra aşağıdaki fonksiyonları tanımlayın;

Kod: Tümünü seç

function PlayWavFromResource(ResID: Integer): Boolean;
begin
Result := PlaySound(PChar('#' + IntToStr(ResID)), HInstance, SND_RESOURCE or SND_ASYNC);
end;

function PlayWavFile(const FileName: string): Boolean;
begin
Result := PlaySound(PChar(FileName), 0, SND_ASYNC);
end;

procedure StopWav;
var
buffer: array[0..2] of char;
begin
buffer[0] := #0;
PlaySound(Buffer, 0, SND_PURGE);
end;
Kullanımı

Kod: Tümünü seç

PlayWavFromResource(1) // 1 ses dosyasının adı gömülü ses dosyasını çalar

Kod: Tümünü seç

StopWav // Normalde durdurması lazım ama durdurmuyor :D
cdmesut
Üye
Mesajlar: 29
Kayıt: 16 Mar 2008 02:40

Re: Delphi'de Dosyaları EXE dosyanın içine gömmek (Embed etmek)

Mesaj gönderen cdmesut »

makale için teşekkürler. benim merak ettiğim bir avi dosaysını exeye enbet etmeyip ayrı bir dosyaya enbed edip mesele deneme.ghk isimli dosyaya enbet edip buradan çağırabilirmiyiz..
ben bir dosya için değilde birden fazla dosya için de bu mümkünmü..
teşekkürler.
Cevapla