中年人学C语言Windows程序设计,35 WIN32图形界面音乐播放器
利用菜单类,滑块类,静态文本框构建一个音乐播放器,只能每次打开一个文件播放,下一期文章会加入播放列表。
音乐播放器V1版本界面如下
界面设计的思路
用menu构建出一个菜单,菜单上有5个功能
界面如上, 菜单栏有 打开,播放,暂停,停止和退出 5个菜单
然后在用户区显示播放信息
第一行为 播放进度信息,
最左侧 用static静态文本显示播放时间,
中间 用TRACKBAR_CLASS显示播放进度,
最右 侧static静态文本显示文件总大小,
下侧 用显示文件名称。
如下图:
点击打开文件 选择 音频文件
打开文件后,点击播放 开始播放文件
拖动进度条可以 改变音乐播放位置。
代码实例
//窗口调用程序
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
HDC hdcStatic;//字体句柄
PAINTSTRUCT ps;
//HINSTANCE hInst;
RECT rect;
TEXTMETRIC tm;//TEXTMETRIC 结构记录当前设备环境中有关字体的各种信息。
static TCHAR szBuffer[1024] = { 0 };
static TCHAR szBufInfo[1024] = { 0 };//缓存
static TCHAR szBufPos[1024]={ 0 };//缓存
static TCHAR szCmdPos;
//static TCHAR szStatusPre[1024] = { 0 };
//size_t iLength;//字符串长度
static long int llen;
static int m, s,mi,si;
static int cxChar, cHeighChar;
static HFONT hFont;//字体
static HWND hStatic, hStatus, hStatusPre;//静态文本框
static int cxClient, cyClient, cExternalLeading;
static HBRUSH hBrush; //画刷
static OPENFILENAME ofn;//openfilename
static HWND hwndPB, hSlider;//进度条
static TCHAR szFile[MAX_PATH];
static TCHAR slen[100];
TCHAR sPos[100];
long int lPos;
//TCHAR szCmd[1024];
static int flag = 0;
long int sliderPos;
switch (message)
{
case WM_SIZE:
{
hdc = GetDC(hWnd);
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
//ShowWindow(hStatus, SW_HIDE);
//解决静态static 文本重影的问题
//GetClientRect(hWnd, &rect);
MoveWindow(//拖动大小,改变进度条位置
hSlider,
6 * cxChar, 0,
cxClient - 12 * cxChar, cHeighChar*3/2 ,
TRUE);
MoveWindow(//拖动大小,改变位置
hStatusPre,
0, 0,
6 * cxChar, cHeighChar,
TRUE);
MoveWindow(//拖动大小,改变位置
hStatus,
cxClient-6 * cxChar, 0,
6 * cxChar, cHeighChar,
TRUE);
MoveWindow(//拖动大小,改变条位置
hStatic,
0, 2*cHeighChar,
cxClient, cyClient,
TRUE);
ReleaseDC(hWnd, hdc);
UpdateWindow(hWnd);//改变大小后更新窗口
break;
}
case WM_CREATE:
{
//创建字体微软雅黑
hFont = CreateFont(
-14/*高度*/, -7/*宽度*/, 0, 0, 400 /*一般这个值设为400*/,
FALSE/*不带斜体*/, FALSE/*不带下划线*/, FALSE/*不带删除线*/,
DEFAULT_CHARSET, //使用默认字符集
OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, //这行参数不用管
DEFAULT_QUALITY, //默认输出质量
FF_DONTCARE, //不指定字体族*/
TEXT("微软雅黑")); //字体名
//
//InitCommonControls(); // 确保已注册了进度条类PROGRESS_CLASS
hSlider = CreateWindow(TRACKBAR_CLASS, TEXT("Trackbar Control"),
WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS | TBS_BOTTOM,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hWnd, NULL,
((LPCREATESTRUCT)lParam)->hInstance ,NULL);
SendMessage(hSlider, TBM_SETRANGE,TRUE,MAKELONG(0, 100)); // 设置min. & max. positions
SendMessage(hSlider, TBM_SETPAGESIZE, 0, (LPARAM)5); //设置步长
//SendMessage(hSlider, TBM_SETTICFREQ, 10, 0); // new page size
SendMessage(hSlider, TBM_SETPOS,(WPARAM)TRUE, (LPARAM)0); //初始滑块位置 // redraw flag
//播放位置文字框
hStatusPre = CreateWindow(
TEXT("static"), //静态文本框的类名
szBufPos, //控件的文本
WS_CHILD /*子窗口*/ | WS_VISIBLE /*创建时显示*/ | SS_LEFT | SS_LEFTNOWORDWRAP/*垂直居中*/,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hWnd, //父窗口句柄
(HMENU)1, //为控件指定一个唯一标识符
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), //当前程序实例句柄
NULL);
//音频大小文字框
hStatus = CreateWindow(
TEXT("static"), //静态文本框的类名
szBufInfo, //控件的文本
WS_CHILD /*子窗口*/ | WS_VISIBLE /*创建时显示*/ | SS_LEFT | SS_LEFTNOWORDWRAP/*垂直居中*/,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hWnd, //父窗口句柄
(HMENU)1, //为控件指定一个唯一标识符
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), //当前程序实例句柄
NULL);
//音频文件文字框
hStatic = CreateWindow(
TEXT("static"), //静态文本框的类名
szBuffer, //控件的文本
WS_CHILD /*子窗口*/ | WS_VISIBLE /*创建时显示*/ | SS_LEFT | SS_LEFTNOWORDWRAP/*垂直居中*/,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hWnd, //父窗口句柄
(HMENU)2, //为控件指定一个唯一标识符
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), //当前程序实例句柄
NULL);
SendMessageW(hStatusPre, WM_SETFONT, (WPARAM)hFont, (LPARAM)NULL);
SendMessageW(hStatus, WM_SETFONT, (WPARAM)hFont, (LPARAM)NULL);
SendMessageW(hStatic, WM_SETFONT, (WPARAM)hFont, (LPARAM)NULL);
SetWindowText(hStatusPre, TEXT(" 00:00 "));
SetWindowText(hStatus, TEXT(" 00:00 "));
SetWindowText(hStatic, TEXT("欢迎使用音乐播放器"));
hdc = GetDC(hWnd);
//创建画刷
hBrush = CreateSolidBrush(RGB(0x00, 0x00, 0x00)); //黑色
GetTextMetrics(hdc, &tm);//GetTextMetrics 函数将当前字体的信息填充到指定缓冲区
cxChar = tm.tmAveCharWidth;//字体中小写字符的平均宽度(一般定义为字母 x 的宽度)
//cHeighChar = tm.tmHeight + tm.tmExternalLeading;
cHeighChar = tm.tmHeight+ tm.tmExternalLeading;//字符高度(tmAscent + tmDescent)
//打开openfile
ZeroMemory(&ofn, sizeof(ofn));//C语言中,结构体声明后必须要进行初始化结构体
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = szFile;//打开的文件的全路径
ofn.lpstrFile[0] = TEXT('\0');
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = TEXT("mp3\0*.mp3\0所有\0*.*\0");//格式
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.hwndOwner = hWnd;
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
ReleaseDC(hWnd, hdc);
SetTimer(hWnd, ID_TIMER, 1000, NULL);//设置计时器
break;
}
case WM_HSCROLL://点击进度条
sliderPos = SendMessage(hSlider, TBM_GETPOS, 0, 0);//获取当前位置
int msliderPos = sliderPos / 60;
int ssliderPos = sliderPos % 60;
TCHAR newCmd[100];
wsprintf(newCmd, TEXT("play sound from %ld"), sliderPos*1000);
mciSendString(newCmd, NULL, 0, NULL);//播放到当前位置
break;
case WM_PAINT://绘制用户区内的文字
hdc = BeginPaint(hWnd, &ps);//BeginPaint 函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。
GetClientRect(hWnd, &rect);
int x = rect.right;
int y = rect.bottom;
EndPaint(hWnd, &ps);
//ReleaseDC(hWnd, hdc);
break;
case WM_CTLCOLORSTATIC://设置静态文本框颜色
hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(255, 255, 255)); //字体白色
SetBkMode(hdcStatic, OPAQUE); //透明背景
SetBkColor(hdcStatic, RGB(0, 0, 0)); //设置字体背景为翠绿色
return (INT_PTR)hBrush; //这里必须返回画刷句柄
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDM_OPEN:
{
ExitMusic(fileName);
if (OpenMusic(ofn,fileName))
{
lstrcpy(szBuffer, fileName);
SetWindowText(hStatic, fileName);
llen = GetInfo(fileName);
m = llen / 60;//分
s = llen % 60;//秒
wsprintf(szBufInfo, TEXT(" %02d:%02d "),m,s);
SetWindowText(hStatus, szBufInfo); //显示文件总时长
SetWindowText(hStatusPre, TEXT(" 00:00 "));//显示当前播放位置
SendMessage(hSlider, TBM_SETRANGE, TRUE, MAKELONG(0, llen)); //重新设置范围 min. & max. positions
}
break;
}
case IDM_PLAY:
{
flag =PlayMusic(fileName);
break;
}
case IDM_PAUSE:
{
PauseMusic(fileName);
break;
}
case IDM_STOP:
StopMusic(fileName);
break;
case IDM_EXIT:
{
if (MessageBox(hWnd, TEXT("是否退出播放器"), TEXT(""), MB_YESNO | MB_ICONQUESTION) == IDYES)
ExitMusic(fileName);
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
}
break;
}
break;
case WM_TIMER://定时器程序每秒获取一次播放信息
{
if (flag)
{
mciSendString(TEXT("status sound position"), sPos, 100, 0);
lPos = _wtoi(sPos) / 1000;//测量出媒体长度,单位为秒,需要转化
SendMessage(hSlider, TBM_SETRANGE, TRUE, MAKELPARAM(0, llen)); //设置进度条的范围
SendMessage(hSlider, TBM_SETPOS, TRUE, lPos); //设置进度
mi = lPos / 60;//分
si = lPos % 60;//秒
wsprintf(szBufPos, TEXT(" %02d:%02d "), mi, si);
SetWindowText(hStatusPre, szBufPos);//显示当前位置
}
}
break;
case WM_CLOSE:
{
PostQuitMessage(0);
}
break;
case WM_DESTROY:
{
DeleteObject(hBrush);
KillTimer(hWnd, ID_TIMER);
DeleteObject(hFont);//删除创建的字体
DestroyWindow(hWnd);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}