2.Avi 출력하기

AVI 파일은 MS-WINDOWS용 기본 비디오 파일입니다. 매체 재생기를 이용하여 확장자가 avi인 avi 파일을 직접 출력해 본 경우가 있을 것입니다. 이번 장에서는 이런 avi 파일을 MFC프로그램 안에서 출력할 수 있도록 해보겠습니다.

대상:중급,고급

구분: 선택

공부방법: Avi 출력이 필요할때 예제를 작성해보시거나 CMyVideo 클래스를 분석해 보세요.

1.MCI를 이용한 AVI 출력 방법

윈도의 win.ini에 보면 다음과 같은 항목이 있을 것입니다.

[mci]

waveaudio=mciwave.drv

sequencer=mciseq.drv

cdaudio=mcicda.drv

CDIVideo=XMDRIVER.DRV// cdi 비디오

avivideo=mciavi.drv  // avi형

videodisc=mcipionr.drv //dickvideo

Animation1=MCIAAP.DRV //fil,flc형

MpegVideo=XMDRIVER.DRV //mpeg형

[mci]라는 항목 밑에 물론 각자의 컴퓨터에 설치되어 있는 비디오 드라이버는 여러 가지일 것입니다. 상기에 기록한 화면과는 다를 수도 있죠. 그러나 avivideo=mciavi.drv라는 항목은 같을 것입니다.

컴퓨터에서 멀티미디어는 크게 2가지로 나눌 수가 있습니다. 사운드와 동영상, 이중 동영상은 비디오 디스크와 CDIVIDEO, MPEGVIDEO 등이 있습니다.

디스크 자체가 동영상인 항목은 여기서 다루지 않으나 mci를 이용한다면 크게 다를 것이 없습니다. mci에 설치된 동영상과 오디오 사운드의 사용법은 본서의 멀티미디어 프로그래밍을 해본 다음 응용하시면 됩니다.

파일로 설치된 동영상을 여기에서는 avi에 국한시키지 않았습니다. 만일 fli나 flc 또는 mpeg 등의 mci 드라이버가 설치되었다면 fil, flc, Mpeg 파일 또한 Avi 출력과 같은 방법을 이용하시면 됩니다.

<1>파일 열기

파일을 개방할 경우 MCI의 여러 파라미터 중 MCI_DGV_OPEN_PARMS 구조체를 사용합니다.

MCI_DGV_OPEN_PARMS mciOpenParms;

MCI_DGV_OPEN_PARMS의 맴버인 lpstrDeviceType에 무엇을 설정하느냐에 따라 AVI, FLI, FLC MPEG 등이 결정됩니다. 물론 현재 컴퓨터에 위의 드라이버가 설치되었다고 가정하고 말입니다.

① mciOpenParms.lpstrDeviceType = "AVIVideo"; //AVI용 파일

② mciOpenParms.lpstrDeviceType = "Animation1"; //FLI,FLC용 파일

③ mciOpenParms.lpstrDeviceType = "MpegViedeo"; //Mpeg 용 파일

①은 avi 파일을 설정할 때 사용하고 ②는 fli나 flc 파일을 출력할 때 사용합니다. fli나 flc는 3D STUDIO 프로그램을 이용하여 제작한 애니메이션 파일을 말합니다. ③은 MPEG 파일을 출력할 때 사용합니다 . 파일명을 설정할 때는 MCI_DGV_OPEN_PARMS의 멤버인  lpstrElementName에 파일명을 설정하면 됩니다.

mciOpenParms.lpstrElementName = "test.avi";

이제 mciSendCommand 명령문을 이용하여 파일을 개방합니다.

mciSendCommand(0,

MCI_OPEN,

MCI_OPEN_ELEMENT | MCI_OPEN_TYPE | MCI_DGV_OPEN_WS,

(DWORD)(LPVOID) &mciOpenParms);

위와 같이 실행하면 MCI_DGV_OPEN_PARMS로 설정된 mciOpenParms의 부함수 wDeviceID가 현재 MCI의 ID 번호를 넘겨줍니다. wDeviceID가 바로 핸들러 번호입니다.. 앞으로 mciSendCommand 함수를 사용할 때는 본 wDeviceID를 계속적으로 사용합니다.

