델파이 리소스(Resource)
리소스 파일 생성
리소스 파일은 바이너리 형태의 데이터로서 RCDATA라 부른다.
리소스 파일은 Res라는 확장자를 가지게 되는데
이 Res 파일을 만들기 위한 과정을 살펴 보자
Res 파일을 만들기 위해서는 Text로 작성된 RC 파일이 있어야 한다.
이 RC 파일은 Res 파일에 포함하고자 하는 데이터 이름과 데이터 식별자,
그리고 데이터로 구성된 Text 파일이다.
RC 파일
WAVEFILE WAVE c:\WaveSound.wav 이렇게 작성된 것이 RC 파일이다.
여기서 'WAVEFILE'은 리소스를 호출할 때 쓰일 이름이며
'WAVE'는 이 리소스가 WAVE 파일임을 명시하는 것이며
맨 뒷부분은 실제로 리소스에 적재될 파일의 경로와 파일명으로 구성되어 진다.
이렇게 텍스트 에디터에서 작성을 한 후 '파일이름.RC'로 저장을 하면 된다.
여기까지 해서 RC 파일을 작성했으면
이제는 컴파일을 해서 RES 파일로 만드는 과정이 남아 있다.
리소스 파일을 만들기 위해 델파이에서는
BRCC(Boaland Resource Command Line Compiler)와 BRCC32를 제공한다.
이 녀석들은 RC 파일을 컴파일해서 RES 파일로 만들어 주는 역할을 한다.
이름 그대로 Command Line에서 사용하는 녀석들인데 사용방법은 매우 간단하다.
그저 'BRCC32 파일명.RC' 라고 커맨드 라인에서 입력하기만 하면 RES 파일을 만들어 준다.
이 두녀석은 델파이의 BIN 디렉토리에 존재하며
다른 경로에서 컴파일 하기위해서는 Path에 이 디렉토리를 추가하여 주어야 한다.
(path c:\progra~1\borland\delphi5\bin)
RC 파일의 컴파일
BRCC32 MyRes.RC 이렇게 해서 만들어진 Res 파일을 사용하려면
어떻게 해야 하는지 알아보자.
리소스 파일을 실행파일의 Res에 추가하려면
$R 지시자를 사용하여 추가한다.
{$R MyRes.RES}
아마 Unit에서 {$R *.DFM} 이렇게 작성된 부분을 보았을 것이다.
이것 또한 DFM 파일을 폼의 리소스에 추가하겠다는 코드이다.
이렇게 추가된 리소스는 한 프로젝트 내의 모든 유닛에서 사용이 가능하다.
위와 같이 하여 폼에 우리가 작성한 Res 파일을 추가한 후
컴파일을 하면 컴파일 전과 컴파일 후의 실행 파일의 크기가 변한 것을 알 수 있다.
실행 파일에 우리가 작성한 리소스 파일을 추가 했으니
추가된 리소스 만큼 폼의 크기가 늘어나는 것은 당연한 것이다.
마지막 부분에서 생각해 볼 것이지만 리소스 파일을 남발하는 것은
자칫 잘못하면 엄청난 크기의 실행 파일을 만들어 낼 수도 있다는 것을 주의해야 하며
이것은 메모리 낭비로 이어지는 것이다.
이렇게해서 실행 파일에 우리의 리소스를 추가했다면
우리는 이 리소스를 사용을 해야 한다.
리소스의 사용
우리가 추가한 리소스가 Wave 파일이므로 리소스에서
Wave 파일을 로드하여 연주하는 방법을 살펴보자.
Wave 파일을 연주하려면 PlaySound나 sndPlaySound 같은
API를 이용하여 연주하게 되는데 문제는
Wave가 파일로 존재하지 않는 것이라는 것이다.
리소스에 추가된 Wave를 연주하는데 PlaySoud와 sndPlaySound는
서로 비슷한 방법을 사용해서 연주하게 된다.
본론 부터 말하자면 두 함수 모두 Wave 리소스를 연주하는데는 별다른 차이가 없다.
즉 사용방법이 거의 동일하다는 얘기이다.
이 함수들을 사용하기 전에 MMSYSTEM을 Uses에 추가 해 주어야 한다.
PlaySound의 경우는 바로 리소스에서 Wave를 연주 할 수 있는데
바로 SND_RESOU RCE란 플랙을 이용하면 된다.
PlaySound('WAVEFILE', hInstance, SND_RESOURCE or SND_ASYNC);
여기서 WAVEFILE은 처음에 RC 파일을 만들때 맨 앞에 적어 주었던 리소스
이름이며 두번째 인자로 필요한 HModule에 현재 Instance를 주면 되며
마지막으로 SND_RESOURCE라는 플랙을 추가 함으로써
간단히 Wave리소스를 연주 할 수 있다.
sndPlaySound도 PlaySound와 별다른 차이가 없다.
sndPlaySound('WAVEFILE', SND_RESOURCE or SND_ASYNC);
설명을 따로 할 필요가 없을 정도로 비슷하다.
리소스에서 바로 연주하는 방법을 살펴 보았는데
다른 방법으론 TResourceStream을 이용해서 연주하는 방법이 있다.
이 때 사용하는 플랙은 SND_MEMORY란 플랙이며 sndPlaySound만을 예로 들어 보겠다.
TResourceStream을 이용한 연주
var
Soo: TResourceStream;
begin
Soo := TResourceStream.Create(hInstance, 'WAVEFILE', PChar('Wave'));
sndPlaySound(Soo.Memory, SND_MEMORY or SND_ASYNC);
Soo.Free;
end;
TResourceStream을 생성하는 부분을 살펴 보면 첫번째 인자로 인스탄스를 넘겨준다.
그리고 두 번째로 리소스 이름, 그리고 마지막으로 리소스 타입을 넘겨주면 된다.
이렇게 해서 얻어진 Wave를 sndPlaySound의 SND_MEMORY 플랙을
이용해서 연주 할 수 있는 것이다.
PlaySound도 거의 동일
실행파일에 추가
프로젝트안에 리소스를 포함시킴으로 인해 리소스를 불러오는 속도가 빠르고
exe 파일안에 포함되어 컴파일되므로 배포도 용이하다.
단. exe파일이 커지고 실행시 모든 리소스를 메모리에서 올려야 하기에
메모리 점유율이 높아지는 단점이 있다.
project - Resources and Images.. 선택 2
Add 클릭 후 이미지파일을 추가한다.
procedure TfmMain.ResourceIMG;
var
JPGImage : TJPEGImage;
RS : TResourceStream;
begin
imgBG.Align := alClient;
JPGImage := TJPEGImage.Create;
Try
RS := TResourceStream.Create(hinstance, 'Resource-name' , RT_RCDATA);
Try
JPGImage.LoadFromStream(RS);
imgBg.Picture.Graphic := JPGImage;
finally
RS.Free;
end;
finally
JPGImage.Free;
end;
end;
리소스 Dll 만들기
리소스 Dll이란 말 그대로 리소스를 포함하고 있는 Dll을 말한다.
1. 리소스의 경로를 저장하고 있는 RC 파일을 만든다.
2. RC 파일을 Brcc32등으로 컴파일 하여 Res 파일로 만든다.
3. 만들어진 Res 파일을 Dll에 포함시킨다.
(폼에 포함시키는것과 동일하다.)
4. Dll을 컴파일 한다.
library ResOnly;
{$R Resource.res}
begin
end.
아무런 함수등을 포함하지 않고 오직 리소스만 가지고 있는 Dll의 모습이다.
Dll에 리소스를 포함시키기 위해서 폼에서 했던것과
마찬가지로 $R 지시자를 사용해서 Dll에 리소스를 포함 시키고 있다.
동일한 Dll이다.
단지 리소스를 포함하고 있다는 것만이 다를뿐. 이 Dll에도 함수를 넣을 수 있다.
그리고 기존의 Dll에도 리소스를 포함시킬 수도 있다.
그럼 실제로 예제로 사용할 Dll을 하나 만들어 보자.
먼저 RC 파일을 만든다.
[MyRes.RC]
MyBMP BITMAP
Delphikorea.bmp
MyAVI AVI Cool.avi
MyCur CURSOR HandPoint.cur
MyJPG JPEG Window.jpg
저장한 후 컴파일 한다.
컴파일이 완료되면 MyRes.Res 란 리소스 파일이 생성되었을 것이다.
이 리소스 파일을 Dll에 포함시킨다.
[MyResource.dpr]
library MyResource;
{$R MyRes.res}
begin
end.
이 프로젝트 파일을 컴파일 하면 아무런 함수등이 포함되지 않은
순수 리소스 Dll이 완성된다.
물론 이 리소스 Dll엔 일반 Dll과 마찬가지고 함수를 가지고 있을 수도 있다.
단지 리소스 파일을 포함하고 있다는 것만 다를 뿐이다.
이제 남은일은 dll에 포함된 리소스를 하나 하나 꺼내 사용하는 일뿐이다.
Dll내의 리소스 사용
2-1) AVI 리소스의 사용
Dll 내의 AVI 리소스를 사용하기 위해서는 먼저 리소스 Dll을 로드하여야 한다.
우리는 간단히 LoadLibrary API를 이용해서 Dll을 로드 할 수 있다.
var
DllHandle: THandle; ...
DllHandle := LoadLibrary('MyResource.dll');
이렇게 해서 얻어진 Dll의 Instance Handle은 앞으로 두고 두고
사용할 것이므로 잘 챙겨 두도록 하자. ^^
로드된 Dll을 이용해서 AVI 리소스를 뽑아내는 것은 정말 정말 간단하다.
TAnimate 객체를 사용하여 플레이 할것이기 때문이다.
우리는 TAnimate 객체의 ResName과 ResHandle 프러퍼티만을
셋팅해 줌으로써 바로 플레이가 가능하다.
먼저 ResHandle을 채워준다.
Animate1.ResHandle := DllHandle;
다음으로 ResName을 준다.
Animate1.ResName := 'MyAVI'; //우리가 저장한 AVI의 이름이다.
마지막으로 플레이...
Animate1.Play(1, Animate1.FrameCount, 0);
2-2) JPEG 리소스의 사용
JPEG는 Resource Type으로 등록되지 않은 녀석이다.
별도로 등록되지 않은 리소스 형식은 RT_RCDATA 형식으로 봐도 무방하다.
바이너리로 저장되었으므로 JPEG 리소스를 로드하기 위해선
TResourceStream이란 메모리 스트림 계열의 스트림을 이용해서
리소스 Dll로 부터 메모리로 JPEG 데이터를 옮겨 올 수 있다.
var
ResStream: TResourceStream; ...
ResStream := TResourceStream.Create(DllHandle, 'MyJPEG', 'JPEG');
여기까지 작업하면 ResStream에 JPEG 파일이 들어온다.
이것을 담을 JPEG 형식의 객체가 필요하므로 하나 생성하자.
(JPEG Unit을 포함시켜야 한다.)
uses JPEG;
var
JPEG: TJPEGImage; ...
JPEG := TJPEGImage.Create;
JPEG Image를 생성했으면 위에서 로드한 ResStream을 받아온다.
JPEG.LoadFromStream(ResStream);
마지막으로 Image에 JPEG를 넣어준다.
Image1.Picture.Bitmap.Assign(JPEG);
위에서 동적 생성한 객체들을 해제해 준다.
JPEG.Free; ResStream.Free;
2-3) Cursor 리소스의 사용
Custom Cursor를 사용하기 위해선 먼저 Screen의 Cusors에 리소스를 로드해 줘야 한다.
단, 우리가 사용할 커서의 액세를 위해 유니크한 커서 상수를 하나 미리 선언해 주자.
const
crMyCursor = 10;
이 값은 0보다 큰 값이면 어느 값이나 사용해도 무방하다.
단... ^^ 미리 윈도우에 등록된 Cursor 상수값과는 달라야 한다.
커서를 로드하는데는 LoadCursor란 API를 이용한다.
Screen.Cursors[crMyCursor] := LoadCursor(DllHandle, 'MyCur');
로드가 되었으므로 사용하고저 할 때 이 커서를 불러주면 된다.
Screen.Cursor := crMyCursor;
2-4) Bitmap 리소스의 사용
Bitmap 리소스는 리소스 중에서 사용하기가 가장 쉽다. ^^
이미 델파이에선 TBitmap에 리소스를 사용하기 위한 모든 준비를 마쳐 놨기 때문이다.
그렇지 않았다면 우리는 일일이 많은 작업을 손수 했어야 할 것이다.
우리는 리소스의 비트맵을 로드하기 위해 단지
LoadFromResourceName이란 메소드만 호출해 주면 된다.
Image2.Picture.Bitmap.LoadFromResourceName(DllHandle, 'MyBMP');
내부적으로 어떻게 처리되는지 알고 싶은 사람은
Graphics.pas에 정의된 LoadFromResourceName 메소드를 분석해 보자
이것으로 할 얘긴 거의 다 한것 같다.
한 가지 빠진것이 있다면 Icon 파일에 대한 것인데
이것또한 별로 설명할 것이 없으므로 직접 한 번 해 보시길... ^^
마지막 단계로 로드한 Dll을 해제 할 차례이다.
FreeLibrary(DllHandle);
폼의 종료에 넣어 두면 될 것이다.
앞에서도 얘기 했듯이 Exe 파일도 리소스에 포함시켜서 사용할 수 있다.
눈치채신 분도 있으시겠지만 별 특별한건 없다.
그저 TResourceStream을 이용하는 것이다.
그 외에 MIDI 파일도 넣어보고 String 데이터도 한 번 넣어 보자.
[MyExeRc.rc]
MyNotePad EXEFILE
c:\windows\NotePad.exe
MyMIDI MIDI xi_shui_chang_liu.mid
STRINGTABLE {
1, "하영재 바보! 윽... 앞으론 이런 예문은 만들지 않으렵니다."
2, "델파이 코리아 만세!!! (www.delphikorea.com)"
}
위 에서 설명한대로 컴파일 후 Dll에 포함시켜서 다시 컴파일 한다.
그럼 Dll이 만들어 질 것이다. 여기서 Dll이름은 MyExeDll.dll로 했다.
먼저 dll을 로드 한다.
var
DllHandle: THandle; ...
DllHandle := LoadLibrary('MyExeDll.dll'); ...
[Exe 파일 저장하고 실행하기]
var
ExeRes: TResourceStream;
begin
if DllHandle = 0 then Exit;
ExeRes := TResourceStream.Create(DllHandle, 'MyNotePad', 'EXEFILE');
ExeRes.SaveToFile('Note.exe');
WinExec(PChar('Note.exe'), SW_SHOW);
ExeRes.Free;
end;
[MIDI 파일 저장하고 연주하기]
var
MidiRes: TResourceStream;
begin
if DllHandle = 0 then Exit;
MidiRes := TResourceStream.Create(DllHandle, 'MyMIDI', 'MIDI');
MidiRes.SaveToFile('MyMIDI.Mid');
MediaPlayer1.FileName := 'MyMidi.mid';
MediaPlayer1.Open; MediaPlayer1.Play;
MidiRes.Free;
end;
[String Resource 사용하기]
리소스내의 String을 읽어오기 위해 LoadString 함수를 이용한다.
var
FText : pchar;
begin
if DllHandle = 0 then Exit;
GetMem(FText, 1025);
LoadString(DllHandle, 1, FText, 1024);
ShowMessage(string(FText));
FreeMem(FText);
end;
마찬가지로 사용한 Library를 해제해 준다.
FreeLibrary(DllHandle);
'Delphi Tip > 파일' 카테고리의 다른 글
델파이 리소스(Resource)의 활용 2 (0) | 2023.10.18 |
---|---|
델파이 리소스(Resource)의 활용 1 (0) | 2023.10.13 |
프로그램간의 메모리공유 (0) | 2023.07.05 |
DLL만들기와 사용방법 (0) | 2023.06.28 |
DLL(Dynamic-link library)란 (5) (0) | 2023.06.27 |
댓글