관리 메뉴

ㄴrㅎnㅂrㄹrㄱi

[강좌 13] 멀티미디어1 본문

API 관련/API 강좌모음

[강좌 13] 멀티미디어1

님투 2007. 10. 26. 03:41
반응형

[API]강좌(13)<--멀티미디어1



멀티미디어에 대해 알아 보도록 하겠습니다. 아마 여러분들도
상당히 흥미있는 부분이 될것입니다. 먼저 확장자가 wav인 파일을 어떻게 프로그램
상에서 플레이할수 있는지 부터 알아 봅시다. 확장자가 wav인 파일은 윈도우즈에서
쉽게 녹음기를 이용해서 만들수 있고 매체재생기를 이용해서 쉽게 듣을수도 있었을
겁니다. 이것을 프로그램상으로 구현하려면 쉬울것 같습니까? 윈도우즈 프로그래밍
에서는 보기보다 간단하게 이것을 구현할수 있습니다. 자 그러면 간단하게 한번
구현해 봅시다.
먼저 함수 하나를 알아 보죠. 이 함수 하나로 간단하게 wav파일을 들을수 있습니
다.
BOOL sndPlaySound(
LPCTSTR lpszSoundName,
UINT fuOptions
);
첫번째 파라미터는 wav파일을 지정해 주면 되고 두번째 파라미터는 디음과 같은
예약어를 지정해 주면 됩니다.
SND_SYNC 비동기적으로 플레이 해줍니다.
SND_ASYNC 동기적으로 플레이 해줍니다.
SND_LOOP 반복적으로 플레이 해줍니자.
아주 간단하죠? 위 함수 하나만 이용해서 쉽게 구현이 되는 것입니다. 그러면 실제
로 구현한 프로그램을 보도록 합시다. 아래 프로그램은 Enter키가 눌릴때마다 wav
파일을 반복적으로 플레이하고 플레이하지 않는 기능을 하고 있습니다.
#include <windows.h>
#include <string.h>
#include <mmsystem.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
static char szAppName[] = "Multimedia Example";
HWND hWnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW|CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
if(!RegisterClass(&WndClass))
return FALSE;
hWnd = CreateWindow(
szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL bCheck;
switch(message)
{
case WM_KEYDOWN :
if(LOWORD(wParam) == VK_RETURN)
{
if(!bCheck)
sndPlaySound("d:\\test.wav", SND_ASYNC|SND_LOOP);
else
sndPlaySound(NULL, 0);
bCheck = !bCheck;
}
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
자 그러면 프로그램 소스를 자세히 보도록 합시다. 먼저 헤더 파일을 보게되면
못보던 것이 있을 겁니다.
#include <mmsystem.h>
바로 위와 같이 선언되어 있는데 이 헤더 파일은 멀티미디어를 구현하기 위한
함수들이 정의되어 있습니다. 그러기 때문에 위 헤더 파일을 꼭 선언 해 주어야
합니다.
Enter키가 눌릴때마다 플레이되고 플레이되지 않는다고 했으니 그 부분을 보도
록 합시다.
case WM_KEYDOWN :
if(LOWORD(wParam) == VK_RETURN)
Enter키가 눌렸는지 확인하는 구문이죠? Enter키의 토글을 체크하기 위해서 아래
bCheck라는 변수를 사용한것입니다.
{
if(!bCheck)
sndPlaySound("d:\\test.wav", SND_ASYNC|SND_LOOP);
계속해서 wav파일을 연주하는 구문이 되겠네요. 만약에 위 두번째 파라미터 대신
에 SND_SYNC를 지정하고 사용했다면 어떤 일이 발생할까요? 이것은 비동기적이
므로 플레이가 다 될때까지 다음 루틴이 실행되지 않게 될겁니다. 차이점을 잘
알두시기 바랍니다.
else
sndPlaySound(NULL, 0);
첫번째 파라미터를 NULL로 지정하고 두번째 파라미터를 0으로 지정하면 연주가
중단됩니다.
bCheck = !bCheck;
}
return 0;
이 프로그램을 컴파일하려면 lib디랙토리내에 있는 winmm.lib 파일을 프로젝트
파일에 추가한뒤에 해주어야 합니다.
자 이번에는 다른방법을 사용해서 구현해 봅시다. 이 방법으로 구현하면 플레이
도중에 Pause시킬수도 있고 다시 Resume시킬수도 있습니다. 물론 중단 시키는
기능도 있습니다. 이 방법을 알아 보기 위해서는 먼저 MCI 디바이스에 대해 알
아야 합니다. MCI라는 것은 간단하게 말해서 어떤 인터페이스 카드를 컴퓨터가
인식하게끔 하는 디바이스입니다. 우리는 이 MCI 디바이스를 이용해서 각종
멀티미디어 파일을 플레이할텐데 이 MCI 디바이스에 대한것은 자신의 윈도우즈
디렉토리내의 system.ini 파일에 정의 되어 있습니다. 한번 찾아보세요.
[mci]
waveaudio=mciwave.drv
sequencer=mciseq.drv
cdaudio=mcicda.drv
avivideo=mciavi.drv
videodisc=mcipionr.drv
vcr=mcivisca.drv
필자같은 경우에는 위와 같이 되어 있군요. 어떤문자열이 특수한 드바이스 파일로
정의 되어 있죠. 우리는 이제 이 앞에 정의된 문자열을 이용해서 각 드라이버를
제어할것입니다. 확장자가 drv인 파일이 바로 디바이스 드라이브 파일입니다.
이제 부터 우리가 알아볼 함수로 장치 이름을 지정하여 그 핸들(아이디)을
얻어 각종 파일들을 플레이 할텐데 이 장치이름에 위에 정의된 waveaudio,
sequencer, cdaudio등을 지정하면 됩니다. waveaudio라는 것은 wav 파일을 의미하
고 sequencer는 midi 파일, cdaudio는 cd 오디오를 의미합니다.
자 그러면 구체적으로 어떤 함수를 이용해서 이러한 것들을 구현할수 있는지 알아
봅시다. 우리가 알아볼 것은 웨이브 파일에 대한 것이니 이 파일에 대해 먼저
알아 봅시다. 먼저 MCI 드바이스를 사용하기 위해서는 어떤 파일을 어떤 디바이스
드라이버로 열것인지 지정해 주어야 합니다. 그래서 성공적으로 열리면 이 파일에
대한 아이디를 얻을수 있는데 앞으로 이 아이디를 이용해서 플레이하거나 중지하거
나 할수 있습니다.
MCIERROR mciSendCommand(
MCIDEVICEID IDDevice,
UINT uMsg,
DWORD fdwCommand,
DWORD dwParam
);
앞으로 우리는 이 함수를 많이 사용할것입니다. 위 함수의 두번째 파라미터에 어떤
예약어를 지정함에 따라 파일을 열수도 있고 닫을수도 있으며 플레이할수도 있습니
다.
먼저 첫번째 파라미터에는 MCI 장치의 아이디를 지정하면 되는데 만약에 처음에 여
는과정이라면 장치 아이디가 없기 때문에 NULL을 지정하면 됩니다. 그리고 여는 과
정에서 얻어진 아이디를 이용해서 다른 작업을 할때에는 이 얻어진 아이디를 첫번
째 파라미터에 지정해 주면 됩니다.
두번째 파라미터에 지정해주는 예약어에 따라 어떤 작업을 할것인지 구분된다고
했는데 이 두번째 파라미터로 올수 있는 예약어는 다음과 같습니다.
MCI_OPEN MCI 장치를 엽니다.
MCI_CLOSE MCI 장치를 닫습니다.
MCI_PLAY 플레이합니다.
MCI_PAUSE 잠시 중단합니다.
MCI_RESUME 다시 재생합니다.
MCI_STOP 중단합니다.
세번째 파라미터는 두번째 파라미터에 어떤것이 지정되느냐에 따라 그 의미가
달라지므로 이 부분은 다시 아래에 가서 설명드리겠습니다. 그리고 마지막 파라미
터는 어떠한 정보로 구성되어 있는 구조체의 주소가 오는데 이 구조체도 두번째 파
라미터에 따라서 달라지니 이것도 아래 부분에서 다시 설명드리겠습니다.
다시 원래대로 돌아와서 MCI 장치를 어떻게 여는지 봅시다.
MCI 장치를 열때 위 함수의 첫번째 파라미터는 NULL을 지정하면 됩니다. 그리고
두번째 파라미터는 MCI_OPEN을 지정하면 되구요. 그리고 세번째 파라미터에는
MCI_OPEN_TYPE|MCI_OPEN_ELEMENT을 지정하면 됩니다. 여기서 MCI_OPEN_
TYPE이라는 것은 마지막 파라미터로 오는 구조체에 지정된 MCI 장치를 사용하겠
다는 것을 의미합니다. MCI_OPEN_ELEMENT는 마지막 파라미터로 오는 구조체
에 지정된 파일을 사용하겠다는 것을 의미합니다.
자 위의 설명을 잘 생각해 봅시다. 마지막 파라미터에 오는 구조체에 지정된 정보
를 사용하겠다는 의미죠? 그러면 이 부분에 오는 구조체는 어떤 구조체일까요?
typedef struct{
DWORD dwCallback;
MCIDEVICEID wDeviceID;
LPCTSTR lpstrDeviceType;
LPCTSTR lpstrElementName;
LPCTSTR lpstrAlias;
} MCI_OPEN_PARMS;
바로 위 구조체가 오게됩니다. 위 구조체 변수를 선언한 다음 파라미터중
lpstrDeviceType에 우리가 앞에서 알아본 웨이브 파일인 waveaudio을 지정해
주고 lpstrElementName에 플레이할 파일이름을 지정해 준후에 이 구조체를
mciSendCommand()함수의 마지막 파라미터에 지정해 주면 됩니다. 조금 복잡
한거 같지만 사실은 간단합니다. 이 함수가 성공적으로 수행되면 위 구조체 멤버
중 dwDeviceID에 이 장치의 아이디가 저장됩니다. 앞으로 이 아이디를 다른데서
이용할테니 어떤 변수에 저장해 주어야 겠네요.
MCI 장치를 여는 방법을 알았으니 닫는 방법도 알아 봅시다. MCI장치를 닫을 때
에는 mciSendCommand()함수의 첫번째 파라미터에 장치의 아이디를 지정하고
두번째 파라미터에 MCI_CLOSE를 지정하면 됩니다. 세번째 파라미터에는
MCL_WAIT를 지정하면 되고 마지막 파라미터에는 아래 구조체의 주소를 지정
하면 됩니다. 뭐 특별히 구조체 멤버에 어떤 값을 지정한후에 지정할 필요는 없
습니다.
typedef struct {
DWORD dwCallback;
} MCI_GENERIC_PARMS;
자 이번에는 플레이 하는 방법을 알아 봅시다. 역시 이것도 mciSendCommand()
함수를 이용하면 됩니다. 역시 첫번째 파라미터에 장치의 아이디를 지정하고 두번
째 파라미터에 MCI_PLAY를 지정하면 됩니다. 세번째 파라미터에는 MCI_NOTIFY
를 지정하는데 이것을 지정하게 되면 연주가 끝났을때 메인 윈도우에 MM_MCINOTIFY
라는 메시지를 전달해 줍니다. 마지막 파라미터에는 아래의 구조체 변수를 지정해
주어야 하는데 구조체의 멤버중 dwCallback에 윈도우의 핸들을 넣어준뒤
mciSendCommand() 함수에 넣어주어야 합니다.
typedef struct {
DWORD dwCallback;
DWORD dwFrom;
DWORD dwTo;
} MCI_PLAY_PARMS;
그러면 플레이되고 있는 것을 잠시 중단하려면 어떻게 할까요. 더 간단합니다.
mciSendCommand() 함수의 첫번째 파라미터에 장치 아이디를 지정하고 두번째 파
라미터에 MCI_PAUSE를 지정하면 됩니다. 세번째 파라미터에 MCI_WAIT를 지정하
고 마지막 파라미터에 앞에서 알아본 MCI_GENERIC_PARMS 구조체로 선언한 변
수의 주소를 지정하면 됩니다.
다시 플레이하려면 두번째 파라미터에 MCI_RESUME를 지정해서 사용하면 됩니다.
아예중단을 하려면 MCI_STOP을 지정해서 사용하면 되구요. 어때요? 좀 복잡해
보입니까? 알고 보면 그렇게 복잡하지도 않습니다. 물론 처음에 알아본 함수만을
이용해서 하는 방법보다는 복잡하죠.
다 그러면 실제로 이러한 함수를 가지고 구현한 프로그램을 보도록 합시다. 아차!
한가지 설명을 빠뜨렸군요. 그것은 플레이되는 위치를 지정하는 것인데 연주가
끝나면 플레이되는 지정을 처음으로 다시 옮길 필요가 있을 겁니다. 이때 다음과
같이 mciSendCommand()함수를 이용하면 됩니다.
먼저 첫번째 파라미터에 장치의 아이디를 지정하고 두번째 파라미터에 MCI_SEEK_TO
_START를 지정하면됩니다. 이 두번째 파라미터의 의미가 바로 처음으로 이동한다는
의미입니다.
그리고 마지막 파라미터에 아래와 같은 구조체 변수의 주소를 지정하면 되는데 특
별한 곳으로 이동하는 것이 아니기 때문에 초기에 어떤 값을 넣어서 지정할 필요는
없습니다. 만약에 특정한 곳으로 이동하려면 이 구조체의 맴버중 dwTo에 이동할곳
을 지정해 주면 됩니다.
typedef struct {
DWORD dwCallback;
DWORD dwTo;
} MCI_SEEK_PARMS;
 
프로그램을 분석해 보겠습니다. 그리고 플레이하는 또
다른 방법도 알아 보겠습니다.
먼저 앞에 만들어본 소스를 보도록 합시다.
case WM_CREATE :
dwID = Open(hWnd);
return 0;
윈도우가 생성되었을때에 Open()이라는 함수에 의해서 장치의 아이디를 얻는 과정
을 보여 주고 있습니다.
case MM_MCINOTIFY :
MoveStartPosition(hWnd, dwID);
return 0;
이 메시지는 언제 발생됩니까? MCI_PLAY라는 파라미터를 지정해서 사용한
mciSendCommand() 함수를 보면 세번째 파라미터를 MCI_NOTIFY라고 지정했을 겁니
다. 그렇죠? 이것에 의해서 연주가 끝나거나 중단되면 바로 위 메시지가 발생됩니
다. 플레이가 끝나면 플레이 시작 위치를 처음으로 옮기는 역할을 하는것이 위
MoveStartPosition()함수입니다.
case WM_COMMAND :
switch(LOWORD(wParam))
{
case 100 :
Play(hWnd, dwID);
break;
플레이를 하는 구문입니다.
case 200 :
Pause(hWnd, dwID);
break;
잠시 중단하게 하는 구문입니다.
case 300 :
Resume(hWnd, dwID);
break;
다시 플레이하는 구문입니다.
case 400 :
Stop(hWnd, dwID);
break;
플레이를 중단하는 구문입니다.
}
return 0;
case WM_DESTROY :
Close(hWnd, dwID);
PostQuitMessage(0);
return 0;

프로그램이 종료되면 MCI 장치를 닫는다는 것을 보여 주고 있습니다.
자 그러면 구체적으로 제가 만든 함수들을 보도록 합시다.
DWORD Open(HWND hWnd)
{
이 함수는 MCI 장치를 여는 역할을 하는 함수입니다.
MCI_OPEN_PARMS mciOpenParms;
장치를 열기 위해서는 위 구조체 변수가 필요하다고 이미 설명 드렸을 겁니다.
MCIERROR mciError;
장치가 제대로 열렸는지 확인하기 위해서 위 MCIERROR이라는 변수를 선언한 것
입니다.
mciOpenParms.lpstrDeviceType = "waveaudio";
확장자가 wav인 파일을 열기 위해서 디바이스 타입능 waveaudio라고 지정해준 것
입니다.
mciOpenParms.lpstrElementName = "d:\\test.wav";
플레이할 파일의 이름을 지정해 주고 있습니다.
mciError = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,
(DWORD)&mciOpenParms);
실제로 MCI 장치를 여는 과정을 보여 주고 있습니다. 특별한 부분은 없는것 같군
요.
if(mciError)
MessageBox(hWnd, "Open Error!!", "Error", MB_OK);
에러 체크하는 과정이 간단하죠?
return mciOpenParms.wDeviceID;
장치 아이디를 리턴하고 있습니다. 다른 함수에서 이 장치 아이디를 사용할것입니
다.
}
void Play(HWND hWnd, DWORD dwID)
{
이 함수는 플레이 하는 역할을 합니다.
MCI_PLAY_PARMS mciPlayParms;
플레이 하기 위해서는 위 구보체 변수가 필요하죠.
MCIERROR mciError;
역시 에러를 체크하기 위해서 선언한 것입니다.
mciPlayParms.dwCallback = (DWORD)hWnd;
구조체 멤버중 dwCallback에 윈도우의 핸들을 지정해 주고 있습니다.
mciError = mciSendCommand(dwID, MCI_PLAY, MCI_NOTIFY,
(DWORD)&mciPlayParms);
이 구조체를 이용해서 플레이하는과정을 보여주고 있습니다. 세번째 파라미터에
쓰인 MCI_NOTIFY에 의해서 플레이가 끝나면 윈도우에 MM_MCINOTIFY메시지를 보
내 줍니다.
if(mciError)
MessageBox(hWnd, "Play Error!!", "Error", MB_OK);
플레이가 안되면 에러 메시지를 출력하기 위한 구문입니다.
}
void Stop(HWND hWnd, DWORD dwID)
{
이 함수는 플레이를 중지하는 역할을 합니다. 이 함수에 의해서 플레이가 중지 되
도 윈도우에 MM_MCINOTIFY메시지를 보냅니다.
MCI_GENERIC_PARMS mciGenericParms;
중지하기 위해서 사용할 함수의 파라미터에 위 구조체 변수가 필요합니다.
MCIERROR mciError;
에러를 체크하기 위한 변수입니다.
mciError = mciSendCommand(dwID, MCI_STOP, MCI_WAIT,
(DWORD)&mciGenericParms);
중지를 하는 과정입니다. 세번째 파라미터에 MCI_WAIT가 지정된다는 것을 기억
하시기 바랍니다. 그냥 NULL로 지정해도 아마 같은 결과가 나올겁니다.
if(mciError)
MessageBox(hWnd, "Stop Error!!", "Error", MB_OK);
중지를 하는 과정에 에러가 있는지 판단하는 구문입니다.
}
void Pause(HWND hWnd, DWORD dwID)
{
이 함수는 연주중에 잠시 중단하는 역할을 하고 있습니다.
MCI_GENERIC_PARMS mciGenericParms;
MCIERROR mciError;
mciError = mciSendCommand(dwID, MCI_PAUSE, MCI_WAIT,
(DWORD)&mciGenericParms);
if(mciError)
MessageBox(hWnd, "Pause Error!!", "Error", MB_OK);
중지하는 구문과 그 쓰임이 크게 다르지는 않군요.
}
void Resume(HWND hWnd, DWORD dwID)
{
이 함수는 잠시 중지된 것을 다시 플레이하는 역할을 하고 있습니다. 물론 중지된
곳부터 다시 플레이됩니다.
MCI_GENERIC_PARMS mciGenericParms;
MCIERROR mciError;
mciError = mciSendCommand(dwID, MCI_RESUME, MCI_WAIT,
(DWORD)&mciGenericParms);
if(mciError)
MessageBox(hWnd, "Resume Error!!", "Error", MB_OK);
사용방법이 같죠?
}
void Close(HWND hWnd, DWORD dwID)
{
이 함수는 MCI 장치를 닫는 역할을 합니다.
MCI_GENERIC_PARMS mciGenericParms;
MCIERROR mciError;
mciError = mciSendCommand(dwID, MCI_CLOSE, MCI_WAIT,
(DWORD)&mciGenericParms);
if(mciError)
MessageBox(hWnd, "Resume Error!!", "Error", MB_OK);
역시 똑같군요.
}
void MoveStartPosition(HWND hWnd, DWORD dwID)
{
이 함수는 플레이 될 위치를 처음으로 옮기는 역할을 합니다.
MCI_SEEK_PARMS mciSeekParms;
위치를 바꾸기 위해서는 위 구조채 변수를 사용한다고 설명 드렸을 겁니다.
MCIERROR mciError;
mciError = mciSendCommand(dwID, MCI_SEEK, MCI_SEEK_TO_START,
(DWORD)&mciSeekParms);
두번째 파라미터의 MCI_SEEK가 위치를 옮기겠다는 의미이고 세번째 파라미터에 쓰
인 MCI_SEEK_TO_START가 처음 부분으로 옮긴다는 의미입니다.
if(mciError)
MessageBox(hWnd, "Set Length Format Error!!", "Error", MB_OK);
}
별로 크게 어려운 부분은 없죠? 그러면 확장자가 wav인 파일을 플레이하는 다른 방
법을 알아 봅시다. 참 방법이 다양하죠?
이 방법은 문자열을 이용해서 하는 방법인데 상당히 간단합니다. 역시 커다란 과정
은 같습니다. MCI 장치를 열고 플레이하고 나중에 닫고 뭐 그런 과정이죠.
우리는 앞에서 mciSendCommand()라는 함수를 이용해서 위의 모든 과정을 처리했는
데 이번에는 mciSendString()이라는 함수를 이용해서 위의 모든 과정을 처리할 것
입니다.
MCIERROR mciSendString(
LPCTSTR lpszCommand,
LPTSTR lpszReturnString,
UINT cchReturn,
HANDLE hwndCallback
);
첫번째 파라미터는 정의된 특별한 문자열을 지정해주면 되는데 이 부분에 어떻게
지정하느냐에 따라 MCI 장치를 열기도 하고 플레이하기도 합니다. 두번째 파라미
터는 이 함수를 사용하고 나서 리턴되는 문자열을 저장할 버퍼를 의미하고 세번째
파라미터는 버퍼의 크기 마지막 파라미터는 윈도우의 핸들을 지정하면 됩니다.
자 그러면 위 함수의 첫번째 파라미터에 어떤 문자열을 지정해서 어떤 작업을 하
는지 알아 봅시다.
먼저 MCI 장치를 여는 방법부터 봅시다. MCI 장치를 열기 이해서는 open이라는 문
자열을 이용해서 할수 있습니다. 물론 이 문자열만으로는 불가능하죠. MCI 장치가
어떤 형태이고 또 어떤 파일인지도 같이 지정해 주어야 할겁니다.
예를들어 볼까요?
open d:\\test.wav type waveaudio alias wavefile
open 다음에 오는 것이 바로 플레이할 파일 이름입니다. 그리고 파일 타입이 어떤
것인지 지정해 주어야 하는데 이때 type이라는 문자열 다음에 그 타입을 지정해 주
면 됩니다. 확장자가 wav이니 waveaudio라고 지정해 준것입니다. 앞에서 한 것과
같죠? 그 다음에 보면 alias라는 문자열이 있는데 이 문자열 다음에 오는 문자열이
우리가 앞에서 알아본 장치 아이디와 같은 역할을 합니다. 무슨 말인지 알겠습니
까? 위 예를보면 앞으로 우리는 wavefile이라는 문자열을 이 장치의 아이디로 사
용하겠다는 의미입니다.
반응형

'API 관련 > API 강좌모음' 카테고리의 다른 글

[강좌 15] 멀티미디어3  (0) 2007.10.26
[강좌 14] 멀티미디어2  (0) 2007.10.26
[강좌 12] 그래픽3  (0) 2007.10.26
[강좌 11] 그래픽2  (0) 2007.10.26
[강좌 10] 그래픽1  (0) 2007.10.26
Comments