이와 같이 함으로써 파일을 열기는 했지만 avi란 화면에 동영상이 출력되기 때문에 화면에 출력될 좌표를 설정해 주어야 합니다. 즉 화면의 x1, x2, y1, y2를 설정해 줍니다. 이 때 사용하는 파라미터가 MCI_DGV_RECT_PARMS입니다.

MCI_DGV_RECT_PARMS mciRect;

mctRect 안에 x1, y1, x2, y2를 설정하는 방법은 다음과 같습니다.

mciRect.rc.top = 0;

mciRect.rc.left= 0;

mciRect.rc.right=300;

mciRect.rc.bottom =240;

다음 MCI_DGV_OPEN_PARMS로 설정된 mciOpenParms의 부함수 wDeviceID를 받습니다.

UINT wDeviceID;

wDeviceID = mciOpenParms.wDeviceID;

이제 화면에 출력할 좌표를 mciSendCommand를 이용하여 설정합니다.

mciSendCommand(wDeviceID,MCI_PUT,MCI_ANIM_PUT_DESTINATION | MCI_DGV_RECT,

(DWORD) (LPVOID) &mciRect);

출력할 좌표는 정해 주었는데 어느 윈도에 출력할 것인가가 또 하나의 문제이지요. 즉 avi를 출력할 윈도를 설정해 주어야 합니다. 이 윈도 설정은 HWND를 이용합니다.

예를 든다면 CTextView라는 뷰 프레임에 avi를 출력할 경우 뷰 프레임의 m_hWnd를 설정해 주어서 CTextView에 avi를 출력시키게 하는 것입니다.

윈도를 설정하는 파라미터는 MCI_DGV_WINDOW_PARMS입니다.

MCI_DGV_WINDOW_PARMS mciWindow;

MCI_DGV_WINDOW_PARMS의 멤버인  hWnd에 m_hWnd를 설정시켜 준다.

mciWindow.hWnd = m_hWnd;

이제 mciSendCommand를 이용하여 윈도를 설정해야겠지요.

mciSendCommand(wDeviceID,MCI_WINDOW,MCI_ANIM_WINDOW_HWND,

(DWORD)(LPVOID) &mciWindow);

이와 같이 함으로써 동영상 파일을 출력하는 모든 준비가 완료되었습니다.

<2>동영상 출력하기

이제 설정된 동영상을 출력하겠습니다. 출력할 때 사용하는 파라미터는 MCI_PLAY_PARMS입니다.

MCI_PLAY_PARMS mciPlayParms;

위와 같이 설정한 다음 mciSendCommand를 이용하여 동영상을 출력합니다.

mciSendCommand(wDeviceID,MCI_PLAY,MCI_NOTIFY,

(DWORD)(LPVOID) &mciPlayParms);

위와 같이 하면 동영상이 출력됩니다. 요즘 좋은 VGA 카드가 나와서 트루 칼라를 많이 사용합니다. 그런데 256칼라를 사용할 때는 위와 같이 영상을 출력시키면 다른 비트맵과 문제가 생깁니다. 팔레트 때문입니다. 예를 들어, 어떤 비트맵 이미지를 화면에 출력한 다음 그 위에 동영상을 출력한다고 했을 경우 이미지의 팔레트와 동영상의 팔레트가 다를 때는 이미지의 색이 변하든지 동영상의 색이 변하게 되어 있습니다. 이럴 때는 동영상과 이미지의 팔레트를 재활성화해 주어야 합니다. 팔레트를 활성화해 주는 방법은 다음과 같습니다.

mciSendCommand(wDeviceID,MCI_REALIZE,MCI_ANIM_REALIZE_NORM,NULL);

<3>화면 이동하기

avi 동영상이 출력되면서 화면을 이동시키는 방법은 자주 사용되지 않으나 많이 사용할 경우가 있다면 위의 파일을 열 때 사용한 MCI_PUT 명령어를 그대로 사용합니다.

//좌표를 바꾸어 준다.

mciRect.rc.top = x;

mciRect.rc.left= y;

mciRect.rc.right=cx;

mciRect.rc.bottom = cy;

