C++ music player: the use of MCI library

I've been busy working on projects recently, and I haven't posted an article for a long time. Okay, let's not talk nonsense

1. Project display

insert image description here

The functions of this music player are clear at a glance, and functions can also be added. Interested masters study and study

2. Key technologies

The whole program mainly realizes the following functions:
1) Volume and playback progress control
2) Top window
3) Basic playback and pause functions

1. Play pause

First, open a file selection dialog box, then get the path of the music file, and play it with the help of the mciSendCommand() function

First look at the MCI_PLAY_PARMS structure on MSDN for playing music

typedef struct {
DWORD_PTR dwCallback;
DWORD dwFrom;
DWORD dwTo;
} MCI_PLAY_PARMS;

dwCallback: The low-order word specifies the window handle for the MCI_NOTIFY flag.
dwFrom: The position to play from.
dwTo: The position to play.

Several MCI commands

MCI_PAUSE Pause
MCI_RESUME Continue playing
MCI_PLAY Play
MCI_OPEN Open
MCI_STATUS Get current duration
MCI_STOP Stop
MCI_CLOSE Close

These commands need to use the mciSendCommand () function
mciSendCommand function to send a command message to the specified MCI device.

MCIERROR mciSendCommand(
MCIDEVICEID IDDevice,
UINT uMsg,
DWORD_PTR fdwCommand,
DWORD_PTR dwParam
);

IDDevice : The device identifier of the MCI device to receive the command message. This parameter is not used with the MCI_OPEN command message.
uMsg : Command message. For a list, see Multimedia Commands.
fdwCommand: Flags for command messages.
dwParam : Pointer to a structure containing command message parameters.

upper code

//打开
void CMusicPlayerDlg::OnBnClickedBtnChoose()
{
    
    
	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, L"MP3文件(*.mp3)|*.mp3|WMA文件(*.wma)|*.wma|WAV文件(*.wav)|*.wav|所有文件(*.*)|*.*||");
	if (IDCANCEL == dlg.DoModal())
	{
    
    
		return;
	}

	//获取路径
	CString strMusicFile = dlg.GetPathName();
	SetDlgItemText(IDC_EDIT_NAME, strMusicFile);
	

	//打开
	MCI_OPEN_PARMS mciOpenParms;
	mciOpenParms.lpstrElementName = strMusicFile;

	MCIERROR mcierror = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_ELEMENT | MCI_WAIT, (DWORD)&mciOpenParms);
	if (mcierror)
	{
    
    
		wchar_t szErrorMsg[256];
		//获取错误信息
		mciGetErrorString(mcierror, szErrorMsg, 256);
		MessageBox(szErrorMsg, L"音乐播放器");
		return;
	}
	StopMusic();//清除 循环播放
	m_DeviceID = mciOpenParms.wDeviceID;
	//调用函数自动播放
	OnBnClickedBtnPlay();
}

