| 首页 | 新闻 | 网页 | 设计 | 色彩 | 原创 | 视觉 | 素材 | 动漫 | 酷站 | 策划 | 文案 | 访谈 | 运营 | 编程 | 数据库 | 服务器 | 下载 | 图库 | 
您的位置: 幽幽天空 > 网页 > 编程开发 > Visual C++教程 > 文章正文 用户登录
为什么创业者总是
如何实现SWF转VCD
SWF高质量转换为V
SWF转VCD完整篇
Visual C++实现Fl
FLASH转化为VCD 没
在 Visual Studio
在VC中用OLE DB读
用VC程序来创建SQ
在VB中使用文件对

在VC++中实现自动连续播放多媒体文件           

在VC++中实现自动连续播放多媒体文件

作者:佚名 来源:天极 更新:2006-8-25 21:05:35 错误报告 我要投稿

 

  一、实现方法

  可视动画控件ActiveMovie Control Object 是Microsoft公司开发的ActiveX控件,为程序员提供了在该层次上控制媒体设备接口的能力。它包含一组高层次的独立于设备的命令,可以控制音频和视频外设,我们不必关心具体的设备便可以对CD、视盘机、波形音频设备、视频播放设备和MIDI设备等媒体设备进行控制,也可以理解成设备面板上的一排按键,通过选择不同的按键(发送不同的命令)即可让设备完成各种功能,而不必关心设备的内部实现,它是一种主要实现音/视频播放的方法。下面先介绍一下当前音/视频文件的主要形式:

  1、波形音频

  波形音频是一种电子数字化声音,是计算机播放音频的一种重要的形式,它存储的声音的波形信息,特点是:当播放播形音频时,不管播放文件的设备是何种类型,都会得到相似的声音。波形音频文件通常以.wav作为文件扩展名。由于采用波形音频存储电子需要大量的存储空间,因此它一般只用于短时间的声音播放。

  2、MIDI音乐

  MIDI(Musical Instrument Digital Interface)在多媒体音频中占有重要的位置,是播放和录制音乐的国际标准,它确定了连接音乐设备的电缆线、硬件和通信协议。多媒体计算机只需具有MIDI接口声卡和MIDI合成器,就具有处理MIDI的功能。MIDI在处理音乐时是将MIDI音乐设备上产生的活动编码记录下来,将这些数据传递到MIDI合成器上就能中现原来的演奏。MIDI的消息有两种类型:状态字节和数字字节。状态字节描述发送的类别(动作和函数),数字字节总是跟在状态字节后,表示发送消息的实际值。数值字节的个数取决于状态字节表示的消息类型。MIDI通过通道字节最高位区别这两种类型。最高位为1表示状态字节,最高位为0表示数字字节。

  3、CD音频

  CD音频采用红皮书标准,通过CD-ROM驱动器来播放CD音频。CD音频需要的存储量大,一张光盘大约能够存储10首歌,70分钟音频左右。在一般情况下,整个光盘都用来存储CD音频数据,并划分为多个音轨,轨道的具体长度可以不定,通常一个音轨对应一首曲目。CD音频的长度由分、秒、帧的形式来衡量,最小的单位为帧,每一帧为1/75秒,一分等于60秒。

  4、数字视频

  数字视频(Digital Video)使用数据信息在计算机上实现动画的效果,它是利用人眼睛的视觉暂留形成的,使人们连续图像效果所需的最低播放速度是24幅/秒,播放速度越快,数字视频给人的视觉连续性效果越好。存储视频影像需要巨大的磁盘空间,一般来讲,1秒钟全屏视频信号需要大约28MB的空间。为了实现连续的视频播放,不仅需要有足够的空间来存储视频音像信息,还需要保证硬盘有28MB/秒的传播速度。数字视频包括AVI、MEPG等格式。其中AVI文件格式是由微软提出的在WINDOWS下存储视频信息的标准。它以一系列的位图来存储视频信息,并同时在文件中以数字形式来存储数字化视频信息,它实际上是由一组信息流组成的文件。
ACTIVEMOVIE CONTROL OBJECT的常用属性包括以下几个:

  (1)播放文件的函数:

void CActiveMovie3::Run()
{
  InvokeHelper(0x60020001, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
}

  (2)暂停播放的函数:

void CActiveMovie3::Pause()
{
  InvokeHelper(0x60020002, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
}

  (3)停止播放的函数:

void CActiveMovie3::Stop()
{
  InvokeHelper(0x60020003, DISPATCH_METHOD, VT_EMPTY, NULL, NULL);
}

  (4)获得文件的函数:

CString CActiveMovie3::GetFileName()
{
  CString result;
  InvokeHelper(0xb, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
  return result;
}

  (5)设置文件的函数:

void CActiveMovie3::SetFileName(LPCTSTR lpszNewValue)
{
  static BYTE parms[] = VTS_BSTR;
  InvokeHelper(0xb, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms,lpszNewValue);
}

  (6)获得播放位置的函数:

double CActiveMovie3::GetCurrentPosition()
{
  double result;
  InvokeHelper(0xd, DISPATCH_PROPERTYGET, VT_R8, (void*)&result, NULL);
  return result;
}

  (7)设置播放位置的函数:

void CActiveMovie3::SetCurrentPosition(double newValue)
{
  static BYTE parms[] = VTS_R8;
  InvokeHelper(0xd, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue);
}

  (8)获得音量的函数:

long CActiveMovie3::GetVolume()
{
  long result;
  InvokeHelper(0x13, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL);
  return result;
}

  (9)设置音量的函数:

void CActiveMovie3::SetVolume(long nNewValue)
{
  static BYTE parms[] = VTS_I4;
  InvokeHelper(0x13, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, nNewValue);
}

  (10)设置自动开始播放的函数:

void CActiveMovie3::SetAutoStart(BOOL bNewValue)
{
  static BYTE parms[] = VTS_BOOL;
  InvokeHelper(0x28, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, bNewValue);
}

  在Visual C++6.0中,一般情况都是在基于对话框的应用程序中使用ActiveMovie控件,可在菜单中依次选择"project- > Add To Project- > Components And Controls",在出现的"Components And Controls Gallery"对话框中打开"Registered Active Controls"文件夹,选中"ActiveMovie Control Object"选项,按"Insert"按钮后关闭该对话框,ActiveMovie控件便出现在程序编辑器的控件面板中,调整好控件在对话框中的位置。利用ClassWizard为ActiveMovie控件声明一个变量,设该变量的名字为m_ActiveMovie,当用户选择过待播放的文件后,为了能够播放多个文件,可以使用如下代码来向列表控件添加待播放的文件名:

CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,szFileFilter);
if(dlg.DoModal()==IDOK)
{
  CString m_filename=dlg.GetPathName();
  m_list.AddString(m_filename);
  UpdateData(FALSE);
}

  为了实现多媒体文件的循环播放,我们利用定时器来工作,在定时器中添加代码如下:

CString m_filename; //定义文件变量
double CurPos=m_ActiveMovie.GetCurrentPosition(); //获得播放位置
if(CurPos= = 0)
{
  //选择列表框的第一个文件
  m_list.SetCurSel(0);
  m_list.GetText(0,m_filename);
  //设置自动播放
  m_ActiveMovie.SetAutoStart(1);
  //设置文件
  m_ActiveMovie.SetFileName(m_filename);
  //播放
  m_ActiveMovie.Run();
  m_list.GetCurSel();
  //插入列表框最后
  m_list.InsertString(-1,m_filename);
  //删除用过的文件
  m_list.DeleteString(0);
}
CDialog::OnTimer(nIDEvent);
}

  当需要关闭音/视频的播放时,可以用函数m_ActiveMovie.Stop()来实现。

   二、编程步骤

  1、 启动Visual C++6.0,生成一个基于对话框的程序,将该程序命名为"Player",去掉程序中对话框上的"确定" 和"取消"按钮,并加入ActiveMovie控件;

  2、 使用资源编辑器对话框添加三个按钮("选择曲目Open"、"循环播放Play"、"关闭Stop")和一个列表框;

  3、 使用ClassWizard为三个按钮和列表框添加成员变量,分别为:CButton m_stop、 CButton m_play、CListBox m_list;并且为三个按钮添加鼠标单击消息响应函数;

  4、 添加代码,编译运行程序。

三、程序代码

//////////////////////////////////////////////////////////////////////////////////// playerDlg.h : header file
//{{AFX_INCLUDES()
#include "activemovie3.h"
//}}AFX_INCLUDES
#if !defined(AFX_PLAYERDLG_H__F5B21A8A_5EE9_11D7_BCB5_CEB29E77AC3D__INCLUDED_)
#define AFX_PLAYERDLG_H__F5B21A8A_5EE9_11D7_BCB5_CEB29E77AC3D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CPlayerDlgAutoProxy;

class CPlayerDlg : public CDialog
{
  DECLARE_DYNAMIC(CPlayerDlg);
  friend class CPlayerDlgAutoProxy;
  // Construction
  public:
   CPlayerDlg(CWnd* pParent = NULL); // standard constructor
   virtual ~CPlayerDlg();
   // Dialog Data
   //{{AFX_DATA(CPlayerDlg)
    enum { IDD = IDD_PLAYER_DIALOG };
    CButton m_stop;
    CButton m_play;
    CListBox m_list;
    CButton m_openfile;
    CActiveMovie3 m_activemovie;
   //}}AFX_DATA
   // ClassWizard generated virtual function overrides
   //{{AFX_VIRTUAL(CPlayerDlg)
  protected:
   virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
   //}}AFX_VIRTUAL
   // Implementation
  protected:
   CPlayerDlgAutoProxy* m_pAutoProxy;
   HICON m_hIcon;
   BOOL CanExit();
   // Generated message map functions
   //{{AFX_MSG(CPlayerDlg)
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnClose();
    virtual void OnOK();
    virtual void OnCancel();
    afx_msg void OnButton1();
    afx_msg void OnTimer(UINT nIDEvent);
    afx_msg void OnButton2();
    afx_msg void OnButton3();
   //}}AFX_MSG
   DECLARE_MESSAGE_MAP()
  };
  #endif

//////////////////////////////////////////////////////////////// playerDlg.cpp : implementation file
#include "stdafx.h"
#include "player.h"
#include "playerDlg.h"
#include "DlgProxy.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

///////////////////////////////////////////////////////////// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
  public:
   CAboutDlg();
   // Dialog Data
   //{{AFX_DATA(CAboutDlg)
    enum { IDD = IDD_ABOUTBOX };
   //}}AFX_DATA
   // ClassWizard generated virtual function overrides
   //{{AFX_VIRTUAL(CAboutDlg)
   protected:
    virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
    //}}AFX_VIRTUAL
    // Implementation
   protected:
    //{{AFX_MSG(CAboutDlg)
    //}}AFX_MSG
   DECLARE_MESSAGE_MAP()
};
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
  //{{AFX_DATA_INIT(CAboutDlg)
  //}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
  CDialog::DoDataExchange(pDX);
  //{{AFX_DATA_MAP(CAboutDlg)
  //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  //{{AFX_MSG_MAP(CAboutDlg)
  // No message handlers
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