mciSendCommand(wDeviceID,MCI_PUT,MCI_ANIM_PUT_DESTINATION | MCI_DGV_RECT,

(DWORD) (LPVOID) &mciRect);

<4>처음으로 이동하기

영상이 출력되는 중에 동영상의 맨 처음으로 이동하고 싶을 경우가 있죠. 이 때는 다음과 같이 합니다.

mciSendCommand (wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, (DWORD) (LPVOID) NULL);

<5>끝으로 이동하기

다음은 끝으로 이동할 때 사용하는 방법입니다.

mciSendCommand (wDeviceID, MCI_SEEK, MCI_SEEK_TO_END, (DWORD) (LPVOID) NULL);

다음 프레임으로 이동

다음 프레임으로 이동할 때는 MCI_STEP 명령문을 사용합니다. 이 때 사용하는 파라미터는 MCI_DGV_STEP_PARMS입니다.

MCI_DGV_STEP_PARMS StepParms;

MCI_DGV_STEP_PARMS의 멤버인  dwFrames에 넘어가고자 하는 프레임수를 설정합니다.

StepParms.dwFrames = 5;//5 프레임 다음으로 이전한다.

위와 같이 설정한 후 mciSendCommand를 실행시킵니다.

mciSendCommand (wDeviceID, MCI_STEP, MCI_DGV_STEP_FRAMES, (DWORD) (LPVOID) &

StepParms);

<6>이전 프레임으로 이동

이전 프레임 이동은 다음 프레임 이동과는 차이가 있습니다. 즉 MCI_STEP이 아닌  MCI_SEEK를 이용합니다. 이 방법은 현재 프레임을 얻은 다음 그 프레임에서 이전으로 이동할 프레임을 설정한 다음 MCI_SEEK를 사용하여 이동하는 것입니다.

MCI_STATUS_PARMS StatusParms;//상태 정보를 얻는 파라미터

// 현재의 포지션을 얻는다.

StatusParms.dwItem = MCI_STATUS_POSITION;

mciSendCommand (wDeviceID, MCI_STATUS, MCI_STATUS_ITEM,

(DWORD) (LPVOID) &StatusParms);

long Position;

Position = StatusParms.dwReturn; //현재 포지션을 얻는다.

MCI_SEEK_PARMS mciSeekParms;

mciSeekParms.dwTo = Position-point; //현재 포지션에서 이전으로 갈 프레임

//만큼 빼준 다음 프레임을 찾아간다.

mciSendCommand(wDeviceID,MCI_SEEK,MCI_TO|MCI_WAIT,

(DWORD)(LPVOID) &mciSeekParms);

<7>일시 정지

일시 정지는 매우 간단합니다. MCI_PAUSE 명령어를 사용하여 다음과 같이 합니다.

mciSendCommand(wDeviceID,MCI_PAUSE,MCI_NOTIFY,

(DWORD)(LPVOID) &mciPlayParms);

<8>MCI 종료

모든 것을 종료할 때에는 다음과 같이 사용합니다.

//mci를 닫는다.

mciSendCommand(wDeviceID,MCI_CLOSE,0,NULL);

동영상에 좀 특이한 점이 있다면 현재 동영상이 재생되고 있을 경우에는 종료되지 않는다는 것입니다.

그렇기 때문에 만약 재생되고 있다면 종료 전에 MCI_PAUSE를 실행시켜야 합니다. 만약 재생 도중에 종료를 시킨다면 윈도에서는 AVI 파일이 계속 출력될 것입니다.

여기서 제작할 예제 ExAvi에서 한번 재생 도중에 mci를 종료해 보세요. 아마 이상한 곳에서 동영상이 계속적으로 출력될 것입니다.

2. MCI를 이용한 동영상 출력 클래스 만들기

이제 위의 내용을 토대로 동영상 출력 클래스를 만들어 보겠습니다. 여기서 만드는 동영상 출력 클래스의 이름은 CMyVideo입니다. 본 클래스는 avi 동영상을 로드한 후 화면에 재생하고 이전으로, 다음으로, 멈춤, 종료, 특정 위치로 이동 등의 함수가 있습니다.

(프로그램 소스)

//myvid.h

//avi화일 출력 클래스 헤더

