C语言Windows下实现音乐播放器
前言
? ? ? ? 由于之前沒有開發過Windows下跑的exe程序,聽著歌,想著能不能用C語言寫一個windows跑的音樂播放器呢?
? ? ? ? 于是乎便開始探尋想法的可行性,難易程度,搜尋資料了解到,可以使用EasyX圖形庫做UI界面,而且學習成本不高,相對比較簡單,看看文檔示例很快就能入手;然后,播放聲音的話可以調用WinMM.lib,這個需要了解它的調用函數和操作指令,不需要全部了解,用到什么再去查什么,對癥下藥就行。
軟件工程下載鏈接
1. 工程建立
這里使用的是VS2022,組件使用C++的桌面開發,然后建立控制臺工程即可。
?EasyX是基于C++開發的,所以需要創建添加一個.cpp文件;
?EasyX提供了倆個 .lib庫,分別對應不同的字符集;
#ifndef __cplusplus
 #error EasyX is only for C++
 #endif
#ifdef UNICODE
 ?? ?#pragma comment(lib,"EasyXw.lib")
 #else
 ?? ?#pragma comment(lib,"EasyXa.lib")
 #endif
EasyX獲取
EasyX下載鏈接,去官網下載并安裝到vs中,然后把它的庫文件和頭文件復制到你的調用庫路徑下。
?WinMM.lib獲取
在Windows下搜索WinMM.lib,找到你對應的那一個添加進工程。
2. 實現效果展示
2.1? 效果圖片展示
????????音樂圖標找的有點丑,懶得換了,圖片沒做處理,可以看到白色背景色,主要要的是功能的實現,其它的能將就就將就著用。
中間左右綠色的兩個箭頭用于切換背景圖,還有顯示歌名、播放進度等......
2.2? 錄頻效果展示
點擊視頻鏈接
操作錄屏點擊的是對應圖標的區域,沒顯示點擊的鼠標。
EasyX也支持按鍵字符輸入功能,讓你的播放器錦上添花,這個功能這里沒去做。
3. 軟件設計框架
3.1 實現的功能框架
切換背景圖:把圖片添加到指定文件夾里,然后軟件實現到指定文件夾里搜索,把所有背景圖鏈接起來,就可以實現上下切換背景圖了;(下圖為我的工程文件夾)
添加音樂:把音樂添加到指定文件夾里,然后軟件實現到指定文件夾里搜索,把所有音樂都鏈接起來,并儲存音樂其它信息,就可以實現上下切換歌曲了;
鼠標事件:鼠標點擊獲取事件,執行相對應功能;
功能:歌曲播放、暫停;
? ? ? ? ? ?歌曲上、下曲選擇;
? ? ? ? ? ?歌曲名稱顯示;
? ? ? ? ? ?歌曲進度條、時間長度;
? ? ? ? ? ?歌曲音量加、減;
? ? ? ? ? ?歌曲快進、回退;
? ? ? ? ? ?歌曲循環/順序播放。
3.2 結構體設計
mouse_t?結構體獲取需要處理的功能事件,點擊對應的圖標,獲取對應的事件;
music_t?結構體存儲音樂信息:曲名、時間長度等;
image_t?結構體存儲圖片信息;
dir_t 結構體儲存文件夾絕對路徑;
home_t 結構體對應主界面的所有信息。
typedef enum _mouse_message{PLAY_PAUSE_HANDLE = 0, //播放暫停事件處理BK_ZUO_HANDLE,BK_YOU_HANDLE,VOL_UP_HANDLE,VOL_DOWN_HANDLE,NEXT_HANDLE,PREVIOUS_HANDLE,FAST_JIN_HANDLE,FAST_TUI_HANDLE,PLAY_WAY_HANDLE, //播放方式事件處理 }mouse_t;typedef struct _music {char name[48]; //歌名int music_index; //歌曲索引unsigned int music_len; //歌曲長度unsigned int cur_seek; //當前播放進度struct _music *pre;struct _music *next; }music_t;typedef struct _image {char image_name[48]; //圖片名int image_index; //圖片索引struct _image* pre;struct _image* next; }image_t;typedef struct _icon {IMAGE play_pause_icon;IMAGE fast_tui_icon;IMAGE fast_jin_icon;IMAGE previous_icon;IMAGE next_icon;IMAGE vol_up_icon;IMAGE vol_down_icon;IMAGE play_way_icon;IMAGE bk_zuo_icon;IMAGE bk_you_icon; }icon_t;typedef struct _dir {char main_dir[MAX_PATH]; //主目錄char mp3_dir[MAX_PATH]; //mp3目錄char bk_image_dir[MAX_PATH]; //image背景目錄char icon_image_dir[MAX_PATH]; //image-icon目錄 }dir_t;typedef struct __home_win {IMAGE home_img; //桌面背景dir_t dir; //目錄music_t *music; //歌單int play_state; //歌曲播放狀態bool is_repeat; //是否循環播放int music_count; //歌曲數目int music_vol; //音樂音量int current_music_index; //當前歌曲image_t* bk; //背景圖icon_t icon; //icon圖標int current_bk_index; //當前背景索引mouse_t mouse_m; //鼠標操作 }home_t;3.3 音頻播放指令
3.3.1 音頻調用函數
mciSendString 函數:
第一個參數:要發送的命令字符串。字符串結構是:[命令][設備別名][命令參數].
 第二個參數:返回信息的緩沖區,為一指定了大小的字符串變量.
 第三個參數:緩沖區的大小,就是字符變量的長度.
 第四個參數:回調方式,一般設為零
 返回值:函數執行成功返回零,否則返回錯誤代碼
3.3.2 open打開設備指令
open后面接的是音頻的路徑,可以是絕對路徑也可以是相對路徑,注意Windows下的路徑是反斜杠 ‘\’ 。
例如:mciSendString(“open music.mp3”, NULL, 0, NULL);
3.3.3 close 關閉設備指令
例如:mciSendString(“close music.mp3”, NULL, 0, NULL);
3.3.4 play 播放音頻指令
例如:mciSendString(“play music.mp3”, NULL, 0, NULL);
3.3.5 pause 暫停音頻指令
例如:mciSendString(“pause music.mp3”, NULL, 0, NULL);
3.3.6 resume 繼續音頻指令
例如:mciSendString(“resume music.mp3”, NULL, 0, NULL);
3.3.7 pause 暫停音頻指令
例如:mciSendString(“pause music.mp3”, NULL, 0, NULL);
3.3.8 repeat 循環音頻指令
例如:mciSendString(“play music.mp3 repeat”, NULL, 0, NULL);
3.3.9 status 查詢音頻狀態指令
例如:mciSendString(“status music.mp3 length”, buff, LEN, NULL);//獲取長度
mciSendString(“status music.mp3 position”, buff, LEN, NULL);//獲取位置
mciSendString(“status music.mp3 mode”, buff, LEN, NULL);//獲取工作模式
3.3.10 setaudio設置音量指令
例如:mciSendString(“setaudio music.mp3 volume to 200”, NULL, 0, NULL);
3.3.11? 指令示例代碼
/*********** 打開設備 **********/ void open_music_Cmd(music_t* music_p) {size_t name_len = 0;char cmd_buff[128] = "open ./mp3/";name_len = strlen(music_p->name)+1;snprintf(&cmd_buff[strlen(cmd_buff)], name_len, music_p->name);DEBUG("%s\n",cmd_buff);mciSendString(cmd_buff, NULL, 0, NULL); }3.4? 獲取鼠標事件
MouseHit():判斷是否有鼠標事件發生,
WM_LBUTTONUP:表示左鍵單擊抬起事件;相應的還有雙擊、右擊等其它事件,我只用到了左擊事件;getmessage()函數是一個阻塞函數,直到獲取鼠標信息為止;
這里調用相應的處理函數即可。鼠標有其它很多事件就不一一說明,可以查看EasyX在線文檔。
ExMessage mess; // 定義消息處理變量if (MouseHit()) {mess = getmessage(EX_MOUSE);switch (mess.message){case WM_LBUTTONUP:coord_handle(home_p, mess.x, mess.y);DEBUG("mouse event.\n");break;default:break;}}3.5? Windows下定時器功能
Windows下開啟一個周期定時器,間隔一定時間就去更新UI、信息狀態等。
由于我開啟的是周期定時器,所以全程不需要關閉它;否則回調完需要關閉該定時器。
timeSetEvent(500,0, (LPTIMECALLBACK)TimerCallback, NULL, TIME_PERIODIC); //開啟500ms的周期定時器
void WINAPI TimerCallback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)? ? //定時器回調函數
4 總代碼示例
這是我只適配了.mp3格式的音樂和.png格式的背景圖;
功能都是邊想邊加的,有些地方有點亂,沒去精簡。
/***************************************Fuction:c語言Windows下實現音樂播放功能*Author:Qurry*Date:12/14/2022*************************************/#include <stdio.h> #include <graphics.h> //圖形庫 #include <time.h> #include <conio.h> #include <mmsystem.h> //音頻 #include <io.h> #include <direct.h> //操作目錄函數 #include <string.h> #include <stdlib.h>#if 1 #define DEBUG printf #else #define DEBUG #endif#define LCD_WIDTH 1280 //屏寬 #define LCD_HEIGH 720 //屏高#define ICON_WIDTH 60 //icon寬 #define ICON_HEIGH 60 //icon高#define PLAY_PAUSE_COORD_X ((LCD_WIDTH/2)-(ICON_WIDTH/2)) #define PLAY_PAUSE_COORD_Y (LCD_HEIGH- (ICON_HEIGH*3)) #define PREVIOUS_COORD_X (PLAY_PAUSE_COORD_X - ICON_WIDTH -30) #define PREVIOUS_COORD_Y (LCD_HEIGH- (ICON_HEIGH*3)) #define NEXT_COORD_X (PLAY_PAUSE_COORD_X + ICON_WIDTH +30) #define NEXT_COORD_Y (LCD_HEIGH- (ICON_HEIGH*3)) #define PLAY_WAY_COORD_X (NEXT_COORD_X + ICON_WIDTH +30) #define PLAY_WAY_COORD_Y (LCD_HEIGH- (ICON_HEIGH*3)) #define VOL_UP_COORD_X (300) #define VOL_UP_COORD_Y ((LCD_HEIGH/2)+ICON_HEIGH) #define VOL_DOWN_COORD_X (VOL_UP_COORD_X) #define VOL_DOWN_COORD_Y (VOL_UP_COORD_Y+ICON_HEIGH+30) #define FAST_JIN_COORD_X (LCD_WIDTH - VOL_UP_COORD_X-ICON_WIDTH) #define FAST_JIN_COORD_Y (VOL_UP_COORD_Y) #define FAST_TUI_COORD_X (FAST_JIN_COORD_X) #define FAST_TUI_COORD_Y (VOL_DOWN_COORD_Y) #define BK_ZUO_COORD_X (30) #define BK_ZUO_COORD_Y ((LCD_HEIGH/2)-25) #define BK_YOU_COORD_X (LCD_WIDTH -BK_ZUO_COORD_X-50) #define BK_YOU_COORD_Y ((LCD_HEIGH/2)-25)typedef enum _mouse_message{PLAY_PAUSE_HANDLE = 0, //播放暫停事件處理BK_ZUO_HANDLE,BK_YOU_HANDLE,VOL_UP_HANDLE,VOL_DOWN_HANDLE,NEXT_HANDLE,PREVIOUS_HANDLE,FAST_JIN_HANDLE,FAST_TUI_HANDLE,PLAY_WAY_HANDLE, //播放方式事件處理 }mouse_t;typedef struct _music {char name[48]; //歌名int music_index; //歌曲索引unsigned int music_len; //歌曲長度unsigned int cur_seek; //當前播放進度struct _music *pre;struct _music *next; }music_t;typedef struct _image {char image_name[48]; //圖片名int image_index; //圖片索引struct _image* pre;struct _image* next; }image_t;typedef struct _icon {IMAGE play_pause_icon;IMAGE fast_tui_icon;IMAGE fast_jin_icon;IMAGE previous_icon;IMAGE next_icon;IMAGE vol_up_icon;IMAGE vol_down_icon;IMAGE play_way_icon;IMAGE bk_zuo_icon;IMAGE bk_you_icon; }icon_t;typedef struct _dir {char main_dir[MAX_PATH]; //主目錄char mp3_dir[MAX_PATH]; //mp3目錄char bk_image_dir[MAX_PATH]; //image背景目錄char icon_image_dir[MAX_PATH]; //image-icon目錄 }dir_t;typedef struct __home_win {IMAGE home_img; //桌面背景dir_t dir; //目錄music_t *music; //歌單int play_state; //歌曲播放狀態bool is_repeat; //是否循環播放int music_count; //歌曲數目int music_vol; //音樂音量int current_music_index; //當前歌曲image_t* bk; //背景圖icon_t icon; //icon圖標int current_bk_index; //當前背景索引mouse_t mouse_m; //鼠標操作 }home_t;int timer_per = 0; unsigned int music_seek[3] = { 420,0,0 }; void update_ui(home_t* home_p); void status_music_len_Cmd(music_t* music_p); void status_music_position_Cmd(music_t* music_p);/************************************** Fuction:獲取工程路徑* ***********************************/ void get_main_dir(home_t* home_p) {int buff_index = 0;int out_index = 0;char dir_buff[MAX_PATH];char dir_name[] = "\\\\";_getcwd(dir_buff,MAX_PATH);for (buff_index = 0; buff_index < strlen(dir_buff); buff_index++) {if (dir_buff[buff_index] == '\\') {home_p->dir.main_dir[out_index++] = dir_buff[buff_index];home_p->dir.main_dir[out_index++] = '\\';}else {home_p->dir.main_dir[out_index++] = dir_buff[buff_index];}}snprintf(&home_p->dir.main_dir[out_index],strlen(dir_name)+1,dir_name);DEBUG("main-dir:%s\n", home_p->dir.main_dir); }/********* 獲取mp3存放目錄 *********/ void get_mp3_dir(home_t* home_p ,const char* mp3_dir) {size_t main_dir_len = 0;main_dir_len = strlen(home_p->dir.main_dir);snprintf(home_p->dir.mp3_dir, main_dir_len+1, home_p->dir.main_dir);snprintf(&home_p->dir.mp3_dir[main_dir_len], strlen(mp3_dir)+1, mp3_dir);DEBUG("dir:%s\n", home_p->dir.mp3_dir); }/********* 獲取背景img存放目錄 *********/ void get_bk_image_dir(home_t* home_p, const char* img_dir) {size_t main_dir_len = 0;main_dir_len = strlen(home_p->dir.main_dir);snprintf(home_p->dir.bk_image_dir, main_dir_len + 1, home_p->dir.main_dir);snprintf(&home_p->dir.bk_image_dir[main_dir_len], strlen(img_dir) + 1, img_dir);DEBUG("bk-image-dir:%s\n", home_p->dir.bk_image_dir); }/********* 獲取icon-img存放目錄 *********/ void get_icon_image_dir(home_t* home_p, const char* img_dir) {size_t main_dir_len = 0;main_dir_len = strlen(home_p->dir.main_dir);snprintf(home_p->dir.icon_image_dir, main_dir_len + 1, home_p->dir.main_dir);snprintf(&home_p->dir.icon_image_dir[main_dir_len], strlen(img_dir) + 1, img_dir);DEBUG("icon-image-dir:%s\n", home_p->dir.icon_image_dir); }/********** 獲取.mp3后綴文件 ***********/ void get_all_mp3_file(home_t *home_p ,const char *mp3) {intptr_t fd; //文件頭struct _finddata_t file;music_t* music_p = NULL;music_t* music_p1 = NULL;if (_chdir(home_p->dir.mp3_dir)) { //切換到mp3目錄下DEBUG("change mp3-dir error!\n");return;}fd = _findfirst(mp3, &file); //找到第一個.mp3后綴的文件if (fd < 0) {DEBUG("No file!\n");if (_chdir(home_p->dir.main_dir)) { //返回主目錄DEBUG("change main-dir error!\n");}return;}while (1){if (home_p->music == NULL) {home_p->music = (music_t *)malloc(sizeof(music_t));if (home_p->music == NULL) {exit(-1);}snprintf(home_p->music->name, strlen(file.name) + 1, file.name); home_p->music->music_index = 1;DEBUG("%s,index:%d\n", home_p->music->name, home_p->music->music_index);home_p->music->music_len = 0;home_p->music->cur_seek = 0;home_p->music->pre = NULL;home_p->music->next = NULL;}else {music_p = (music_t*)home_p->music;while (music_p->next != NULL) {music_p = music_p->next;}music_p1 = (music_t*)malloc(sizeof(music_t));if (music_p1 == NULL) {exit(-1);}music_p->next = music_p1;snprintf(music_p1->name, strlen(file.name) + 1, file.name);music_p1->music_index = music_p->music_index + 1;DEBUG("%s,index:%d\n", music_p1->name, music_p1->music_index);music_p1->music_len = 0;music_p1->cur_seek = 0;music_p1->pre = music_p;music_p1->next = NULL;}home_p->music_count++;if (_findnext(fd, &file) != 0) {break;}}if (_chdir(home_p->dir.main_dir)) { //返回主目錄DEBUG("change main-dir error!\n");return;} }/*********** 顯示標題 ***********/ void show_title() {settextstyle(48, 28, "黑體");settextcolor(LIGHTBLUE);setbkmode(TRANSPARENT);outtextxy(LCD_WIDTH / 2 - 160, 30, "Music-Player"); }/*************** 顯示歌名 ***************/ void show_song_name(home_t* home_p) {music_t* music_p = NULL;settextstyle(32, 24, "黑體");settextcolor(YELLOW);setbkmode(TRANSPARENT);if (home_p->music == NULL) {return;}music_p = (music_t*)home_p->music;while (1) {if (home_p->current_music_index == music_p->music_index) {outtextxy((LCD_WIDTH/3)+90, LCD_HEIGH / 3, music_p->name);break;}if (music_p->next != NULL) {music_p = music_p->next;}else {break;}} }/************* 顯示歌曲進度 ************/ void show_music_time_schedule(home_t* home_p) {music_t* music_p = NULL;char min[8], sec[8];char time_point[] = ":";char show_buff[20];settextstyle(28, 20, "楷體");settextcolor(GREEN);setfillcolor(RED); //填充色setbkmode(TRANSPARENT);if (home_p->music == NULL) {return;}music_p = (music_t*)home_p->music;while (1) {if (home_p->current_music_index == music_p->music_index) {_itoa_s((music_p->music_len / 1000 / 60), min, 10); //分鐘_itoa_s((music_p->music_len / 1000 % 60), sec, 10); //秒鐘snprintf(show_buff,strlen(min)+1,min);snprintf(&show_buff[strlen(show_buff)], strlen(time_point) + 1, time_point);snprintf(&show_buff[strlen(show_buff)], strlen(sec) + 1, sec);outtextxy(1010,650, show_buff);fillrectangle(420,660, 1000,670);if (home_p->play_state == 1) {setfillcolor(GREEN);status_music_position_Cmd(music_p); //獲取當前歌曲進度music_seek[1] = music_p->cur_seek / 1000 ;music_seek[2] = music_p->music_len / 1000;music_seek[0] = 420 + (580 * music_seek[1] / music_seek[2]);fillrectangle(420, 660, music_seek[0], 670);}else {setfillcolor(GREEN);fillrectangle(420, 660, music_seek[0], 670);}break;}if (music_p->next != NULL) {music_p = music_p->next;}else {break;}} } /********** 獲取背景文件 ************/ void get_bk_image_file(home_t* home_p, const char* img) {intptr_t fd; //文件頭struct _finddata_t file;image_t* image_p = NULL;image_t* image_p1 = NULL;if (_chdir(home_p->dir.bk_image_dir)) {DEBUG("change bk-img-dir error!\n");return;}fd = _findfirst(img, &file);if (fd < 0) {DEBUG("No file!\n");if (_chdir(home_p->dir.main_dir)) { //返回主目錄DEBUG("change main-dir error!\n");}return;}while (1){if (home_p->bk == NULL) {home_p->bk = (image_t *)malloc(sizeof(image_t));if (home_p->bk == NULL) {exit(-1);}snprintf(home_p->bk->image_name, strlen(file.name) + 1, file.name);home_p->bk->image_index = 1;home_p->bk->pre = NULL;home_p->bk->next = NULL;DEBUG("%s,index:%d\n", home_p->bk->image_name, home_p->bk->image_index);}else {image_p = (image_t*)home_p->bk;while (image_p->next != NULL) {image_p = image_p->next;}image_p1 = (image_t *)malloc(sizeof(image_t));if (image_p1 == NULL) {exit(-1);}image_p->next = image_p1;snprintf(image_p1->image_name, strlen(file.name) + 1, file.name);image_p1->image_index = image_p->image_index + 1;image_p1->pre = image_p;image_p1->next = NULL;DEBUG("%s,index:%d\n", image_p1->image_name,image_p1->image_index);}if (_findnext(fd, &file) != 0) {break;}}if (_chdir(home_p->dir.main_dir)) { //返回主目錄DEBUG("change main-dir error!\n");return;} }/********** 加載背景 **********/ void load_img(home_t* home_p) {char img_dir[MAX_PATH];size_t len = 0;image_t* img = NULL;img = home_p->bk;while (1) {if (home_p->current_bk_index == img->image_index) {len = strlen(home_p->dir.bk_image_dir);snprintf(img_dir, len + 1, home_p->dir.bk_image_dir);snprintf(&img_dir[len], strlen(img->image_name)+ 1, img->image_name);DEBUG("load-bk-img:%s\n", img_dir);loadimage(&home_p->home_img, img_dir); //加載背景圖片putimage(0, 0, &home_p->home_img);break;}if (img->next != NULL) {img = img->next;}else {break;}} }void load_bk_zuo_icon(home_t* home_p, const char* icon_name, int x, int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.bk_zuo_icon, icon_dir); putimage(x, y, &home_p->icon.bk_zuo_icon); }void load_bk_you_icon(home_t* home_p, const char* icon_name, int x, int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.bk_you_icon, icon_dir);putimage(x, y, &home_p->icon.bk_you_icon); }void load_play_pause_icon(home_t* home_p,const char* icon_name,int x,int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.play_pause_icon, icon_dir); //加載play-iconputimage(x, y, &home_p->icon.play_pause_icon); }void load_previous_icon(home_t* home_p, const char* icon_name, int x, int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.previous_icon, icon_dir);putimage(x, y, &home_p->icon.previous_icon); }void load_next_icon(home_t* home_p, const char* icon_name, int x, int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.next_icon, icon_dir);putimage(x, y, &home_p->icon.next_icon); }void load_fast_jin_icon(home_t* home_p, const char* icon_name, int x, int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.fast_jin_icon, icon_dir);putimage(x, y, &home_p->icon.fast_jin_icon); }void load_fast_tui_icon(home_t* home_p, const char* icon_name, int x, int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.fast_tui_icon, icon_dir);putimage(x, y, &home_p->icon.fast_tui_icon); }void load_vol_up_icon(home_t* home_p, const char* icon_name, int x, int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.vol_up_icon, icon_dir);putimage(x, y, &home_p->icon.vol_up_icon); }void load_vol_down_icon(home_t* home_p, const char* icon_name, int x, int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.vol_down_icon, icon_dir);putimage(x, y, &home_p->icon.vol_down_icon); }void load_play_way_icon(home_t* home_p, const char* icon_name, int x, int y) {char icon_dir[MAX_PATH];size_t len = 0;if (icon_name == NULL) {return;}len = strlen(home_p->dir.icon_image_dir);snprintf(icon_dir, len + 1, home_p->dir.icon_image_dir);snprintf(&icon_dir[len], strlen(icon_name) + 1, icon_name);DEBUG("load-icon:%s\n", icon_dir);loadimage(&home_p->icon.play_way_icon, icon_dir);putimage(x, y, &home_p->icon.play_way_icon); }void load_all_icons(home_t* home_p) {if (home_p->play_state == 0 || home_p->play_state == 2|| home_p->play_state == 3) {load_play_pause_icon(home_p,"play.png", PLAY_PAUSE_COORD_X, PLAY_PAUSE_COORD_Y);}else if(home_p->play_state == 1) {load_play_pause_icon(home_p, "pause.png", PLAY_PAUSE_COORD_X, PLAY_PAUSE_COORD_Y);} load_previous_icon(home_p, "previous.png", PREVIOUS_COORD_X, PREVIOUS_COORD_Y);load_next_icon(home_p, "next.png", NEXT_COORD_X, NEXT_COORD_Y);if (home_p->is_repeat == false) {load_play_way_icon(home_p, "random.png", PLAY_WAY_COORD_X, PLAY_WAY_COORD_Y);}else {load_play_way_icon(home_p, "repeat.png", PLAY_WAY_COORD_X, PLAY_WAY_COORD_Y);}load_fast_jin_icon(home_p, "fast_jin.png", FAST_JIN_COORD_X, FAST_JIN_COORD_Y);load_fast_tui_icon(home_p, "fast_tui.png", FAST_TUI_COORD_X, FAST_TUI_COORD_Y);load_vol_up_icon(home_p, "vol_up.png", VOL_UP_COORD_X, VOL_UP_COORD_Y);load_vol_down_icon(home_p, "vol_down.png", VOL_DOWN_COORD_X, VOL_DOWN_COORD_Y);load_bk_zuo_icon(home_p, "bk_zuo.png", BK_ZUO_COORD_X, BK_ZUO_COORD_Y);load_bk_you_icon(home_p, "bk_you.png", BK_YOU_COORD_X, BK_YOU_COORD_Y); }/************* 上一張背景 ************/ void previous_bk_img(home_t* home_p) {image_t* image_p = NULL;if (home_p->bk == NULL) {return;}if (home_p->current_bk_index == 1) {return;}image_p = (image_t *)home_p->bk;while (1) { if (home_p->current_bk_index == image_p->image_index) {home_p->current_bk_index = image_p->pre->image_index;image_p = image_p->pre;update_ui(home_p);break;}if (image_p->next != NULL) {image_p = image_p->next;}else {break;}}}/************* 下一張背景 ************/ void next_bk_img(home_t* home_p) {image_t* image_p = NULL;if (home_p->bk == NULL) {return;}image_p = (image_t*)home_p->bk;while (image_p->next != NULL) {if (home_p->current_bk_index == image_p->image_index) {home_p->current_bk_index = image_p->next->image_index;image_p = image_p->next;update_ui(home_p);break;}image_p = image_p->next;} }/*********** 打開設備 **********/ void open_music_Cmd(music_t* music_p) {size_t name_len = 0;char cmd_buff[128] = "open ./mp3/";name_len = strlen(music_p->name)+1;snprintf(&cmd_buff[strlen(cmd_buff)], name_len, music_p->name);DEBUG("%s\n",cmd_buff);mciSendString(cmd_buff, NULL, 0, NULL); }/*********** 關閉設備 **********/ void close_music_Cmd(music_t* music_p) {size_t name_len = 0;char cmd_buff[128] = "close ./mp3/";name_len = strlen(music_p->name) + 1;snprintf(&cmd_buff[strlen(cmd_buff)], name_len, music_p->name);DEBUG("%s\n", cmd_buff);mciSendString(cmd_buff, NULL, 0, NULL); }/*********** 開始播放 **********/ void play_music_Cmd(music_t *music_p) {size_t name_len = 0;char cmd_buff[128] = "play ./mp3/";name_len = strlen(music_p->name)+1;snprintf(&cmd_buff[strlen(cmd_buff)], name_len, music_p->name);DEBUG("%s\n", cmd_buff);mciSendString(cmd_buff, NULL, 0, NULL); }/*********** 結束播放 **********/ void stop_music_Cmd(music_t* music_p) {size_t name_len = 0;char cmd_buff[128] = "stop ./mp3/";name_len = strlen(music_p->name) + 1;snprintf(&cmd_buff[strlen(cmd_buff)], name_len, music_p->name);DEBUG("%s\n", cmd_buff);mciSendString(cmd_buff, NULL, 0, NULL); }/*********** 暫停播放 **********/ void pause_music_Cmd(music_t* music_p) {size_t name_len = 0;char cmd_buff[128] = "pause ./mp3/";name_len = strlen(music_p->name)+1;snprintf(&cmd_buff[strlen(cmd_buff)], name_len, music_p->name);DEBUG("%s\n", cmd_buff);mciSendString(cmd_buff, NULL, 0, NULL); }/*********** 繼續播放 **********/ void resume_music_Cmd(music_t* music_p) {size_t name_len = 0;char cmd_buff[128] = "resume ./mp3/";name_len = strlen(music_p->name)+1;snprintf(&cmd_buff[strlen(cmd_buff)], name_len, music_p->name);DEBUG("%s\n", cmd_buff);mciSendString(cmd_buff, NULL, 0, NULL); }/************ 循環播放 ************/ void repeat_music_Cmd(music_t* music_p) {char cmd_buff[128] = "play ./mp3/";char repeat_buff[] = " repeat";char status_buff[64];snprintf(&cmd_buff[strlen(cmd_buff)], strlen(music_p->name) + 1, music_p->name);snprintf(&cmd_buff[strlen(cmd_buff)], strlen(repeat_buff) + 1, repeat_buff);DEBUG("cmd:%s\n", cmd_buff);mciSendString(cmd_buff, status_buff, 64, NULL); }/********** 獲取音樂長度 ************/ void status_music_len_Cmd(music_t* music_p) {char cmd_buff[128] = "status ./mp3/";char len_buff[] = " length";char status_buff[64];snprintf(&cmd_buff[strlen(cmd_buff)], strlen(music_p->name)+1, music_p->name);snprintf(&cmd_buff[strlen(cmd_buff)], strlen(len_buff) + 1, len_buff);DEBUG("status:%s\n", cmd_buff);mciSendString(cmd_buff, status_buff,64, NULL);music_p->music_len = atoi(status_buff);DEBUG("music_len:%d\n", music_p->music_len); }/********** 獲取音樂當前位置 ************/ void status_music_position_Cmd(music_t* music_p) {char cmd_buff[128] = "status ./mp3/";char addr_buff[] = " position";char status_buff[64];snprintf(&cmd_buff[strlen(cmd_buff)], strlen(music_p->name) + 1, music_p->name);snprintf(&cmd_buff[strlen(cmd_buff)], strlen(addr_buff) + 1, addr_buff);DEBUG("status:%s\n", cmd_buff);mciSendString(cmd_buff, status_buff, 64, NULL);music_p->cur_seek = atoi(status_buff);DEBUG("music_cur_addr:%d\n", music_p->cur_seek); }/********** 查詢工作模式 *************/ void status_music_mode_Cmd(music_t* music_p,char *sta_buff) {char cmd_buff[128] = "status ./mp3/";char mode_buff[] = " mode";snprintf(&cmd_buff[strlen(cmd_buff)], strlen(music_p->name) + 1, music_p->name);snprintf(&cmd_buff[strlen(cmd_buff)], strlen(mode_buff) + 1, mode_buff);DEBUG("status:%s\n", cmd_buff);mciSendString(cmd_buff, sta_buff, 32, NULL);DEBUG("music_mode:%s\n", sta_buff); }/********** 移動音樂播放位置 ***********/ void seek_music_Cmd(music_t* music_p,long int addr) {size_t name_len = 0;char temp[10];char cmd_buff[128] = "seek ./mp3/";char addr_buff[10] = " to ";long int postion = 0;status_music_position_Cmd(music_p);addr = music_p->cur_seek + addr;if (addr > music_p->music_len || addr <= 0)return;_itoa_s(addr,temp,10);name_len = strlen(music_p->name) + 1;snprintf(&cmd_buff[strlen(cmd_buff)], name_len, music_p->name);snprintf(&cmd_buff[strlen(cmd_buff)], strlen(addr_buff)+ 1, addr_buff);snprintf(&cmd_buff[strlen(cmd_buff)], strlen(temp)+ 1, temp);DEBUG("seek cmd:%s\n", cmd_buff);mciSendString(cmd_buff, NULL, 0, NULL); }/*********** 音樂音量 ************/ void volume_music_Cmd(music_t* music_p,int vol) {size_t name_len = 0;char cmd_buff[MAX_PATH] = "setaudio ./mp3/";char vol_buff[20] = " volume to ";char temp[6];_itoa_s(vol,temp,10);DEBUG("temp:%s\n", temp);snprintf(&vol_buff[strlen(vol_buff)],strlen(temp)+1,temp);DEBUG("temp1:%s\n", vol_buff);name_len = strlen(music_p->name);snprintf(&cmd_buff[strlen(cmd_buff)], name_len+1, music_p->name);snprintf(&cmd_buff[strlen(cmd_buff)], strlen(vol_buff) + 1, vol_buff);DEBUG("%s\n", cmd_buff);mciSendString(cmd_buff, NULL, 0, NULL); }/********** 設置音量 ***********/ void set_music_vol(home_t* home_p) {music_t* music_p = NULL;if (home_p->music == NULL) {return;}music_p = (music_t*)home_p->music;while (1) {if (home_p->current_music_index == music_p->music_index) {volume_music_Cmd(music_p, home_p->music_vol);break;}if (music_p->next != NULL) {music_p = music_p->next;}else {break;}} }/*********** 移動音頻播放位置 **********/ void set_seek_music(home_t* home_p,long int addr) {music_t* music_p = NULL;if (home_p->music == NULL){return;}music_p = (music_t*)home_p->music;while (1) {if (home_p->current_music_index == music_p->music_index) {pause_music_Cmd(music_p);seek_music_Cmd(music_p,addr);if (home_p->is_repeat) {repeat_music_Cmd(music_p);}else {play_music_Cmd(music_p);}break;}if (music_p->next != NULL) {music_p = music_p->next;}else {break;}} }/************* 上一首 *************/ void previous_music(home_t* home_p) {music_t *music_p = NULL;if (home_p->music == NULL) {return;}if (home_p->current_music_index == 1) {return;}music_p = (music_t *)home_p->music;while (1) {if (home_p->current_music_index == music_p->music_index) {home_p->current_music_index = music_p->pre->music_index;close_music_Cmd(music_p);music_p = music_p->pre;open_music_Cmd(music_p);if (home_p->is_repeat == true) {repeat_music_Cmd(music_p);}else {play_music_Cmd(music_p);}if (music_p->music_len == 0) {status_music_len_Cmd(music_p);} set_music_vol(home_p);home_p->play_state = 1;load_play_pause_icon(home_p, "pause.png", PLAY_PAUSE_COORD_X, PLAY_PAUSE_COORD_Y);break;}if (music_p->next != NULL) {music_p = music_p->next;}else {break;} } }/************* 下一首 *************/ void next_music(home_t* home_p) {music_t* music_p = NULL;if (home_p->music == NULL) {return;}music_p = (music_t*)home_p->music;while (music_p->next != NULL) {if (home_p->current_music_index == music_p->music_index) {home_p->current_music_index = music_p->next->music_index;close_music_Cmd(music_p);music_p = music_p->next;open_music_Cmd(music_p);if (home_p->is_repeat == true) {repeat_music_Cmd(music_p);}else {play_music_Cmd(music_p);}if (music_p->music_len == 0) {status_music_len_Cmd(music_p);}set_music_vol(home_p);home_p->play_state = 1;load_play_pause_icon(home_p, "pause.png", PLAY_PAUSE_COORD_X, PLAY_PAUSE_COORD_Y);break;}music_p = music_p->next;} }/********** 播放暫停 **********/ void play_pause_music(home_t* home_p) {music_t* music_p = NULL;if (home_p->music == NULL) {return;}music_p = (music_t*)home_p->music;while (1) {if (home_p->current_music_index == music_p->music_index) {if (home_p->play_state == 1) {pause_music_Cmd(music_p);load_play_pause_icon(home_p, "play.png", PLAY_PAUSE_COORD_X, PLAY_PAUSE_COORD_Y);home_p->play_state = false;}else if (home_p->play_state == 2) {close_music_Cmd(music_p);open_music_Cmd(music_p);if (home_p->is_repeat) {repeat_music_Cmd(music_p);}else {play_music_Cmd(music_p);}load_play_pause_icon(home_p, "pause.png", PLAY_PAUSE_COORD_X, PLAY_PAUSE_COORD_Y);home_p->play_state = 1;}else if(home_p->play_state == 3) {resume_music_Cmd(music_p);if (music_p->music_len == 0) {status_music_len_Cmd(music_p);}load_play_pause_icon(home_p, "pause.png", PLAY_PAUSE_COORD_X, PLAY_PAUSE_COORD_Y);home_p->play_state = 1;}break;}if (music_p->next != NULL) {music_p = music_p->next;}else {break;}} }/************* 設置循環 *************/ void set_repeat_music(home_t* home_p) {music_t* music_p = NULL;if (home_p->music == NULL) {return;}music_p = (music_t*)home_p->music;while (1) {if (home_p->current_music_index == music_p->music_index) {if (home_p->is_repeat == true) {home_p->is_repeat = false;}else {home_p->is_repeat = true;//repeat_music_Cmd(music_p);}update_ui(home_p);break;}if (music_p->next != NULL) {music_p = music_p->next;}else {break;}} }/*********** 獲取工作模式 ***********/ void get_music_mode(home_t* home_p) {char mode[32] = "";music_t* music_p = NULL;if (home_p->music == NULL) {return;}music_p = (music_t*)home_p->music;while (1) {if (home_p->current_music_index == music_p->music_index) {status_music_mode_Cmd(music_p,mode);if (strcmp(mode, "playing") == 0) {home_p->play_state = 1;}else if (strcmp(mode, "stopped") == 0) {if ((home_p->current_music_index != home_p->music_count)&&(home_p->is_repeat == false)&&(home_p->play_state != 0)) {next_music(home_p);home_p->play_state = 1;}else {home_p->play_state = 2;}}else if (strcmp(mode, "paused") == 0) {home_p->play_state = 3;}break;}if (music_p->next != NULL) {music_p = music_p->next;}else {break;}}} /************* 鼠標點擊坐標處理 *************/ void coord_handle(home_t* home_p, int x,int y) {int coord_x = x, coord_y = y;if ((coord_x > PLAY_PAUSE_COORD_X) && (coord_x < PLAY_PAUSE_COORD_X + ICON_WIDTH) &&(coord_y > PLAY_PAUSE_COORD_Y) && (coord_y < PLAY_PAUSE_COORD_Y + ICON_HEIGH)) {play_pause_music(home_p);}else if ((coord_x > PREVIOUS_COORD_X) && (coord_x < (PREVIOUS_COORD_X + ICON_WIDTH)) &&(coord_y > PREVIOUS_COORD_Y) && (coord_y < (PREVIOUS_COORD_Y + ICON_HEIGH))){previous_music(home_p);}else if ((coord_x > NEXT_COORD_X) && (coord_x < NEXT_COORD_X + ICON_WIDTH) &&(coord_y > NEXT_COORD_Y) && (coord_y < NEXT_COORD_Y + ICON_HEIGH)) {next_music(home_p);}else if ((coord_x > PLAY_WAY_COORD_X) && (coord_x < PLAY_WAY_COORD_X + ICON_WIDTH) &&(coord_y > PLAY_WAY_COORD_Y) && (coord_y < PLAY_WAY_COORD_Y + ICON_HEIGH)) {set_repeat_music(home_p);}else if ((coord_x > VOL_UP_COORD_X) && (coord_x < VOL_UP_COORD_X + ICON_WIDTH) &&(coord_y > VOL_UP_COORD_Y) && (coord_y < VOL_UP_COORD_Y + ICON_HEIGH)) {if (home_p->music_vol < 1000) {home_p->music_vol += 50;}set_music_vol(home_p);}else if ((coord_x > VOL_DOWN_COORD_X) && (coord_x < VOL_DOWN_COORD_X + ICON_WIDTH) &&(coord_y > VOL_DOWN_COORD_Y) && (coord_y < VOL_DOWN_COORD_Y + ICON_HEIGH)) {if (home_p->music_vol > 0) {home_p->music_vol -= 50;}set_music_vol(home_p);}else if ((coord_x > FAST_JIN_COORD_X) && (coord_x < FAST_JIN_COORD_X + ICON_WIDTH) &&(coord_y > FAST_JIN_COORD_Y) && (coord_y < FAST_JIN_COORD_Y + ICON_HEIGH)) {set_seek_music(home_p,10000);}else if ((coord_x > FAST_TUI_COORD_X) && (coord_x < FAST_TUI_COORD_X + ICON_WIDTH) &&(coord_y > FAST_TUI_COORD_Y) && (coord_y < FAST_TUI_COORD_Y + ICON_HEIGH)) {set_seek_music(home_p, -10000);}else if ((coord_x > BK_ZUO_COORD_X) && (coord_x < BK_ZUO_COORD_X + ICON_WIDTH) &&(coord_y > BK_ZUO_COORD_Y) && (coord_y < BK_ZUO_COORD_Y + ICON_HEIGH-10)) {previous_bk_img(home_p);}else if ((coord_x > BK_YOU_COORD_X) && (coord_x < BK_YOU_COORD_X + ICON_WIDTH) &&(coord_y > BK_YOU_COORD_Y) && (coord_y < BK_YOU_COORD_Y + ICON_HEIGH - 10)) {next_bk_img(home_p);}else{DEBUG("No handle!\n");} }/*********** 鼠標事件 ************/ void mouse_event_thread(home_t* home_p) {ExMessage mess; // 定義消息處理變量if (MouseHit()) {mess = getmessage(EX_MOUSE);switch (mess.message){case WM_LBUTTONUP:coord_handle(home_p, mess.x, mess.y);DEBUG("mouse event.\n");break;default:break;}} }/********** 初始化數據 ***********/ void init_data(home_t *home_p) {home_p->home_img = NULL;home_p->music = NULL;home_p->bk = NULL;home_p->music_vol = 800;home_p->play_state = 0;home_p->is_repeat = false;home_p->music_count = 0;home_p->current_bk_index = 1;home_p->current_music_index = 1; }/********* 初始化所有文件目錄 ***********/ void init_all_dir(home_t* home_p) {get_main_dir(home_p);get_mp3_dir(home_p, "mp3\\\\");get_bk_image_dir(home_p, "images\\\\bk\\\\");get_icon_image_dir(home_p, "images\\\\icon\\\\"); }/********** 初始化所有文件 ***********/ void init_all_file(home_t *home_p) {get_all_mp3_file(home_p, "*.mp3");get_bk_image_file(home_p, "*.jpg"); }/************ 初始化播放器窗口 **********/ void init_music_play_window(home_t* home_p,int width,int high) {initgraph(width, high); // 初始化圖形模式 setbkcolor(WHITE);load_img(home_p);load_all_icons(home_p);show_title(); }/********* 初始化播放器設置 ***********/ void init_music_settings(home_t* home_p) {if (home_p->music == NULL) {return;}open_music_Cmd(home_p->music);pause_music_Cmd(home_p->music);set_music_vol(home_p); status_music_position_Cmd(home_p->music); }/********* 更新界面 *********/ void update_ui(home_t* home_p) {BeginBatchDraw();cleardevice();load_img(home_p);load_all_icons(home_p);show_title();show_song_name(home_p);show_music_time_schedule(home_p);EndBatchDraw(); }/*********** UI事件 **********/ void ui_event(home_t* home_p) {Sleep(5);if (timer_per == 1) {get_music_mode(home_p);update_ui(home_p);timer_per = 0;} }/********** windows定時器回調函數 **********/ void WINAPI TimerCallback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) {if (timer_per == 0) {timer_per = 1;} }int main() {home_t home_win;home_t* home_win_p = &home_win;int timer_id = 0; //定時器句柄init_data(home_win_p);init_all_dir(home_win_p);init_all_file(home_win_p); init_music_settings(home_win_p);init_music_play_window(home_win_p,LCD_WIDTH,LCD_HEIGH);timer_id = timeSetEvent(500,0, (LPTIMECALLBACK)TimerCallback, NULL, TIME_PERIODIC); //開啟500ms的周期定時器if (timer_id == NULL) {DEBUG("Timer set error!\n");}while (1){mouse_event_thread(home_win_p); //鼠標事件ui_event(home_win_p); //UI更新}return 0; }5 總結
? ? ? ? 學習過程中,我們需要養成遇到問題,就想各種辦法去尋找答案的習慣,然后吸取精華,而不是輕易放棄,如果真的無法解決,那就把問題放一放,改天再看或許會有更新奇的思路。
? ? ? ? 我平時開發的一些原代碼都會無條件的分享出來,如果覺得寫的還不錯的,希望可以點個關注,哪怕只是一個點贊,Haha......
總結
以上是生活随笔為你收集整理的C语言Windows下实现音乐播放器的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 清华大学文件服务器,UserFiles深
- 下一篇: 关于iOS APP设置启动图片
