引用:http://www.easyx.cn/skills/View.aspx?id=6
本文講解怎樣將 mp3 等音樂資源以資源形式嵌入 exe 文件中,並通過 mciSendString 調用。嵌入 mp3 和嵌入圖片略有不同,將圖片嵌入到 exe 中,以及訪問嵌入 exe 中的圖片,請參考:http://www.easyx.cn/skills/View.aspx?id=6
【一、以資源文件形式嵌入 exe】
關於“資源文件”的介紹和“將 mp3 以資源形式嵌入 exe 文件中”的步驟,請仿照 http://www.easyx.cn/skills/View.aspx?id=6。
【二、播放資源文件中的 mp3】
1. 思路
查看 MSDN 中關於 mciSendString 的使用,發現並不支持直接讀取資源文件中的媒體文件,也不支持讀取內存中的媒體文件。因此,我們需要提取資源
文件中的 mp3 為成臨時文件,然后調用 mciSendString 播放,播放結束后再刪掉這個臨時文件。
2. 提取資源文件中的為臨時文件
這個步驟不算復雜,只需要將資源文件中的資源讀取到內存中,然后將內存數據寫入文件即可。針對資源 ID 為字符串和宏兩種形式,核心代碼如下:
1 ////////////////////////////////////////////////////////////////// 2 // 提取指定模塊中的資源文件 3 // 參數: 4 // strDstFile: 目標文件名。提取的資源將保存在這里; 5 // strResType: 資源類型; 6 // strResName: 資源名稱; 7 // 返回值: 8 // true: 執行成功; 9 // false: 執行失敗。 10 bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName) 11 { 12 // 創建文件 13 HANDLE hFile = ::CreateFile(strDstFile, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); 14 if (hFile == INVALID_HANDLE_VALUE) 15 return false; 16 17 // 查找資源文件中、加載資源到內存、得到資源大小 18 HRSRC hRes = ::FindResource(NULL, strResName, strResType); 19 HGLOBAL hMem = ::LoadResource(NULL, hRes); 20 DWORD dwSize = ::SizeofResource(NULL, hRes); 21 22 // 寫入文件 23 DWORD dwWrite = 0; // 寫入大小 24 ::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL); 25 ::CloseHandle(hFile); 26 27 return true; 28 }
3. 使用 mciSendString 播放音樂
這一步利用第 2 步導出的文件名,直接用 mciSendString 播放。mciSendString 的使用方法請參考:http://www.easyx.cn/skills/View.aspx?id=44
4. 刪除臨時文件
臨時文件如果不再使用,請及時刪除。可以使用 windows api 函數 DeleteFile。
【三、范例 1】
下面是一個完整的范例項目,該項目中有一個 "MP3" 類型的資源文件,資源 ID 為字符串 "background.mp3",播放這個 mp3 的范例代碼如下:
1 /////////////////////////////////////////////////// 2 // 程序名稱:范例:播放以資源形式保存的 mp3 音樂 3 // 編譯環境:Visual C++ 6.0 / 2010,EasyX 2011驚蟄版 4 // 作 者:yangw80 <yw80@qq.com> 5 // 最后修改:2011-10-7 6 // 7 #include <graphics.h> 8 #include <conio.h> 9 #include <stdio.h> 10 #pragma comment(lib, "Winmm.lib") // 引用 Windows Multimedia API 11 // #include "resource.h" // 注:如果資源 ID 為宏定義,請取消這行注釋 12 13 14 ////////////////////////////////////////////////////////////////// 15 // 提取指定模塊中的資源文件 16 // 參數: 17 // strDstFile: 目標文件名。提取的資源將保存在這里; 18 // strResType: 資源類型; 19 // strResName: 資源名稱; 20 // 返回值: 21 // true: 執行成功; 22 // false: 執行失敗。 23 bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName) 24 { 25 // 創建文件 26 HANDLE hFile = ::CreateFile(strDstFile, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); 27 if (hFile == INVALID_HANDLE_VALUE) 28 return false; 29 30 // 查找資源文件中、加載資源到內存、得到資源大小 31 HRSRC hRes = ::FindResource(NULL, strResName, strResType); 32 HGLOBAL hMem = ::LoadResource(NULL, hRes); 33 DWORD dwSize = ::SizeofResource(NULL, hRes); 34 35 // 寫入文件 36 DWORD dwWrite = 0; // 返回寫入字節 37 ::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL); 38 ::CloseHandle(hFile); 39 40 return true; 41 } 42 43 44 // 主函數 45 void main() 46 { 47 // 初始化圖形窗口 48 initgraph(640, 480); 49 50 // 輸出提示信息 51 outtextxy(0, 0, _T("按任意鍵開始播放")); 52 _getch(); 53 54 // 產生臨時文件的文件名 55 TCHAR tmpmp3[_MAX_PATH]; 56 ::GetTempPath(_MAX_PATH, tmpmp3); 57 _tcscat(tmpmp3, _T("testapp_background.mp3")); // VC2008、VC2010 請用 _tcscat_s 函數 58 59 // 將 MP3 資源提取為臨時文件 60 ExtractResource(tmpmp3, _T("MP3"), _T("background.mp3")); 61 // 注:如果 MP3 資源的 ID 為宏 IDR_BACKGROUND,這樣做: 62 // ExtractResource(tmpmp3, _T("MP3"), MAKEINTRESOURCE(IDR_BACKGROUND)); 63 64 // 打開音樂 65 TCHAR mcicmd[300]; 66 _stprintf(mcicmd, _T("open \"%s\" alias mymusic"), tmpmp3); // VC2008、VC2010 請用 _stprintf_s 函數 67 mciSendString(mcicmd, NULL, 0, NULL); 68 69 // 播放音樂 70 mciSendString(_T("play mymusic"), NULL, 0, NULL); 71 72 // 輸出提示信息 73 outtextxy(0, 0, _T("按任意鍵停止播放")); 74 _getch(); 75 76 // 停止播放並關閉音樂 77 mciSendString(_T("stop mymusic"), NULL, 0, NULL); 78 mciSendString(_T("close mymusic"), NULL, 0, NULL); 79 80 // 刪除臨時文件 81 DeleteFile(tmpmp3); 82 83 // 輸出提示信息 84 outtextxy(0, 0, _T("按任意鍵退出程序")); 85 _getch(); 86 87 // 關閉圖形窗口 88 closegraph(); 89 }