#if !defined(AFX_MCIVIDEO_H__C5B8D34E_554E_11D2_A595_00403320A530__INCLUDED_)

#define AFX_MCIVIDEO_H__C5B8D34E_554E_11D2_A595_00403320A530__INCLUDED_

#include <digitalv.h>

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

class CMyVideo

{

public:

DWORD GetCurPosition();

DWORD GetTotalLength();

BOOL Close();

BOOL Open(CRect rect,HWND hwnd);

CMyVideo       (int ,int,int,int,LPSTR lpszFileName,HWND hwnd);

CMyVideo();

~CMyVideo      ();

void MoveWindow(int x,int y,int cx,int cy);//윈도우를 이동

void MoveCursor(DWORD posion,HWND hWnd);//프레임 을 이동

void Pause();//멈춤

BOOL Play();//play

BOOL FramePrev (long point);//이전 프레임으로

BOOL Rewind (void);//처음으로

BOOL Foward (void); //끝으로

BOOL FrameNext (long point); //다음으로

protected:

CString m_strFileName;

UINT wDeviceID;

MCI_DGV_OPEN_PARMS mciOpenParms;

MCI_PLAY_PARMS mciPlayParms;

MCI_DGV_WINDOW_PARMS mciWindow;

MCI_DGV_RECT_PARMS mciRect;

};

#endif // !defined(AFX_MCIVIDEO_H__C5B8D34E_554E_11D2_A595_00403320A530__INCLUDED_)

//myvid.cpp

// avi출력 클래스 소스

#include "stdafx.h"

#include "myvid.h"

CMyVideo::CMyVideo(int x,int y,int cx,int cy,LPSTR filename,HWND wnd)

{

m_strFileName=filename;

Open(CRect(x,y,cx,cy),wnd);

}

CMyVideo::CMyVideo()

{

m_strFileName="";

}

BOOL CMyVideo::Open(CRect rect, HWND hwnd)

{

mciWindow.hWnd = hwnd ;

mciOpenParms.lpstrDeviceType = "AVIVideo";

mciOpenParms.lpstrElementName = (LPSTR)(LPCSTR)m_strFileName;

//avi 형태의 화일로 mci를 오픈한다.

mciSendCommand(0,

MCI_OPEN,

MCI_OPEN_ELEMENT | MCI_OPEN_TYPE | MCI_DGV_OPEN_WS,

(DWORD)(LPVOID) &mciOpenParms);

//open 된 mci를 받는다.

wDeviceID = mciOpenParms.wDeviceID;

mciRect.rc.top = rect.top;

mciRect.rc.left= rect.left;

mciRect.rc.right=rect.right;

mciRect.rc.bottom =rect.bottom;

//위치를 설정한다.

mciSendCommand(wDeviceID,MCI_PUT,MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,

(DWORD) (LPVOID) &mciRect);

mciSendCommand(wDeviceID,MCI_WINDOW,MCI_DGV_WINDOW_HWND,

(DWORD)(LPVOID) &mciWindow);

return TRUE;

}

CMyVideo::~CMyVideo()

{

//mci 를 닫는다.

if(m_strFileName!="")

mciSendCommand(wDeviceID,MCI_CLOSE,0,NULL);

}

BOOL CMyVideo::Play()

{

//화면을 플레이 한다.

mciSendCommand(wDeviceID,MCI_PLAY,MCI_NOTIFY,

(DWORD)(LPVOID) &mciPlayParms);

//avi이기 때문에 팔레트를 다시 활성화 시켜준다.

mciSendCommand(wDeviceID,MCI_REALIZE,MCI_DGV_REALIZE_NORM,NULL);

return TRUE;

}

void CMyVideo::MoveWindow(int x,int y,int cx,int cy)

{

mciRect.rc.top = x;

mciRect.rc.left= y;

mciRect.rc.right=cx;

mciRect.rc.bottom = cy;

//윈도우의 위치를 바꾼다.

mciSendCommand(wDeviceID,MCI_PUT,MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,

(DWORD) (LPVOID) &mciRect);

}

void CMyVideo::MoveCursor(DWORD Position,HWND hWnd)

