접기
#include <mmsystem.h>
class CVideo : public CObject
{
public:
void Close(); // 오픈된 디바이스를 닫는다.
BOOL Open(CString strFileName, CWnd* pWnd, CRect rc);
void SetPrevFrame(UINT pos); // 이전 프레임으로 이동
void SetNextFrame(UINT pos); // 다음 프레임으로 이동
void EndPos(); // 마지막 프레임으로 이동
void StartPos(); // 처음 프레임으로 이동
DWORD GetCurFrame(); // 현재 프레임 수
DWORD GetTotalFrame(); // 총 프레임 수
BOOL Play(); // 재생
void Pause(); // 일시 정지
void DisplayError(DWORD error); // 에러 메시지 출력
CVideo();
~CVideo();
protected:
MCI_PLAY_PARMS mciPlay;
MCI_ANIM_WINDOW_PARMS mciWindow;
MCIDEVICEID dwDeviceID;
};
CVideo::CVideo() {}
CVideo::~CVideo() {}
BOOL CVideo::Open(CString strFileName, CWnd *pWnd, CRect rc)
{
MCI_ANIM_OPEN_PARMS mciOpen;
MCI_ANIM_RECT_PARMS mciRect;
DWORD result = 0; // 에러 체크
if(strFileName.Right(3) == "avi") // 파일 확장자 판단
mciOpen.lpstrDeviceType = "avivideo"; // 장치 타입 설정
else if(strFileName.Right(3) == "mpg"
|| strFileName.Right(3) == "mov")
mciOpen.lpstrDeviceType = "MPEGVideo"; // 장치 타입 설정
mciOpen.lpstrElementName = strFileName; // 재생할 파일 경로 설정
result =
mciSendCommand (0,
MCI_OPEN , MCI_OPEN_ELEMENT | MCI_OPEN_TYPE | MCI_ANIM_OPEN_WS,
(DWORD)(LPVOID)&mciOpen);
DisplayError(result);
dwDeviceID = mciOpen.wDeviceID; // 디바이스 ID 저장
mciRect.rc = rc; // 동화상이 출력될 사각형 설정
result =
mciSendCommand (dwDeviceID, MCI_PUT,
MCI_ANIM_PUT_DESTINATION | MCI_ANIM_RECT,
(DWORD)(LPVOID)&mciRect);
DisplayError(result);
mciWindow.hWnd = pWnd->GetSafeHwnd();
result =
mciSendCommand (dwDeviceID, MCI_WINDOW, MCI_ANIM_WINDOW_HWND,
(DWORD)(LPVOID)&mciWindow);
DisplayError(result);
return TRUE;
}
void CVideo::Close()
{
mciSendCommand (dwDeviceID,
MCI_CLOSE , 0, NULL);
}
BOOL CVideo::Play()
{
DWORD result = 0; // 에러 체크
mciPlay.dwCallback = (DWORD)mciWindow.hWnd;
result =
mciSendCommand (dwDeviceID,
MCI_PLAY ,
MCI_NOTIFY ,
(DWORD)(LPVOID)&mciPlay);
DisplayError(result);
result =
mciSendCommand (dwDeviceID, MCI_REALIZE,
MCI_ANIM_REALIZE_NORM, NULL);
DisplayError(result);
return TRUE;
}
void CVideo::Pause()
{
mciSendCommand (dwDeviceID,
MCI_PAUSE , NULL, (DWORD)(LPVOID)&mciPlay);
}
void CVideo::StartPos()
{
mciSendCommand (dwDeviceID,
MCI_SEEK ,
MCI_SEEK_TO_START ,
(DWORD)(LPVOID)NULL);
}
void CVideo::EndPos()
{
mciSendCommand (dwDeviceID,
MCI_SEEK ,
MCI_SEEK_TO_END ,
(DWORD)(LPVOID)NULL);
}
void CVideo::DisplayError(DWORD error) // 에러 출력 함수
{
if(error)
{
char strInfo[256];
if(!mciGetErrorString(error, strInfo, sizeof(strInfo)))
strcpy(strInfo, "모르는 에러");
AfxMessageBox(strInfo); // 에러 메시지 출력
}
}
DWORD CVideo::GetTotalFrame() // 총 프레임 수 얻음
{
MCI_STATUS_PARMS mciStatus;
mciStatus.dwItem = MCI_STATUS_LENGTH; // 전체 프레임 길이
mciSendCommand (dwDeviceID,
MCI_STATUS , MCI_STATUS_ITEM,
(DWORD)(LPVOID)&mciStatus);
return mciStatus.dwReturn;
}
DWORD CVideo::GetCurFrame() // 현재 프레임 위치 얻음
{
MCI_STATUS_PARMS mciStatus;
mciStatus.dwItem = MCI_STATUS_POSITION;
mciSendCommand (dwDeviceID,
MCI_STATUS , MCI_STATUS_ITEM|MCI_NOTIFY,
(DWORD)(LPVOID)&mciStatus);
return mciStatus.dwReturn;
}
void CVideo::SetPrevFrame(UINT pos)
{
DWORD totalFrame, curFrame;
totalFrame = GetTotalFrame();
curFrame = GetCurFrame();
if(totalFrame == 0)
return;
MCI_SEEK_PARMS mciSeek;
mciSeek.dwTo = curFrame-pos;
mciSendCommand (dwDeviceID,
MCI_SEEK , MCI_TO | MCI_WAIT,
(DWORD)(LPVOID)&mciSeek);
}
void CVideo::SetNextFrame(UINT pos)
{
DWORD totalFrame, curFrame;
totalFrame = GetTotalFrame();
curFrame = GetCurFrame();
if(totalFrame == curFrame)
return;
MCI_ANIM_STEP_PARMS mciStep;
mciStep.dwFrames = pos;
mciSendCommand (dwDeviceID, MCI_STEP, MCI_ANIM_STEP_FRAMES,
(DWORD)(LPVOID)&mciStep);
}
class CAviFrame : public CFrameWnd
{
DECLARE_DYNCREATE(CAviFrame)
public:
CAviFrame();
virtual ~CAviFrame();
...
// Generated message map functions
//{{AFX_MSG(CAviFrame)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
LONG OnMCINotify(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
IMPLEMENT_DYNCREATE(CAviFrame, CFrameWnd)
CAviFrame::CAviFrame()
{
}
CAviFrame::~CAviFrame()
{
}
BEGIN_MESSAGE_MAP(CAviFrame, CFrameWnd)
//{{AFX_MSG_MAP(CAviFrame)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
ON_MESSAGE(
MM_MCINOTIFY , OnMCINotify)
END_MESSAGE_MAP()
...
LONG CAviFrame::OnMCINotify(WPARAM wParam, LPARAM lParam)
{
switch(wParam)
{
case MCI_NOTIFY_SUCCESSFUL:
AfxMessageBox("Playback completed");
DestroyWindow(); // 재생이 끝나면 윈도우 종료
break;
case MCI_NOTIFY_FAILURE:
AfxMessageBox("Playback interrupted!");
break;
case MCI_NOTIFY_SUPERSEDED:
AfxMessageBox("Playback stopped!");
break;
case MCI_NOTIFY_ABORTED:
AfxMessageBox("Playback aborted!");
break;
}
return 0L;
}
class CAviPlayDlg : public CDialog
{
...
// Implementation
protected:
HICON m_hIcon;
CVideo* m_pVideo;
CAviFrame* m_pFrame;
// Generated message map functions
//{{AFX_MSG(CAviPlayDlg)
...
afx_msg void OnOpenFile();
afx_msg void OnPause();
afx_msg void OnPlay();
afx_msg void OnEnd();
afx_msg void OnStart();
afx_msg void OnNext();
afx_msg void OnPrev();
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAviPlayDlg::CAviPlayDlg(CWnd* pParent /*=NULL*/)
: CDialog(CAviPlayDlg::IDD, pParent)
{
...
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pVideo = NULL;
m_pFrame = NULL;
}
void CAviPlayDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAviPlayDlg)
DDX_Control(pDX, IDC_START, m_Start);
DDX_Control(pDX, IDC_PREV, m_Prev);
DDX_Control(pDX, IDC_PLAY, m_Play);
DDX_Control(pDX, IDC_PAUSE, m_Pause);
DDX_Control(pDX, IDC_OPEN_FILE, m_Open);
DDX_Control(pDX, IDC_NEXT, m_Next);
DDX_Control(pDX, IDC_END, m_End);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAviPlayDlg, CDialog)
//{{AFX_MSG_MAP(CAviPlayDlg)
...
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_OPEN_FILE, OnOpenFile)
ON_BN_CLICKED(IDC_PAUSE, OnPause)
ON_BN_CLICKED(IDC_PLAY, OnPlay)
ON_BN_CLICKED(IDC_END, OnEnd)
ON_BN_CLICKED(IDC_START, OnStart)
ON_BN_CLICKED(IDC_NEXT, OnNext)
ON_BN_CLICKED(IDC_PREV, OnPrev)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
...
void CAviPlayDlg::OnDestroy()
{
CDialog::OnDestroy();
if(m_pVideo)
{
// 오픈된 디바이스를 닫고 힙에 할당된 비디오 객체 제거
m_pVideo->Close();
delete m_pVideo;
}
}
void CAviPlayDlg::OnOpenFile()
{
if(m_pVideo) // 이미 생성된 객체가 있는지 판단
{
// 오픈된 디바이스를 닫고 힙에 할당된 비디오 객체 제거
m_pVideo->Close();
delete m_pVideo;
m_pVideo = NULL;
}
CFileDialog dlg(TRUE, "", "", OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
"AVI 파일(*.avi)|*.avi|MPEG 파일(*.mpg)|*.mpg|MOV 파일(*.mov)|*.mov||");
if(dlg.DoModal() == IDOK)
{
CRect rc;
m_pFrame = new CAviFrame;
m_pFrame->Create(NULL, "동영상 윈도우");
m_pFrame->ShowWindow(SW_SHOW);
m_pFrame->UpdateWindow();
m_pFrame->GetClientRect(rc);
m_pFrame->SetWindowText(dlg.GetFileName());
m_pVideo = new CVideo;
m_pVideo->Open(dlg.GetPathName(), m_pFrame, rc);
}
}
void CAviPlayDlg::OnPause()
{
if(m_pVideo)
m_pVideo->Pause(); // 일시 중지
}
void CAviPlayDlg::OnPlay()
{
if(m_pVideo)
m_pVideo->Play(); // 동영상 재생
}
void CAviPlayDlg::OnEnd()
{
if(m_pVideo)
m_pVideo->EndPos(); // 마지막 프레임으로 이동
}
void CAviPlayDlg::OnStart()
{
if(m_pVideo)
m_pVideo->StartPos(); // 처음 프레임으로 이동
}
void CAviPlayDlg::OnNext()
{
if(m_pVideo)
m_pVideo->SetNextFrame(5); // 앞으로 5프레임 이동
}
void CAviPlayDlg::OnPrev()
{
if(m_pVideo)
m_pVideo->SetPrevFrame(5); // 뒤로 5프레임 이동
}
접기