1. 程式人生 > >MFC 基於VLC的視訊播放器(三)---介面設計以及對話方塊接受檔案的拖拽

MFC 基於VLC的視訊播放器(三)---介面設計以及對話方塊接受檔案的拖拽

北京時間23點11分 2018年12月20日

前面已經完成了vlc的環境的搭建,下面便開始真正的程式設計。

前面的介面是這樣的:

理想的介面應該是這樣的:

所以新增按鈕、進度條和播放列表控制元件,並且修改好ID。

介面設計完成,執行,還是隻是一個空殼,因為沒加任何處理函式。

接下來就要實現拖拽檔案或者資料夾到對話方塊時,自動新增路徑到播放列表控制元件上。

首先先把對話方塊屬性中的Accept Files設為TRUE,然後再設定訊息處理函式。

在類嚮導裡面新增檔案拖拽響應資訊

在OnDropFiles裡面新增一下處理函式

void CVlcPlayerCsdnDlg::OnDropFiles(HDROP hDropInfo)
{
	// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值

	UINT nFileCount = ::DragQueryFile(hDropInfo, (UINT)-1, NULL, 0);
	TCHAR        szFileName[_MAX_PATH] = _T("");
	CFileStatus  fStatus;
	CStringArray strArray;

	ShowPlaylist(TRUE);

	// 獲取拖拽進來檔案和資料夾
	for (UINT i = 0; i < nFileCount; i++)
	{
		// 獲取檔案路徑
		::DragQueryFile(hDropInfo, i, szFileName, sizeof(szFileName));
		CFile::GetStatus(szFileName, fStatus);

		// 是否為資料夾
		if (fStatus.m_attribute & FILE_ATTRIBUTE_DIRECTORY)
		{
			::SetCurrentDirectory(szFileName);  // 將當前目錄設定在此           
			EnumerateFiles(strArray);	        // 列舉目錄中所有檔案
		}
		else
		{
			strArray.Add(szFileName);
		}
	}

	// 過濾需要的檔案
	m_listPlay.SetRedraw(FALSE);
	m_listPlay.SetHorizontalExtent(1500); // 這裡只是簡單的設定為500寬度,若要剛好匹配路徑寬度,請參見msdn裡的例子

	for (int i = 0; i < strArray.GetCount(); i++)
	{
		if (IsWantedFile(strArray[i]))
		{
			m_listPlay.AddString(strArray[i]);
		}
	}

	m_listPlay.SetRedraw(TRUE);
	::DragFinish(hDropInfo);
	CDialog::OnDropFiles(hDropInfo);

}

其中,用到的m_listPlay變數為播放列表控制元件變數,m_listInfo為音訊顯示控制元件資訊的控制元件變數。

EnumerateFiles的函式定義為:

void EnumerateFiles(CStringArray &strArray)
{
	WIN32_FIND_DATA fd;
	HANDLE hFind = ::FindFirstFile(_T("*.*"), &fd);

	if (hFind != INVALID_HANDLE_VALUE)
	{
		do
		{
			// 如果為目錄
			if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				// 如果不為當前目錄.或上一層目錄..
				if (_tcscmp(fd.cFileName, _T(".")) && _tcscmp(fd.cFileName, _T("..")))
				{
					::SetCurrentDirectory(fd.cFileName);    // 進入該目錄
					EnumerateFiles(strArray);               // 遞迴列舉
					::SetCurrentDirectory(_T(".."));        // 返回該目錄上一層目錄
				}
			}
			// 如果為檔案
			else
			{
				CString strDir;
				TCHAR   lpDir[MAX_PATH];

				::GetCurrentDirectory(MAX_PATH, lpDir);
				strDir = lpDir;
				if (strDir.Right(1) != _T("\\"))
				{
					strDir += _T("\\");
				}
				strDir += fd.cFileName;

				strArray.Add(strDir);
			}
		} while (::FindNextFile(hFind, &fd));

		::FindClose(hFind);
	}
}

IsWantedFile的函式定義為:

BOOL IsWantedFile(const CString &str)
{
	CString strLower;
	TCHAR   szExt[_MAX_EXT] = _T("");

	const   CString STR_FileFilter =
		_T("*.rm;*.rmvb;*.flv;*.f4v;*.avi;*.3gp;*.mp4;*.wmv;*.mpeg;*.mpga;*.asf;*.dat;*.mov;*.mkv;*")
		_T("*.mp3;*.wma;*.wav;*.mid;*.rmi;*.aac;*.ac3;*.aiff;*.m4a;*.mka;*.mp2;*.ogg;*");

	_tsplitpath_s(str, NULL, 0, NULL, 0, NULL, 0, szExt, _MAX_EXT);   // 獲取字尾名
	strLower = szExt;
	strLower.MakeLower();

	if (!strLower.IsEmpty())    // 沒有後綴名的不符合條件
	{
		strLower += _T(";*");   // .mo不符合條件,由於會匹配到.mov,所以在後面加上【;*】來判斷是否完全匹配
		return -1 != STR_FileFilter.Find(strLower);
	}

	return FALSE;
}

ShowPlaylist的定義為:

void CVlcPlayerCsdnDlg::ShowPlaylist(BOOL bShow)
{
	CRect rcWnd, rcPlaylist;

	GetWindowRect(&rcWnd);
	m_listPlay.GetClientRect(&rcPlaylist);

	if (m_listPlay.IsWindowVisible() != bShow) // 只有顯示狀態發生變化時,才調整視窗大小
	{
		if (bShow)
		{
			SetWindowPos(NULL, 0, 0, rcWnd.Width() + rcPlaylist.Width(), rcWnd.Height(), SWP_NOMOVE);
		}
		else
		{
			SetWindowPos(NULL, 0, 0, rcWnd.Width() - rcPlaylist.Width(), rcWnd.Height(), SWP_NOMOVE);
		}
	}

	m_listPlay.ShowWindow(bShow ? SW_SHOW : SW_HIDE);
	m_listInfo.ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}

執行,如下:

最後的最後,再實現一下一開始隱藏播放列表的功能。

在初始化函式隱藏,程式碼為:

CRect rcWnd, rcPlaylist;
	GetWindowRect(&rcWnd);
	m_listPlay.GetClientRect(&rcPlaylist);

	SetWindowPos(NULL, 0, 0, rcWnd.Width() - rcPlaylist.Width() - GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXBORDER), rcWnd.Height() , SWP_NOMOVE);
	GetDlgItem(IDC_LIST_PLAY)->ShowWindow(SW_HIDE);
	GetDlgItem(IDC_LIST_MUSINFO)->ShowWindow(SW_HIDE);

好了,執行,播放列表已經隱藏:

拖拽如檔案後,播放列表再次顯示:

行了,執行完成!

程式碼已經上傳,你們可以看一下。下載地址

注意:1、本人是萌新,大佬們可以直接跳過閱讀我的文章,寫這個目的就是為了賺點分數以後可以用,當然也是想和其他萌新一起學習。

2、我會盡力快點更新,如果有什麼問題大家可以在底下評論,我看到便會回覆的,我的個人郵箱[email protected]

3、每一期我都會盡量放上原始碼,希望能幫到大家的學習。