自己封装的CMusic类 【转】

http://www.cnblogs.com/zhangminaxiang/archive/2013/02/27/2936011.html

缘由:

  在改正俄罗斯方块程序的功能的时候,想给这个程序增加一个背景音乐。本想用PlayWave来做的,但想到这个功能十分常用,那还不如封装一个自己的CMusic

类,以备不时之需。本来以为很容易的,可是在真正操作的时候,却出现了一个问题,就是无法准确的知道什么时候音乐播放完成。问题的难道就在于,怎样将类的成员函数作为窗口的回调函数。

 原本用thunk来解决这个问题的,但是在解决的时候出现了一个问题,调试了好几天都没有解决。直到最近才解决。(也就是前一篇文章的由来)

代码:(前面定义的宏主要是解决Unicode问题)

cMusic.h

复制代码
  1 #ifndef CMUSIC_H
  2 #define CMUSIC_H
  3 
  4 #ifdef _UNICODE
  5 #define tstring wstring
  6 #define tcout wcout
  7 #define tcin wcin
  8 #else
  9 #define tstring string
 10 #define tcout cout
 11 #define tcin cin
 12 
 13 #endif
 14 
 15 #pragma warning(disable:4311)
 16 
 17 #include "TCHAR.h"
 18 #include<iostream>
 19 #include<windows.h>
 20 #include<string>
 21 #include<vector>
 22 #include<MMSystem.h>
 23 #pragma  comment(lib,"Winmm.lib")
 24 using namespace std;
 25 
 26 typedef LRESULT (*pfaCallBack)(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
 27 #pragma pack(push,1)
 28 struct Thunk
 29 {
 30     BYTE op_movecx;
 31     DWORD_PTR val_ecx;
 32     BYTE op_call;
 33     DWORD_PTR val_address;
 34 };
 35 #pragma pack(pop)
 36 
 37 #define MY_WM_PLAY WM_USER+1
 38 #define MY_WM_PAUSE WM_USER+2
 39 #define MY_WM_STOP WM_USER+3
 40 #define MY_WM_CLOSE WM_USER+4
 41 #define MY_WM_PLAYNEXT WM_USER+5
 42 #define MY_WM_PLAYLAST WM_USER+6
 43 #define MY_WM_REPLAY WM_USER+7
 44 #define MY_WM_PLAY_LOOP WM_USER+8
 45 #define MY_WM_RESUME WM_USER+9
 46 #define MY_WM_TEST0 WM_USER+10
 47 
 48 //类说明开始
 49 //=========================================================//
 50 // 功能:播放音乐以及进行相关的控制
 51 // 设计思路:
 52 //        这个类的实现应该会比较简单,主要是利用MCI开头的函数来进行控制
 53 //    最主要实现一下功能:
 54 //      播放一个音频文件
 55 //      暂停播放
 56 //      恢复播放
 57 //      得到音频文件的信息
 58 //      文件名  
 59 //      长度   
 60 //      当前播放的位置
 61 //      显示播放列表//一个文件夹中的所有MP3或者是wav文件
 62 //      播放上一首
 63 //      播放下一首
 64 //  
 65 // 作者:张敏
 66 // 日期:2013-1-10  邮箱 zhang19min88@163.com   
 67 // 注意:实现这个类我的最大的感想就是不要想在一个类中封装所有的函数 
 68 // 在真正要用的时候再进行继承
 69 //也许这样不会焦头乱额
 70 //=========================================================//
 71 class ZMCMusic
 72 {
 73 public:
 74     friend DWORD WINAPI ThreadProc(LPVOID);
 75 public:
 76     ZMCMusic();//构造函数
 77     ~ZMCMusic();//析构函数
 78 public:
 79     void Init();
 80     void AddPlayList(tstring tstrDir);
 81     BOOL Play();
 82     BOOL Pause();
 83     BOOL Resume();
 84     BOOL Stop();
 85     BOOL Close();
 86     BOOL Replay();
 87     BOOL PlayNext();//播放下一曲
 88     BOOL playLast();//播放上一曲
 89     BOOL GetFileInfo();
 90     BOOL LoadMusicFile(tstring const tstrFileNmae);
 91     static void ShowError();
 92 private:
 93     void GetCurPos();
 94     void GetFileLenth();
 95     int MakeWindow();//产生一个窗口
 96     int CreateWindowInThread();//在线程中创建窗口
 97     LRESULT ProcWindow(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);//窗口过程的处理函数
 98 private:
 99     tstring m_tstrFileName;
100     vector<tstring> m_vcPlayList;//保存播放列表
101     int m_nCurPlayIndex;//当前正在播放文件夹的索引
102     int m_nFileLen;//文件的总长度
103     int m_nCurPos;//当前正播放的位置
104     int m_nSound;//播放的音量大小
105 private:
106     HWND m_hWnd;
107     HANDLE m_hThread;
108     HINSTANCE m_hInstance;
109     UINT m_uDeviceID;
110     DWORD m_dwThreadID;
111     tstring m_tstrWinClassName;
112     tstring m_tstrWinCaptionName;
113 private:
114     void InitThunk()
115     {
116         m_thunk.op_movecx=0xB9;// 0xb9 mov ecx,数值的 机器码
117         m_thunk.val_ecx=(DWORD_PTR)this;
118         m_thunk.op_call=0xE9;//0xe9是Jmp 相对地址的机器码
119         DWORD_PTR off=0;
120         _asm
121         {
122             mov eax,ZMCMusic::ProcWindow
123             mov DWORD PTR[off],eax
124         }
125         m_thunk.val_address=off-((DWORD_PTR)(&m_thunk.val_address)+sizeof(DWORD_PTR));
126     }
127     pfaCallBack GetStaticEntry()
128     {
129         return (pfaCallBack)&m_thunk;
130     }
131 private:
132     Thunk m_thunk;
133 };
134 
135 #endif
复制代码

cMusic.cpp

复制代码
  1 #include "cMusic.h"
  2 //程序说明开始
  3 //=========================================================//
  4 // 功能:类的构造函数,由于本类需要 创建一个隐藏的窗口,用来接收
  5 //   播放完成之后的消息。所以在构造类的时候,很自然也需要构建一个
  6 //   隐藏的窗口
  7 // 参数:无
  8 // 返回 :无
  9 // 主要思路:
 10 //            初始化一些变量 并且调用createThread函数创建一个线程,并且在线程中
 11 // 创建一个窗口
 12 // 调用方法:系统自动调用
 13 // 作者:张敏
 14 // 日期:2012-1-11  邮箱 zhang19min88@163.com   
 15 // 说明:
 16 //=========================================================//
 17 ZMCMusic::ZMCMusic()
 18 {    
 19     m_uDeviceID=0;
 20     m_tstrFileName=_T("");
 21     m_tstrWinCaptionName=_T("MCI");
 22     m_tstrWinClassName=_T("CMCI");
 23     m_nSound=0;
 24     m_nFileLen=0;
 25     m_nCurPos=0;
 26     m_dwThreadID=0;
 27     m_nCurPlayIndex=0;
 28     m_hInstance=(HINSTANCE)GetModuleHandle(NULL);
 29     InitThunk();
 30 }
 31 void ZMCMusic::Init()
 32 {
 33     CreateWindowInThread();//在线程中创建一个窗口
 34 }
 35 ZMCMusic::~ZMCMusic()
 36 {
 37 
 38 }
 39 //程序说明开始
 40 //=========================================================//
 41 // 功能:加载需要播放的文件
 42 // 参数:tstrFileName 需要加载的文件名
 43 // 返回 :成功执行返回真 否则返回假
 44 // 主要思路:
 45 //            调用MCISendCommand函数 发送MCI_OPEN命令
 46 //  得到一个设备ID
 47 // 调用方法:外部接口函数
 48 // 作者:张敏
 49 // 日期:2013-1-10  邮箱 zhang19min88@163.com   
 50 // 说明:
 51 //=========================================================//
 52 BOOL ZMCMusic::LoadMusicFile(tstring const tstrFileNmae)
 53 {
 54     m_tstrFileName=tstrFileNmae;
 55     MCI_OPEN_PARMS mciOPenParms;
 56     DWORD dwReturn=0;
 57 
 58     mciOPenParms.lpstrDeviceType=_T("mpegvideo");//使用这种类型,可以播放MP3
 59     mciOPenParms.lpstrElementName=m_tstrFileName.c_str();//也就是播放的音频文件的路径名
 60     mciOPenParms.dwCallback=(DWORD_PTR)m_hWnd;//该命令成功执行后 想m_hWnd窗口发送一条消息
 61 
 62     dwReturn=mciSendCommand(0,MCI_OPEN,MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOPenParms);
 63     if(dwReturn!=0)
 64     {
 65         return FALSE;
 66     }//成功打开这个设备
 67     m_uDeviceID=mciOPenParms.wDeviceID;    //得到一个设备的ID号
 68 
 69     //MCI_STATUS_PARMS mciStatusParms;
 70     //ZeroMemory(&mciStatusParms,sizeof(mciStatusParms));
 71     //mciStatusParms.dwItem=MCI_STATUS_LENGTH;
 72     //if(mciSendCommand( m_uDeviceID , MCI_STATUS , MCI_STATUS_ITEM , (DWORD)(LPMCI_STATUS_PARMS) &mciStatusParms )==0 )
 73     //{
 74     //    m_nFileLen=mciStatusParms.dwReturn;
 75     //}
 76     return TRUE;
 77 }
 78 
 79 //程序说明开始
 80 //=========================================================//
 81 // 功能:播放加载了的音频文件
 82 // 参数:
 83 // 返回 :成功执行返回真 否则返回假
 84 // 主要思路:
 85 //            调用MCISendCommand函数 发送MCI_PLAY命令
 86 // 调用方法:外部接口函数
 87 // 作者:张敏
 88 // 日期:2013-2-26  邮箱 zhang19min88@163.com   
 89 // 说明:
 90 //     在这里并有处理MCI_NOTIFY消息,通过这个消息我们可以知道播放是否结束
 91 // 当歌曲播放完成之后 我们会收到一个播放完成的消息
 92 //=========================================================//
 93 BOOL ZMCMusic::Play()
 94 {
 95     //LoadMusicFile(m_vcPlayList[ m_nCurPlayIndex]);
 96     MCI_PLAY_PARMS mciPlayParms;
 97     ZeroMemory(&mciPlayParms,sizeof(mciPlayParms));
 98     mciPlayParms.dwCallback=(DWORD)m_hWnd;
 99     return mciSendCommand(m_uDeviceID,MCI_PLAY,MCI_NOTIFY,(DWORD)(LPVOID)&mciPlayParms);
100 }
101 //程序说明开始
102 //=========================================================//
103 // 功能:暂停当前播放的文件
104 // 参数:无
105 // 返回 :成功执行返回真 否则返回假
106 // 主要思路:
107 //            调用MCISendCommand函数 发送MCI_PAUSE命令
108 // 调用方法:外部接口函数
109 // 作者:张敏
110 // 日期:2012-1-10  邮箱 zhang19min88@163.com   
111 // 说明:
112 //     在这里并没有处理MCI_NOTIFY消息,通过这个消息我们可以知道播放是否结束
113 //=========================================================//
114 BOOL ZMCMusic::Pause()
115 {
116     MCI_GENERIC_PARMS mciGenericParms;
117     ZeroMemory(&mciGenericParms,sizeof(mciGenericParms));
118     mciGenericParms.dwCallback=(DWORD_PTR)m_hWnd;
119     return mciSendCommand(m_uDeviceID,MCI_PAUSE,MCI_WAIT,(DWORD)(LPVOID)&mciGenericParms);    
120 }
121 //程序说明开始
122 //=========================================================//
123 // 功能:继续播放当前被暂停播放的文件
124 // 参数:无
125 // 返回 :成功执行返回真 否则返回假
126 // 主要思路:
127 //            调用MCISendCommand函数 发送MCI_RESUME命令
128 // 调用方法:外部接口函数
129 // 作者:张敏
130 // 日期:2012-1-10  邮箱 zhang19min88@163.com   
131 // 说明:
132 //    
133 //=========================================================//
134 BOOL ZMCMusic::Resume()
135 {
136     MCI_GENERIC_PARMS mciGenericParms;
137     ZeroMemory(&mciGenericParms,sizeof(mciGenericParms));
138     return mciSendCommand(m_uDeviceID,MCI_RESUME,MCI_NOTIFY,(DWORD)(LPVOID)&mciGenericParms);    
139 }
140 //程序说明开始
141 //=========================================================//
142 // 功能:停止播放的文件
143 // 参数:无
144 // 返回 :成功执行返回真 否则返回假
145 // 主要思路:
146 //            调用MCISendCommand函数 发送MCI_STOP命令
147 // 调用方法:外部接口函数
148 // 作者:张敏
149 // 日期:2012-1-10  邮箱 zhang19min88@163.com   
150 // 说明:
151 //  这个命令和PAUSE是不同的 pause只是暂停播放,但播放的内容依然在内存中,可以继续播放
152 // 而STOP则是该文件退出资源 不能继续播放
153 //对于这个命令的确切理解MSDN上说 它和Pause的区别是看不同的设备来说的
154 //=========================================================//
155 BOOL ZMCMusic::Stop()
156 {
157     return mciSendCommand(m_uDeviceID,MCI_STOP,NULL,NULL);
158 }
159 //程序说明开始
160 //=========================================================//
161 // 功能:关闭播放设备
162 // 参数:无
163 // 返回 :成功执行返回真 否则返回假
164 // 主要思路:
165 //            调用MCISendCommand函数 发送MCI_CLOSE命令
166 // 调用方法:外部接口函数
167 // 作者:张敏
168 // 日期:2013-1-11  邮箱 zhang19min88@163.com   
169 // 说明:
170 //  这个命令和PAUSE是不同的 pause只是暂停播放,但播放的内容依然在内存中,可以继续播放
171 // 而STOP则是该文件退出资源 不能继续播放
172 //=========================================================//
173 BOOL ZMCMusic::Close()
174 {
175     return mciSendCommand(m_uDeviceID,MCI_CLOSE,NULL,NULL);
176 }
177 //程序说明开始
178 //=========================================================//
179 // 功能:重新播放
180 // 参数:无
181 // 返回 :成功执行返回真 否则返回假
182 // 主要思路:
183 //            调用CLose()函数 关闭设备 然后调用LoadMusicFile()函数打开设备 最后调用Play()函数进行播放
184 // 调用方法:外部接口函数
185 // 作者:张敏
186 // 日期:2013-2-27  邮箱 zhang19min88@163.com   
187 // 说明:
188 //=========================================================//
189 BOOL ZMCMusic::Replay()
190 {
191     Close();
192     LoadMusicFile(m_tstrFileName);
193     return    Play();
194 }
195 
196 
197 
198 int ZMCMusic::MakeWindow()
199 {
200     MSG stMsg;
201     TCHAR szClassName[]=_T("MCI");
202     
203     WNDCLASSEX stWC;
204     ZeroMemory(&stWC,sizeof(stWC));
205     stWC.hCursor=LoadCursor(NULL,IDC_ARROW);
206     stWC.cbSize=sizeof(stWC);
207     stWC.style=CS_HREDRAW|CS_VREDRAW;
208     stWC.lpfnWndProc=(WNDPROC)ZMCMusic::GetStaticEntry();//将类成员函数作为窗口过程函数
209     //stWC.lpfnWndProc=DefWindowProc;
210     stWC.lpszClassName=m_tstrWinClassName.c_str();
211     stWC.cbClsExtra=0;
212     stWC.hInstance=m_hInstance;
213 
214     RegisterClassEx(&stWC);
215     
216     m_hWnd=CreateWindowEx(WS_EX_CLIENTEDGE,m_tstrWinClassName.c_str(),m_tstrWinCaptionName.c_str(),WS_OVERLAPPEDWINDOW,100,100,600,700,NULL,NULL,m_hInstance,NULL);
217     if(m_hWnd==NULL)
218     {
219         ShowError();
220     }
221     ShowWindow(m_hWnd,SW_HIDE);
222     UpdateWindow(m_hWnd);
223     while(GetMessage(&stMsg,NULL,0,0))
224     {
225         TranslateMessage(&stMsg);
226         DispatchMessage(&stMsg);
227     }
228     return 0 ;    
229 }
230 
231 //程序说明开始
232 //=========================================================//
233 // 功能:窗口过程的处理函数
234 // 参数:hWNd uMsg wParam lParam 正常窗口回调函数
235 // 返回 :无
236 // 主要思路:
237 //        在这个回调函数中我们完成的就是处理MM_MCINOTIFY消息,主要是对MCI播放命令的执行结果进行响应
238 // 最关键的一个结果是通过这个消息的处理我们可以知道什么时候音乐播放完成
239 // 调用方法:系统自动调用
240 // 作者:张敏
241 // 日期:2012-1-11  邮箱 zhang19min88@163.com   
242 // 说明:
243 //=========================================================//
244 
245 //这个类该怎样利用还不是很清楚
246 LRESULT  ZMCMusic::ProcWindow(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
247 {    
248     switch(uMsg)
249     {
250     case WM_CREATE:
251     //    MessageBox(NULL,_T("MCI"),_T("MCI"),MB_OK);
252         break;
253     case MM_MCINOTIFY://当播放完成之后 
254         //在这里可以进行很多设置
255         //比喻说设定单曲循环
256         //设置自动播放下一首等等
257         //关键是如何用代码进行封装
258         //MessageBox(NULL,_T("MCI"),_T("Play End!"),MB_OK);
259         this->Replay();
260         break;
261     case MY_WM_PLAY:    break;
262     case MY_WM_PAUSE:break;
263     case MY_WM_STOP:break;
264     case MY_WM_RESUME:break;
265     case MY_WM_REPLAY:break;
266     case MY_WM_PLAYNEXT:break;
267     case MY_WM_PLAYLAST:break;
268     case MY_WM_PLAY_LOOP:break;
269     default:
270         return DefWindowProc(hWnd,uMsg,wParam,lParam);
271     }
272     return 0;
273 }
274 
275 //程序说明开始
276 //=========================================================//
277 // 功能:线程函数
278 //在这个函数中我们接受一个创建线程时的一个参数this 因为线程可以传递一个参数
279 // 在这个程序的处理过程中 我很好的解决了在内中调用线程的例子
280 // 以前遇到这种问题几次了,都是用一种不是很好的方式解决,今天算是搞清楚了
281 // 在类中创建线程,那么线程函数必须为全局函数,或者是静态函数,因为线程函数只能有一个参数,如果为成员函数,那么就会有一个默认的this
282 // 所以不行 我首先将它定义为友元函数,然后从线程函数中传递参数this这样就可以很好的解决这个问题了
283 // 参数:this指针
284 // 返回 :DWORD
285 // 主要思路:
286 //            调用类的方法创建一个隐藏的窗口
287 // 调用方法:系统自动调用
288 // 作者:张敏
289 // 日期:2012-1-11  邮箱 zhang19min88@163.com   
290 // 说明:
291 //=========================================================//
292 DWORD WINAPI ThreadProc(LPVOID lParam)
293 {    
294     ZMCMusic *pMusic=NULL;
295     pMusic=(ZMCMusic *)lParam;
296     return pMusic->MakeWindow();
297 }
298 
299 //程序说明开始
300 //=========================================================//
301 // 功能:启动一个新的线程来创建一个窗口
302 // 参数:无
303 // 返回 :int
304 // 主要思路:
305 //            创建一个新的线程
306 // 调用方法:系统自动调用
307 // 作者:张敏
308 // 日期:2012-1-11  邮箱 zhang19min88@163.com   
309 // 说明:
310 //=========================================================//
311 int ZMCMusic::CreateWindowInThread()
312 {
313     m_hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,(LPVOID)this,0,&m_dwThreadID);
314     WaitForSingleObject(m_hThread,500);
315     return 0;
316 }
317 
318 //程序说明开始
319 //=========================================================//
320 // 功能:输出最近一次的错误信息
321 // 返回 :成功执行返回真 否则返回假
322 // 主要思路:
323 //            调用InternetReadFile函数
324 // 调用方法:
325 // 作者:张敏
326 // 日期:2012-1-7  邮箱 zhang19min88@163.com   
327 // 说明:
328 //=========================================================//
329 void ZMCMusic::ShowError()
330 {
331 #define  ERROR_BUF 256
332     TCHAR szBuf[ERROR_BUF];
333     LPVOID lpMsgBuf;
334     DWORD dw=GetLastError();
335     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,dw,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR)&lpMsgBuf,0,NULL);
336     wsprintf(szBuf,_T("执行失败!错误码为:%d. 错误原因为:%s\n"),dw,lpMsgBuf);
337     MessageBox(NULL,szBuf,_T("错误"),MB_OK);
338 }
339 //程序说明开始
340 //=========================================================//
341 // 功能:得到文件当前播放的位置
342 // 返回 :无
343 // 主要思路:
344 //            发送MCI_STATUS命令获得
345 //   主要是得到状态
346 // 调用方法:
347 // 作者:张敏
348 // 日期:2012-1-7  邮箱 zhang19min88@163.com   
349 // 说明:
350 //=========================================================//
351 void ZMCMusic::GetCurPos()
352 {
353     MCI_STATUS_PARMS mciStatusParms;
354     mciStatusParms.dwItem=MCI_STATUS_POSITION;
355     if(mciSendCommand( m_uDeviceID , MCI_STATUS , MCI_STATUS_ITEM , (DWORD)(LPMCI_STATUS_PARMS) &mciStatusParms )==0 )
356     {
357         m_nCurPos=mciStatusParms.dwReturn;
358     }
359 }
360 //程序说明开始
361 //=========================================================//
362 // 功能:得到文件的长度
363 // 返回 :无
364 // 主要思路:
365 //            发送MCI_STATUS命令获得
366 //   主要是得到状态
367 // 调用方法:
368 // 作者:张敏
369 // 日期:2012-2-27  邮箱 zhang19min88@163.com   
370 // 说明:
371 //=========================================================//
372 void ZMCMusic::GetFileLenth()
373 {
374     MCI_STATUS_PARMS mciStatusParms;
375     mciStatusParms.dwItem=MCI_STATUS_LENGTH;//获得文件的长度
376     if(mciSendCommand( m_uDeviceID , MCI_STATUS , MCI_STATUS_ITEM , (DWORD)(LPMCI_STATUS_PARMS) &mciStatusParms )==0 )
377     {
378         m_nFileLen=mciStatusParms.dwReturn;
379     }
380 }
381 //程序说明开始
382 //=========================================================//
383 // 功能:将文件夹中的*.MP3文件和*.wav文件读取出来按照顺序添加到播放列表 
384 // 返回 :无
385 // 主要思路:
386 //            在文件夹中查找*.mp3和*.wav的文件,然后放在容器中
387 // 调用方法:
388 // 作者:张敏
389 // 日期:2012-1-7  邮箱 zhang19min88@163.com   
390 // 说明:
391 //=========================================================//
392 void ZMCMusic::AddPlayList(tstring tstrDir)
393 {
394     
395 }
复制代码

