본문 바로가기
Delphi, RadStudio

[개발/delphi] [강좌] 리소스의 활용 2

by SB리치퍼슨 2011. 12. 22.

[강좌] 리소스의 활용 II  

리소스의 활용 II

글: 하영재(vaio91@yahoo.com)
    델파이 코리아(www.delphikorea.com)

1편 강좌가 나간후 참 오랜만에 2편 강좌를 올리게 되는군여. 죄송합니다. 먹고살다
보니 이런일이.. 흑...

1편 강좌에서는 리소스를 어떻게 프로그램에 링크시키고 불러오고 하는지에 대해서
알아보았었죠... 이번엔 리소스 DLL을 만들고 사용하는 법에 대해 알아보겠습니다. 
이번 강좌에서는 AVI, Cur, Ico, Bmp, Jpeg, string을 Dll에 넣고 불러오는 방법에
대해 설명하겠습니다. 그리고 시간이 된다면 Resource의 활용법으로 실행파일을
리소스에 넣고 불러오는 방법에 대해서도 알아보도록 하겠습니다.
그럼 시작하죠...(지금 부터 존칭이 생략되는거... 다 아시죠? ^^)

1. 리소스 Dll 만들기

리소스 Dll이란 말 그대로 리소스를 포함하고 있는 Dll을 말한다. 만드는 순서를
먼저 알아보자. 

1. 리소스의 경로를 저장하고 있는 RC 파일을 만든다. 
2. RC 파일을 Brcc32등으로 컴파일 하여 Res 파일로 만든다. 
3. 만들어진 Res 파일을 Dll에 포함시킨다. (폼에 포함시키는것과 동일하다.)
4. Dll을 컴파일 한다. 

2번까지는 지난번 강좌의 내용과 같다. 3번 항목의 Res를 Dll에 포함 시키는 부분은
폼에 하는것과 동일하다고 했는데 아래의 예제를 보면 왜 동일하다는 건지 쉽게
이해가 될 것이다. 


library ResOnly;

{$R Resource.res}

begin
end.

아무런 함수등을 포함하지 않고 오직 리소스만 가지고 있는 Dll의 모습이다. 
Dll에 리소스를 포함시키기 위해서 폼에서 했던것과 마찬가지로 $R 지시자를
사용해서 Dll에 리소스를 포함 시키고 있다. 
일반 Dll과의 차이를 의심하는 분들이 계실지 모르지만... ^^ 동일한 Dll이다. 단지
리소스를 포함하고 있다는 것만이 다를뿐. 이 Dll에도 함수를 넣을 수 있다. 그리고
기존의 Dll에도 리소스를 포함시킬 수도 있다. 

그럼 실제로 예제로 사용할 Dll을 하나 만들어 보자. 


먼저 RC 파일을 만든다. 

[MyRes.RC]

MyBMP BITMAP Delphikorea.bmp
MyAVI AVI Cool.avi 
MyCur CURSOR HandPoint.cur
MyJPG JPEG Window.jpg

저장한 후 컴파일 한다. (리소스를 활용하자 1편 강좌 참고)
컴파일이 완료되면 MyRes.Res 란 리소스 파일이 생성되었을 것이다.
이 리소스 파일을 Dll에 포함시킨다.

[MyResource.dpr]

library MyResource;

{$R MyRes.res}

begin
end.

이 프로젝트 파일을 컴파일 하면 아무런 함수등이 포함되지 않은 순수 리소스 Dll이
완성된다. 물론 이 리소스 Dll엔 일반 Dll과 마찬가지고 함수를 가지고 있을 수도
있다. 단지 리소스 파일을 포함하고 있다는 것만 다를 뿐이다.
이제 남은일은 dll에 포함된 리소스를 하나 하나 꺼내 사용하는 일뿐이다.


2. 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;

여기서 MIDI의 연주는 MediaPlayer를 이용했다. 역쉬 설명 생략... ^^

[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);


보너스 끝... ^^



3. 마치며...

언제나 그렇듯이 좀 좋은 강좌를 쓸수 없을까 늘 고민을 하게 된다. 이번에도
아쉽지만 이쯤에서 마무리를 지을까 한다. 다음번에 여유가 된다면 Icon
Library에서 Icon을 읽고 또 원하는 Icon만 모아서 Icon Libarary를 만드는 방법에
대해 강좌를 해 볼까 한다. (물론 원하시는 분들이 계시다면...^^)
다음에 더 좋은 강좌로 찾아 뵐 것을 약속드리며 이만 줄이겠다. 



 
반응형

댓글