// CPlayerDlg dialog
IMPLEMENT_DYNAMIC(CPlayerDlg, CDialog);

CPlayerDlg::CPlayerDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPlayerDlg::IDD, pParent)
{
  //{{AFX_DATA_INIT(CPlayerDlg)
  //}}AFX_DATA_INIT
  // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  m_hIcon = AfxGetApp()-> LoadIcon(IDR_MAINFRAME);
  m_pAutoProxy = NULL;
}

CPlayerDlg::~CPlayerDlg()
{
  // If there is an automation proxy for this dialog, set
  // its back pointer to this dialog to NULL, so it knows
  // the dialog has been deleted.
  if (m_pAutoProxy != NULL)
   m_pAutoProxy-> m_pDialog = NULL;
}

void CPlayerDlg::DoDataExchange(CDataExchange* pDX)
{
  CDialog::DoDataExchange(pDX);
  //{{AFX_DATA_MAP(CPlayerDlg)
   DDX_Control(pDX, IDC_BUTTON3, m_stop);
   DDX_Control(pDX, IDC_BUTTON2, m_play);
   DDX_Control(pDX, IDC_LIST1, m_list);
   DDX_Control(pDX, IDC_BUTTON1, m_openfile);
   DDX_Control(pDX, IDC_ACTIVEMOVIECONTROL1, m_activemovie);
  //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPlayerDlg, CDialog)
  //{{AFX_MSG_MAP(CPlayerDlg)
   ON_WM_SYSCOMMAND()
   ON_WM_PAINT()
   ON_WM_QUERYDRAGICON()
   ON_WM_CLOSE()
   ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
   ON_WM_TIMER()
   ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
   ON_BN_CLICKED(IDC_BUTTON3, OnButton3)
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CPlayerDlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  ASSERT(IDM_ABOUTBOX < 0xF000);
  CMenu* pSysMenu = GetSystemMenu(FALSE);
  if (pSysMenu != NULL)
  {
   CString strAboutMenu;
   strAboutMenu.LoadString(IDS_ABOUTBOX);
   if (!strAboutMenu.IsEmpty())
   {
    pSysMenu-> AppendMenu(MF_SEPARATOR);
    pSysMenu-> AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
   }
  }
  SetIcon(m_hIcon, TRUE); // Set big icon
  SetIcon(m_hIcon, FALSE); // Set small icon
  return TRUE; // return TRUE unless you set the focus to a control
}

void CPlayerDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
  if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  {
   CAboutDlg dlgAbout;
   dlgAbout.DoModal();
  }
  else
  {
   CDialog::OnSysCommand(nID, lParam);
  }
}

void CPlayerDlg::OnPaint()
{
  if (IsIconic())
  {
   CPaintDC dc(this); // device context for painting
   SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
   // Center icon in client rectangle
   int cxIcon = GetSystemMetrics(SM_CXICON);
   int cyIcon = GetSystemMetrics(SM_CYICON);
   CRect rect;
   GetClientRect(&rect);
   int x = (rect.Width() - cxIcon + 1) / 2;
   int y = (rect.Height() - cyIcon + 1) / 2;
   // Draw the icon
   dc.DrawIcon(x, y, m_hIcon);
  }
  else
  {
   CDialog::OnPaint();
  }
}

// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CPlayerDlg::OnQueryDragIcon()
{
  return (HCURSOR) m_hIcon;
}

// Automation servers should not exit when a user closes the UI
// if a controller still holds on to one of its objects. These
// message handlers make sure that if the proxy is still in use,
// then the UI is hidden but the dialog remains around if it
// is dismissed.
void CPlayerDlg::OnClose()
{
  if (CanExit())
   CDialog::OnClose();
}

void CPlayerDlg::OnOK()
{
  if (CanExit())
   CDialog::OnOK();
}

void CPlayerDlg::OnCancel()
{
  if (CanExit())
   CDialog::OnCancel();
}

BOOL CPlayerDlg::CanExit()
{
  // If the proxy object is still around, then the automation
  // controller is still holding on to this application. Leave
  // the dialog around, but hide its UI.
  if (m_pAutoProxy != NULL)
  {
   ShowWindow(SW_HIDE);
   return FALSE;
  }
  return TRUE;
}

void CPlayerDlg::OnButton1()
{
  // TODO: Add your control notification handler code here
  char szFileFilter[]=
  "Mp3 File(*.mp3)|*.mp3|"
  "Wma File(*.wma)|*.wma|"
  "Video File(*.dat)|*.dat|"
  "Wave File(*.wav)|*.wav|"
  "AVI File(*.avi)|*.avi|"
  "Movie File(*.mov)|*.mov|"
  "Media File(*.mmm)|*.mmm|"
  "Mid File(*.mid;*,rmi)|*.mid;*.rmi|"
  "MPEG File(*.mpeg)|*.mpeg|"
  "All File(*.*)|*.*||";
  CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,szFileFilter);
  if(dlg.DoModal()==IDOK)
  {
   CString m_filename=dlg.GetPathName();
   m_list.AddString(m_filename);
   UpdateData(FALSE);
  }
}

