<Win32_17>集音频和视频播放功能于一身的简易播放器

本文由BlueCoder编写   转载请说明出处:

http://blog.csdn.net/crocodile__/article/details/10832337

我的邮箱:bluecoder@yeah.net    欢迎大家和我交流编程心得

我的微博:BlueCoder_黎小华    欢迎光临^_^




前段时间,在学习中科院杨老师的教学视频时,他说了一句话:

"我很反对百八十行的教学程序,要来就来一个完整的程序"

对此,我很是赞同。所谓真刀真枪的做了,你才会发现其中的奥秘——然而,能写一个完整的程序,首先你肯定是理解掌握了相关的技术,其次你享受了一个完整开发的基本"旅程"

 

因此,除非是很重要的技术,我会仅仅用一个几十行代码的程序加以说明,否则我就会用一个完整的程序来实现一些基本功能——通过这个完整的程序来掌握相关技术,我感觉很好……

 

好了,F话不多说了,切入正题

 

……

 

*****************************************************程序效果***********************************************************

还是先来看一看鄙人写的简易播放器实现的效果吧:

 

 

可以看到,它既可以播放mp3音频文件,也可以播放avi视频文件

 

 

*****************************************************实现细节***********************************************************

 

(1)利用win32提供的MCI来播放音频或者视频文件

(2)用一个文件浏览对话框来提供文件选择功能

(3)做一个标准菜单——包含快捷键

 

 

*****************************************************代码详解***********************************************************

 

(1)创建一个文件浏览对话框

1>初始化OPENFILENAME结构体变量,它的成员有很多,不过一般只有以下几个很常用(其余的,读者可以参见msdn):

lStructSize——   结构体变量大小,用sizeof(OPENFILENAME)指定

hwndOwner—— 拥有它的窗口句柄

lpstrFilter——     文件过滤

lpstrFile——       保存文件绝对路径

nMaxFile——     绝对路径的最大长度

lpstrFileTitle——对话框标题

nMaxFileTitle— 对话框标题的最大长度

Flags————   标示

 

它的初始化以及相应操作,我是在一个函数中实现的——openFileDialog,具体代码如下:

//打开文件浏览对话框
VOID openFileDialog(HWND hOwner)
{
	static TCHAR	szFilePath[MAX_PATH], szTitleName[MAX_PATH];
	OPENFILENAME	ofn;
	TCHAR			szFileFilter[] = TEXT("Media Files(*.avi;*.mpg;*.mpeg;*.asf;*.wmv;*.mp2;*.mp3)\0")\
									 TEXT("*.avi;*.mpg;*.mpeg;*.asf;*.wmv;*.mp2;*.mp3\0")\
									 TEXT("Movie File(*.avi;*.mpg;*.mpeg)\0*.avi;*.mpg;*.mpeg\0")\
									 TEXT("Windows Media File(*.asf;*.wmv)\0*.asf;*.wmv\0")\
									 TEXT("Audio File(*.mp2;*.mp3)\0*.mp2;*.mp3\0");

	//初始化ofn结构体变量
	ZeroMemory(&ofn, sizeof(OPENFILENAME));

	ofn.lStructSize		= sizeof(OPENFILENAME);
	ofn.hwndOwner		= hOwner;
	ofn.lpstrFilter		= szFileFilter;
	ofn.lpstrFile		= szFilePath;
	ofn.nMaxFile		= MAX_PATH;
	ofn.lpstrFileTitle	= szTitleName;
	ofn.nMaxFileTitle	= MAX_PATH;
	ofn.Flags			= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;

	//打开文件浏览对话框
	if(GetOpenFileName(&ofn))
	{
		int		i=0, j=0, k=0;

		/*
			因为ASCII的字符串中, '\'只能以'\\'才能识别, 所以还得自行在'\'之后添加一个'\'
		*/
		while(szFilePath[i])
		{
			szFileDir[j++] = szFilePath[i];
			if(szFileName[i++] == '\\')
				szFileDir[j++] = '\\';
			if(i >= ofn.nFileOffset)
				szFileName[k++] = szFilePath[i];
		}

		szFileDir[j] = '\0';
		szFileName[k] = '\0';

		//先停止当前播放的视、音频文件
		mciSendString("Close movie", NULL, 0, 0);
		openFile(hOwner);
		
		if(!isMp)
		{
			//打开视频文件后 , 先短暂播放一截 , 给你一个预览的效果
			mciSendString("Play movie", NULL, 0, 0);
			mciSendString("Pause movie", NULL, 0, 0);
		}

		//设置窗口标题为当前打开文件的完整路径
		SetWindowText(hOwner, szFileDir);

		isEnable = TRUE;//标记菜单项可执行
	}
}


 

(2)MCI代码细节

1>打开利用MCI关联系统设备打开相应文件,这需要使用到MCI_DGV_OPEN_PARMS,来看看msdn:

typedef struct {
    DWORD_PTR dwCallback;	//就是窗口句柄,用于MCI_NOTIFY这个标示 
    UINT      wDeviceID; 	//设备ID,一般为0
    LPSTR     lpstrDeviceType;	//设备类型 
    LPSTR     lpstrElementName; //打开文件的绝对地址
    LPSTR     lpstrAlias; 	//设备别名
    DWORD     dwStyle; 		//窗口风格(如果你想在主窗口中播放, 需要设定为子窗口风格WS_CHILD)
    HWND      hWndParent; 	//父窗口句柄
} MCI_DGV_OPEN_PARMS; 

 

2>初始化好这个变量后,就要通知系统打开相应设备,用mciSendCommand这个函数,还是先来看看msdn:

MCIERROR mciSendCommand(
     MCIDEVICEID IDDevice,	//设备ID, 一般为0
     UINT        uMsg,       	//MCI消息
     DWORD       fdwCommand,	//MCI命令
     DWORD_PTR   dwParam 	//指向刚刚初始化的结构体变量    
);


3>下面需要创建一个窗口用于播放视频,使用MCI_DGV_STATUS_PARMS结构体:

typedef struct {
    DWORD_PTR dwCallback;	//也是窗口句柄 , 同上 
    DWORD     dwReturn;		//播放视频的窗口句柄 
    DWORD     dwItem; 		//下面不是很重要,一般可以不管
    DWORD     dwTrack; 
    LPSTR     lpstrDrive; 
    DWORD     dwReference; 
} MCI_DGV_STATUS_PARMS;


4>我写了一个函数——openFile打开文件,用于实现上述功能,具体如下:

//打开音频或视频文件
VOID openFile(HWND hParent)
{
	MCI_DGV_OPEN_PARMS		mciOpen;//MCI打开参数结构体
	MCI_DGV_STATUS_PARMS	mciStatus;//MCI状态参数结构体
	UINT					uDeviceID;//设备ID
	RECT					rClient;//父窗口客户区大小

	mciStatus.dwItem=MCI_DGV_STATUS_HWND;

	//初始化mciOpen以及打开avi文件
	ZeroMemory(&mciOpen,sizeof(mciOpen));
	mciOpen.dwCallback		=(DWORD)hParent;
	mciOpen.lpstrAlias		= TEXT("movie");//设备别名

	mciOpen.lpstrElementName= szFileDir;//avi文件地址

	mciOpen.hWndParent		= hParent;//父窗口
	mciOpen.dwStyle			= WS_CHILD;//窗口风格
	
	mciSendCommand(0 , MCI_OPEN, MCI_OPEN_ALIAS | MCI_OPEN_ELEMENT | 
				MCI_DGV_OPEN_PARENT | MCI_DGV_OPEN_WS, (DWORD)&mciOpen);

	//获取播放avi视频的子窗口hVideo
	uDeviceID=mciOpen.wDeviceID;	
	mciSendCommand(uDeviceID, MCI_STATUS , MCI_STATUS_ITEM, (DWORD)&mciStatus);
	hVideo=(HWND)mciStatus.dwReturn;//获取播放视频的窗口句柄

	//重绘主窗口
	GetClientRect(hParent, &rClient);
	SendMessage(hParent, WM_SIZE, 0, MAKELONG(rClient.right - rClient.left, rClient.bottom - rClient.top));

	//判断当前打开的文件是否是音频文件
	if(strstr(szFileDir, TEXT("mp3")) || strstr(szFileDir, TEXT("mp2")))
	{
		isMp = TRUE;
	}
}

 

(3)做一个标准菜单

这个和上次讲的一样,只不过加了"快捷键",菜单的创建和加载就不多说了,主要讲一下快捷键的用法

 

我们日常些一般程序的消息循环代码如下:

while(GetMessage(&msg, NULL, 0, 0))
{
	TranslateMessage(&msg);
	DispatchMessage(&msg);
}


使用键盘快速键之后修改的代码:

hAccel = LoadAccelerators (hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR));

while(GetMessage(&msg, NULL, 0, 0))
{
      if (!TranslateAccelerator (hwnd, hAccel, &msg))
      {
           TranslateMessage (&msg) ;
           DispatchMessage (&msg) ;
      }
}


 

P先生关于它的说明是:

TranslateAccelerator函数将键盘消息翻译成WM_COMMAND或WM_SYSCOMMAND,当有键盘消息来的时候,该函数在加速键表中寻找句柄为hAccel的匹配值,如果找到匹配值,就会调用句柄为hwnd的窗口回调函数

 

你不需要其它代码来维护,这个函数帮你完成了"快捷键的映射"

 

 

***************************************************************************************************************

 

ok,代码大致讲述到此为止,还有很多细节不便在此细说,读者可以详细拜读我上传的源代码,内含详细注释

 

PS:可能你会发现我的程序在你的电脑上不能播放视频,这是因为你电脑上没有avi视频的解码器,MCI不能识别

解决方法就是安装我上传资源的XviD.rar中的解码程序

 

 

点击下载源代码及相应资源

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值