{

mciPlayParms.dwCallback =(DWORD)(LPVOID)hWnd;

mciPlayParms.dwFrom = Position;

//Avi의 위치를 바꾸어 준다.

mciSendCommand(wDeviceID,MCI_SEEK,MCI_SEEK_TO_START,

(DWORD)(LPVOID) &mciPlayParms);

}

void CMyVideo::Pause()

{

//일시 정지

mciSendCommand(wDeviceID,MCI_PAUSE,MCI_NOTIFY,

(DWORD)(LPVOID) &mciPlayParms);

}

BOOL CMyVideo::Rewind (void)

{

//처음으로 간다.

mciSendCommand (wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, (DWORD) (LPVOID) NULL);

return TRUE;

}

BOOL CMyVideo::Foward (void)

{

//나중으로 간다.

mciSendCommand (wDeviceID, MCI_SEEK, MCI_SEEK_TO_END, (DWORD) (LPVOID) NULL);

return TRUE;

}

//point로 정의된 만큼 포인터 이전

BOOL CMyVideo::FrameNext (long point)

{

DWORD RetCode;

MCI_DGV_STEP_PARMS StepParms;

MCI_STATUS_PARMS StatusParms;

DWORD Length, Position;

//전체위치를 받는다.

StatusParms.dwItem = MCI_STATUS_LENGTH;

if (RetCode = mciSendCommand (wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD) (LPVOID) &StatusParms)){

return FALSE;

}

Length = StatusParms.dwReturn;

// 현재의 위치를 알라낸다.

StatusParms.dwItem = MCI_STATUS_POSITION;

if (RetCode = mciSendCommand (wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD) (LPVOID) &StatusParms)){

return FALSE;

}

Position = StatusParms.dwReturn;

// 현재위위치가 화일 끝이면

if (Length == Position)

return TRUE;

// point 프레임 만큼 동한다.

StepParms.dwFrames = point;

if (RetCode = mciSendCommand (wDeviceID, MCI_STEP, MCI_DGV_STEP_FRAMES, (DWORD) (LPVOID) &StepParms)){

return FALSE;

}

return TRUE;

}

//point 프레임 만큼 이전으로 간다.

BOOL CMyVideo::FramePrev (long point)

{

DWORD RetCode;

MCI_STATUS_PARMS StatusParms;

DWORD Length, Position;

//전체 프레임을 얻는다.

StatusParms.dwItem = MCI_STATUS_LENGTH;

if (RetCode = mciSendCommand (wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD) (LPVOID) &StatusParms)){

return FALSE;

}

Length = StatusParms.dwReturn;

// 현재의 포지션을 얻는다.

StatusParms.dwItem = MCI_STATUS_POSITION;

if (RetCode = mciSendCommand (wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD) (LPVOID) &StatusParms)){

return FALSE;

}

Position = StatusParms.dwReturn;

// 현재의 포지션이 0이면 처음이므로 리턴

if (Position == 0)

return TRUE;

MCI_SEEK_PARMS mciSeekParms;

mciSeekParms.dwTo = Position-point;

//point 프레임 만큼 이전으로 이동한다.

mciSendCommand(wDeviceID,MCI_SEEK,MCI_TO|MCI_WAIT,

(DWORD)(LPVOID) &mciSeekParms);

return TRUE;

}

BOOL CMyVideo::Close()

{

if(m_strFileName!="")

mciSendCommand(wDeviceID,MCI_CLOSE,0,NULL);

return TRUE;

}

DWORD CMyVideo::GetTotalLength()

{

DWORD RetCode;

MCI_STATUS_PARMS StatusParms;

DWORD Length;

//전체 프레임을 얻는다.

StatusParms.dwItem = MCI_STATUS_LENGTH;

if (RetCode = mciSendCommand (wDeviceID, MCI_STATUS, MCI_STATUS_ITEM,

(DWORD) (LPVOID) &StatusParms)){

return FALSE;

}

Length = StatusParms.dwReturn;

return Length;

}

DWORD CMyVideo::GetCurPosition()

{

DWORD RetCode;

MCI_STATUS_PARMS StatusParms;

DWORD Position;

// 현재의 포지션을 얻는다.

StatusParms.dwItem = MCI_STATUS_POSITION;

if (RetCode = mciSendCommand (wDeviceID, MCI_STATUS, MCI_STATUS_ITEM,

(DWORD) (LPVOID) &StatusParms)){

return FALSE;

}

Position = StatusParms.dwReturn;

return Position;

}