void CPlayerDlg::OnTimer(UINT nIDEvent)
{
  // TODO: Add your message handler code here and/or call default
  double CurPos=m_activemovie.GetCurrentPosition();
  CString filename;
  if(CurPos==0){
   m_list.SetCurSel(0);
   m_list.GetText(0,filename);
   m_activemovie.SetAutoStart(1);
   m_activemovie.SetFileName(filename);
   m_activemovie.Run();
   m_list.GetCurSel();
   m_list.InsertString(-1,filename);
   m_list.DeleteString(0);
  }
  CDialog::OnTimer(nIDEvent);
}

void CPlayerDlg::OnButton2()
{
  // TODO: Add your control notification handler code here
  SetTimer(0,500,NULL);
}

void CPlayerDlg::OnButton3()
{
  // TODO: Add your control notification handler code here
  KillTimer(0);
  m_activemovie.Stop();
}

   四、小结

  目前很多程序介绍的播放器,只能播放单个音频/视频文件,很少讲述如何实现多个文件的连续播放,本文试着通过控件,介绍连续播放音/视频文件的方法。我们还可以根据上述提供函数常用属性,解决程序中间的暂停、设置音量,还可以设置平衡、全屏播放等,希望本实例能给读者朋友一个启示。

  随着计算机技术的发展,人们不仅使用单一的文字作为信息的载体,还可以通过各种各样的媒体来传递、存储信息。我们通常所说的"媒体"(Media)包括其中的两点含义,一是指信息的物理载体(即存储和传递信息的实体),如书本、挂图、磁盘、光盘、磁带以及 相关的播放设备等;另一层含义是指信息的表现形式(或者说传播形式),如文字、声音、图像、动画等。多媒体计算机中所说的媒体,是指后者而言,即计算机不仅能处理文字、数值之类的信息,而且还能处理声音、图形、电视图像等各种不同形式的信息。对各种信息媒体的"处理",是指计算机能够对它们进行获取、编辑、存储、检索、展示、传输等各种操作。一般而言,具有对多种媒体进行处理能力的计算机可称为多媒体计算机。多媒体技术不是各 种信息媒体的简单复合,它是一种把文本(Text)、图形(Graphics)、图像(Images)、动画(Animation)和声音(Sound)等形式的信息结合在一起,并通过计算机进行综合处理和控制,能支持完成一系列交互式操作的信息技术。多媒体技术的发展改变了计算机的使用领域,使计算机由办公室、实验室中的专用品变成了信息社会的普通工具,广泛应用于工业生产管理、学校教育、公共信息咨询、商业广告、军事指挥与训练,甚至家庭生活与娱乐等领域。

  我们可以利用MCI控件开发多媒体项目,但现在介绍一种更简便的方法,用ACTIVEMOVIE CONTROL OBJECT控件来实现的方法。可视动画控件ActiveMovie是Microsoft公司开发的ActiveX控件,从开始的1.0版、1.2版到现在的2.0版,功能上已经有了很大的改进。由于该控件内嵌了Microsoft MPEG音频解码器和Microsoft MPEG视频解码器,所以能够很好地支持音频文件和视频文件,用其播放的VCD效果就很好。另外,播放时若用鼠标右键单击画面,可以直接对画面的播放、暂停、停止等进行控制,读者还可以自行在"属性"栏中对影片播放进行控制设置,用起来非常方便。 当前在Microsoft公司推出的Visual C++6.0中已经包含了ActiveMovie控件的2.0版,本实例将介绍在Visual C++6.0中利用这个控件实现自动连续播放多个多媒体文件。程序编译运行后的界面效果如图一所示:




图一、播放AVI文件的界面效果图

文章录入:skyuu    责任编辑:skyuu 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    发表评论:
    姓名:  评 分: 1分 2分 3分 4分 5分
     
  • 严禁发表危害国家安全、政治、黄色淫秽等内容的评论。
  • 用户需对自己在使用幽幽天空服务过程中的行为承担法律责任。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表机友个人观点,与本网站立场无关。