main.cpp

复制代码
 1 #include "cMusic.h"
 2 
 3 void ShowMenu()
 4 {
 5     tcout<<"Press 0 to EXIT"<<endl;
 6     tcout<<"Press 1 to PLAY"<<endl;
 7     tcout<<"Press 2 to PAUSE"<<endl;
 8     tcout<<"Press 3 to RESUSE"<<endl;
 9     tcout<<"Press 4 to STOP"<<endl;
10     tcout<<"Press 5 to FULLSCAN"<<endl;
11     tcout<<"Press 6 to CLOSE"<<endl;
12     tcout<<"Press 7 to REPALY"<<endl;
13     tcout<<"Press 8 to SHOWPOS"<<endl;
14     tcout<<"Press 9 to STOP"<<endl;
15     
16 }
17 int main()
18 {
19     tstring strFileName;
20     strFileName=_T("D:\\musicTest\\ifLove.mp3");
21 //    strFileName=_T("D:\\musicTest\\msg.mp3");
22         
23     ZMCMusic music;
24     music.Init();
25     //music.AddPlayList(strFileName);
26     music.LoadMusicFile(strFileName);
27     
28     int nKey=0;
29     bool bExit=false;
30     while(!bExit)
31     {
32         ShowMenu();
33         tcout<<_T("You Command:");
34         tcin>>nKey;
35         switch(nKey)
36         {
37             case 0:bExit=true;break;
38             case 1:music.Play();break;
39             case 2:music.Pause();break;
40             case 3:music.Resume();break;
41             //case 4:music.Stop();break;
42             case 6:music.Close();break;
43             case 7:music.Replay();break;
44             //case 8:SendMessage(g_hWnd,WM_CLOSE,NULL,NULL);break;
45             default:break;
46         }
47         Sleep(500);
48     }
49     return 0;
50 }
复制代码

运行结果:

注意:

这个类还有一些功能没有实现。

其中不是很理解PAUSE  STOP CLOSE 这三个命令的区别。还待以后研究……

posted on 2015-07-17 15:44  3D入魔  阅读(593)  评论(0编辑  收藏  举报