(프로그램 소스끝)

3. AVI 출력 예제 ExAvi 프로그램

이제 위에서 만든 CMyVideo클래스를 이용하여 Avi를 출력하는 프로그램을 제작해 보겠습니다. 본 프로그램은 ExAvi입니다. 그림 7-2-1이 본 프로그램을 실행한 모습입니다. 프로그램의 뷰 화면에서 마우스 좌측 버튼을 클릭하면 현 디렉토리에 있는 seminar.avi 파일을 출력합니다. 메뉴의 AVI VIDEO에서 비디오 보기를 선택하면 그림 1과 같은 대화상자가 뜨고 FILE을 선택하여 Avi 파일을 열고 Play 버튼을 누르면 화면에 동영상이 나타납니다. 본 대화상자는 처음으로, 끝으로, 이전 프레임에서, 다음 프레임으로 멈추기 기능을 가지고 있습니다.

(그림 7-2-1)Exavi 실행결과

<1>Avi 파일 로드

Avi 파일을 로드하려면 위의 CMyVideo 클래스를 이용하여 다음과 같이 하면 됩니다.

CMyVideo *m_pVideo;

m_pVideo = new CMyVideo(0,0,300,240,"test.avi",this->m_hWnd);

앞의 4개의 정수 인자는 x1, y1과 가로의 길이, 세로의 길이를 설정하는 것이고 그 다음은 파일명이며 그 다음은 hwnd입니다.

<2>Avi 파일 Play

위에서 설정한 함수의 맴버 함수 Play()를 실행시킵니다.

m_pVideo->Play();

<3>Avi 파일 멈춤

Pause 함수를 실행시킵니다.

m_pVideo->Pause();

<4>Avi 파일 처음으로

m_pVideo->Rewind();

<5>Avi 파일 마지막으로

m_pVideo->Foward();

<6>이전 프레임으로

이전으로 넘어가는 함수는 FramePrev입니다. 이 때 인자가 있는데 몇 프레임 이전으로 갈 것인가를 설정해 주는 것입니다. 1 프레임 이전으로 갔을 때는 이전 프레임으로 간 표시가 별로 나지 않습니다.

프로그램의 성격에 맞추어 설정해 주면 됩니다. 본 프로그램에서는 10으로 설정하였습니다.

m_pVideo->FramePrev(10);

<7>다음 프레임으로

다음 프레임으로 가는 함수는 FrameNext입니다. 이 함수도 이전 프레임 함수와 같이 인자가 있습니다.

m_pVideo->FrameNext(10);

<8>끝내기

끝낼 때는 설정된 m_pVideo를 지우기만 하면 됩니다.

delete m_pVideo;

<9>ExAvi 의 CShowAvi 소스

CShowAvi 클래스는 대화상자 클래스로 Avi 파일을 로드하고 출력하는 대화상자입니다. 이클래스의 소스는 다음과 같습니다.

(소스시작)

// ShowAvi.h : header file

//

/////////////////////////////////////////////////////////////////////////////

// CShowAvi dialog

class CShowAvi : public CDialog

{

// Construction

public:

CShowAvi(CWnd* pParent = NULL);   // standard constructor

// Dialog Data

//{{AFX_DATA(CShowAvi)

enum { IDD = IDD_VIDEO };

// NOTE: the ClassWizard will add data members here

//}}AFX_DATA

//avi를 로드시킬 클래스

CMyVideo *m_pVideo;

//화면에 출력할 좌표

CRect m_rectBox;

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CShowAvi)

protected:

virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

//}}AFX_VIRTUAL

// Implementation

protected:

// Generated message map functions

//{{AFX_MSG(CShowAvi)

virtual BOOL OnInitDialog();

afx_msg void OnFile();

afx_msg void OnEnd();

afx_msg void OnHome();

afx_msg void OnNext();

afx_msg void OnPrev();

afx_msg void OnPause();

afx_msg void OnPlay();

afx_msg void OnClose();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

// ShowAvi.cpp : implementation file

//