//播放
void CMusicPlayerDlg::OnBnClickedBtnPlay()
{
    
    
	MCI_PLAY_PARMS mciPlayParms;
	mciPlayParms.dwCallback = NULL;
	mciPlayParms.dwFrom = 0;
	mciSendCommand(m_DeviceID, MCI_PLAY, MCI_FROM | MCI_NOTIFY, (DWORD)&mciPlayParms);


	GetDlgItem(IDC_BTN_PAUSE)->EnableWindow(TRUE);
	GetDlgItem(IDC_SLIDER_MUSIC)->EnableWindow(TRUE);
	GetDlgItem(IDC_SLIDER_VOLUME)->EnableWindow(TRUE);
	//获取总长度
	CString strLength;
	MCI_STATUS_PARMS mciStatusParms;
	mciStatusParms.dwItem = MCI_STATUS_LENGTH;
	mciSendCommand(m_DeviceID, MCI_STATUS, MCI_WAIT | MCI_STATUS_ITEM, (DWORD)&mciStatusParms);
	int m_dLength = mciStatusParms.dwReturn;
	
	int minute = 0;//分
	int second = m_dLength / 1000;//秒
	if (second >= 60)
	{
    
    
		minute = second / 60;
		second = second - (60 * minute);
		strLength.Format(L"%d:%d", minute, second);
	}



	m_Silder.SetRange(0, m_dLength);
	SetDlgItemText(IDC_EDIT_END, strLength);

	SetTimer(1, 200, NULL);//计时器
}
//暂停
void CMusicPlayerDlg::OnBnClickedBtnCause()
{
    
    
	
	CString str;
	GetDlgItemText(IDC_BTN_PAUSE, str);
	if (str == L"暂停")
	{
    
    
		mciSendCommand(m_DeviceID, MCI_PAUSE, 0, 0);
		SetDlgItemText(IDC_BTN_PAUSE, L"继续");
	}
	else if (str == L"继续")
	{
    
    
		mciSendCommand(m_DeviceID, MCI_RESUME, 0, 0);
		SetDlgItemText(IDC_BTN_PAUSE, L"暂停");
	}
}

It is divided into three functions here, which are convenient to call later, and a timer is also set, mainly for the playback duration function later

2. Window top

Not much to say, the code

//置顶
void CMusicPlayerDlg::OnBnTopWin()
{
    
    
	//CButton* pBtn = (CButton*)GetDlgItem(IDC_CHECK1);
	//int state = pBtn->GetCheck();
	int state= m_TopWin.GetCheck();
	if (state == 1)
	{
    
    
		::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
	}
	else
	{
    
    
		::SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
	}
}

3. Volume playback progress

Simple MFC operation

//计时器
void CMusicPlayerDlg::OnTimer(UINT_PTR nIDEvent)
{
    
    
	switch (nIDEvent)
	{
    
    
	case 1:
		CString str;
		MCI_STATUS_PARMS mciStatusParms;
		mciStatusParms.dwItem = MCI_STATUS_POSITION;
		mciSendCommand(m_DeviceID, MCI_STATUS, MCI_WAIT | MCI_STATUS_ITEM, (DWORD)&mciStatusParms);
		int m_dPosition = mciStatusParms.dwReturn;
		int minute = 0;//分
		int second = m_dPosition / 1000;//秒
		str.Format(L"%d:%d", minute, second);
		if (second >= 60)
		{
    
    
			minute = second / 60;
			second = second - (60 * minute);
			str.Format(L"%d:%d", minute, second);
		}
		m_Silder.SetPos(m_dPosition);
		SetDlgItemText(IDC_EDIT_START, str);
		break;
	}
	
	CDialogEx::OnTimer(nIDEvent);
}

//进度条
void CMusicPlayerDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    
    
	int nId = pScrollBar->GetDlgCtrlID();
	int nPostion;
	int nVolume;
	if (nId == IDC_SLIDER_MUSIC)
	{
    
    
		nPostion = m_Silder.GetPos();
		MCI_PLAY_PARMS mciPlayParms;
		mciPlayParms.dwFrom = nPostion;
		mciSendCommand(m_DeviceID, MCI_PLAY, MCI_FROM, (DWORD)&mciPlayParms);
	}
	else if (nId == IDC_SLIDER_VOLUME)
	{
    
    
		nVolume = m_Volume.GetPos();
		MCI_DGV_SETAUDIO_PARMS mciSetVolume;
		mciSetVolume.dwItem = MCI_DGV_SETAUDIO_VOLUME;
		mciSetVolume.dwValue = nVolume;
		mciSendCommand(m_DeviceID, MCI_SETAUDIO, MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_ITEM, (DWORD)&mciSetVolume);
	}
	
	CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}

Well, share a complete project link
https://fow.lanzouw.com/iHmEE07oga9c

Password: 96vp

Thank you, follow me

Guess you like

Origin blog.csdn.net/m0_47563648/article/details/125715659