#include "stdafx.h"

#include "ExAvi.h"

#include "mmsystem.h"

#include "myvid.h"

#include "ShowAvi.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CShowAvi dialog

CShowAvi::CShowAvi(CWnd* pParent /*=NULL*/)

: CDialog(CShowAvi::IDD, pParent)

{

//{{AFX_DATA_INIT(CShowAvi)

// NOTE: the ClassWizard will add member initialization here

//}}AFX_DATA_INIT

m_pVideo=NULL;

}

void CShowAvi::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CShowAvi)

// NOTE: the ClassWizard will add DDX and DDV calls here

//}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CShowAvi, CDialog)

//{{AFX_MSG_MAP(CShowAvi)

ON_BN_CLICKED(IDC_FILE, OnFile)

ON_BN_CLICKED(IDC_END, OnEnd)

ON_BN_CLICKED(IDC_HOME, OnHome)

ON_BN_CLICKED(IDC_NEXT, OnNext)

ON_BN_CLICKED(IDC_PREV, OnPrev)

ON_BN_CLICKED(IDC_PAUSE, OnPause)

ON_BN_CLICKED(IDC_PLAY, OnPlay)

ON_WM_CLOSE()

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CShowAvi message handlers

BOOL CShowAvi::OnInitDialog()

{

CDialog::OnInitDialog();

//동영상이 위치할 좌표를 얻음

CWnd *pWnd = GetDlgItem(IDC_VIDEORECT);

pWnd->GetWindowRect(&m_rectBox);

ScreenToClient(&m_rectBox);

//모든 버튼을 사용할수 없게 함

GetDlgItem(IDC_PLAY)->EnableWindow(FALSE);

GetDlgItem(IDC_PAUSE)->EnableWindow(FALSE);

GetDlgItem(IDC_PREV)->EnableWindow(FALSE);

GetDlgItem(IDC_NEXT)->EnableWindow(FALSE);

GetDlgItem(IDC_HOME)->EnableWindow(FALSE);

GetDlgItem(IDC_END)->EnableWindow(FALSE);

m_pVideo=NULL;

return TRUE;  // return TRUE unless you set the focus to a control

// EXCEPTION: OCX Property Pages should return FALSE

}

void CShowAvi::OnFile()

{

CFileDialog dlg(TRUE,_T("AVI"),_T("*.AVI"),OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,

_T("동영상화일(*.AVI)|*.AVI|"));

if(dlg.DoModal()==IDOK)

{

//avi 화일명을 받은다음

CString m_strFileName;

m_strFileName=dlg.GetPathName();

if(m_pVideo!=NULL)

delete m_pVideo;

else

{

//모든 버튼을 활성화 시킴

GetDlgItem(IDC_PLAY)->EnableWindow(TRUE);

GetDlgItem(IDC_PAUSE)->EnableWindow(TRUE);

GetDlgItem(IDC_PREV)->EnableWindow(TRUE);

GetDlgItem(IDC_NEXT)->EnableWindow(TRUE);

GetDlgItem(IDC_HOME)->EnableWindow(TRUE);

GetDlgItem(IDC_END)->EnableWindow(TRUE);

}

//avi 화일을 로드한다.

m_pVideo= new CMyVideo(m_rectBox.left,

m_rectBox.top,

m_rectBox.right-m_rectBox.left,

m_rectBox.bottom-m_rectBox.top,

(LPSTR)m_strFileName.operator const char*(),

this->m_hWnd);

}

}

//끝으로

void CShowAvi::OnEnd()

{

m_pVideo->Foward();

}

//처음으로

void CShowAvi::OnHome()

{

m_pVideo->Rewind();

}

//다음으로

void CShowAvi::OnNext()

{

m_pVideo->FrameNext(10);

}

//이전으로

void CShowAvi::OnPrev()

{

m_pVideo->FramePrev(10);

}

//멈춤

void CShowAvi::OnPause()

{

m_pVideo->Pause();

}

//Play

void CShowAvi::OnPlay()

{

m_pVideo->Play();

}

//대화상자가 종료될때

void CShowAvi::OnClose()

{

if(m_pVideo)

delete m_pVideo;

CDialog::OnClose();

}

(소스끝)