重构媒体库文件夹标签页,修正搜索状态下的许多问题

This commit is contained in:
lrisora
2023-09-21 20:05:41 +08:00
parent eadf251a0f
commit f2683559ae
6 changed files with 365 additions and 408 deletions
+2 -16
View File
@@ -208,7 +208,7 @@ BEGIN_MESSAGE_MAP(CMusicPlayerDlg, CMainDialogBase)
ON_COMMAND(ID_TRANSLATE_TO_SIMPLIFIED_CHINESE, &CMusicPlayerDlg::OnTranslateToSimplifiedChinese)
ON_COMMAND(ID_TRANSLATE_TO_TRANDITIONAL_CHINESE, &CMusicPlayerDlg::OnTranslateToTranditionalChinese)
ON_COMMAND(ID_ALBUM_COVER_SAVE_AS, &CMusicPlayerDlg::OnAlbumCoverSaveAs)
ON_MESSAGE(WM_PATH_SELECTED, &CMusicPlayerDlg::OnPathSelected)
// ON_MESSAGE(WM_PATH_SELECTED, &CMusicPlayerDlg::OnPathSelected)
ON_MESSAGE(WM_CONNOT_PLAY_WARNING, &CMusicPlayerDlg::OnConnotPlayWarning)
ON_EN_CHANGE(IDC_SEARCH_EDIT, &CMusicPlayerDlg::OnEnChangeSearchEdit)
//ON_BN_CLICKED(IDC_CLEAR_SEARCH_BUTTON, &CMusicPlayerDlg::OnBnClickedClearSearchButton)
@@ -2903,20 +2903,6 @@ void CMusicPlayerDlg::OnSetPath()
}
afx_msg LRESULT CMusicPlayerDlg::OnPathSelected(WPARAM wParam, LPARAM lParam)
{
PathInfo* pPathInfo = (PathInfo*)wParam;
if (pPathInfo != nullptr)
{
CPlayer::GetInstance().SetPath(*pPathInfo);
//m_findDlg.ClearFindResult(); //更换路径后清除查找结果
SetTimer(DELAY_TIMER_ID, 500, NULL); //在媒体库对话框中选择了一个文件夹播放后,500毫秒内不响应WM_LBUTTONUP消息
m_no_lbtnup = true;
}
return 0;
}
void CMusicPlayerDlg::OnFind()
{
// TODO: 在此添加命令处理程序代码
@@ -6220,7 +6206,7 @@ afx_msg LRESULT CMusicPlayerDlg::OnMainWindowActivated(WPARAM wParam, LPARAM lPa
void CMusicPlayerDlg::OnContainSubFolder()
{
// TODO: 在此添加命令处理程序代码
CPlayer::GetInstance().SetContainSubFolder(!CPlayer::GetInstance().IsContainSubFolder());
CPlayer::GetInstance().SetContainSubFolder();
}
-1
View File
@@ -370,7 +370,6 @@ public:
afx_msg void OnTranslateToTranditionalChinese();
afx_msg void OnAlbumCoverSaveAs();
protected:
afx_msg LRESULT OnPathSelected(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnConnotPlayWarning(WPARAM wParam, LPARAM lParam);
public:
afx_msg void OnEnChangeSearchEdit();
+19 -19
View File
@@ -989,10 +989,10 @@ void CPlayer::SaveRecentInfoToFiles(bool save_playlist)
#pragma region 列表初始化方法
void CPlayer::SetPath(const PathInfo& path_info)
bool CPlayer::SetPath(const PathInfo& path_info, bool play)
{
if (m_loading) return;
if (!GetPlayStatusMutex().try_lock_for(std::chrono::milliseconds(1000))) return;
if (m_loading) return false;
if (!GetPlayStatusMutex().try_lock_for(std::chrono::milliseconds(1000))) return false;
m_loading = true;
IniPlayerCore();
@@ -1017,7 +1017,8 @@ void CPlayer::SetPath(const PathInfo& path_info)
m_index = path_info.track;
m_current_position.fromInt(path_info.position);
IniPlayList();
IniPlayList(play);
return true;
}
bool CPlayer::OpenFolder(wstring path, bool contain_sub_folder, bool play)
@@ -1262,10 +1263,10 @@ bool CPlayer::AddSongsToPlaylist(const vector<SongInfo>& songs)
return added;
}
void CPlayer::ReloadPlaylist(bool refresh_info)
bool CPlayer::ReloadPlaylist(bool refresh_info)
{
if (m_loading) return;
if (!GetPlayStatusMutex().try_lock_for(std::chrono::milliseconds(1000))) return;
if (m_loading) return false;
if (!GetPlayStatusMutex().try_lock_for(std::chrono::milliseconds(1000))) return false;
m_loading = true;
IniPlayerCore();
@@ -1282,6 +1283,17 @@ void CPlayer::ReloadPlaylist(bool refresh_info)
m_current_position.fromInt(0);
IniPlayList(false, true);
return true;
}
bool CPlayer::SetContainSubFolder()
{
m_contain_sub_folder = !m_contain_sub_folder;
if (!IsPlaylistMode())
{
return ReloadPlaylist(false);
}
return true; // 播放列表模式返回true
}
#pragma endregion 列表初始化方法
@@ -2709,18 +2721,6 @@ bool CPlayer::IsFfmpegCore() const {
return m_pCore ? m_pCore->GetCoreType() == PT_FFMPEG : false;
}
void CPlayer::SetContainSubFolder(bool contain_sub_folder)
{
if (m_contain_sub_folder != contain_sub_folder)
{
m_contain_sub_folder = contain_sub_folder;
if (!IsPlaylistMode())
{
ReloadPlaylist(false);
}
}
}
void CPlayer::UpdateControlsMetadata(SongInfo info)
{
m_controls.UpdateDuration(info.length().toInt());
+6 -5
View File
@@ -288,8 +288,8 @@ public:
#pragma region 列表初始化方法
// 切换到指定路径的文件夹模式,没有PathInfo时应使用CPlayer::OpenFolder
void SetPath(const PathInfo& path_info);
// 切换到指定路径的文件夹模式,没有PathInfo时应使用CPlayer::OpenFolder(没能取得播放状态锁返回false)
bool SetPath(const PathInfo& path_info, bool play = false);
// 切换到指定路径的播放列表模式/通过“打开文件夹”来设置路径的处理
// (不进行“切换播放列表时继续播放”)(没能取得播放状态锁返回false)
bool OpenFolder(wstring path, bool contain_sub_folder = false, bool play = false);
@@ -318,8 +318,10 @@ public:
// 向当前播放列表添加歌曲,仅在播放列表模式可用,如果一个都没有添加,则返回false,否则返回true
bool AddSongsToPlaylist(const vector<SongInfo>& songs);
// 重新载入播放列表
void ReloadPlaylist(bool refresh_info = true);
// 重新载入播放列表(没能取得播放状态锁返回false)
bool ReloadPlaylist(bool refresh_info = true);
// 翻转是否包含子文件夹设置,如果当前为文件夹模式则直接重新加载播放列表(没能取得播放状态锁返回false)
bool SetContainSubFolder();
#pragma endregion 列表初始化方法
@@ -506,7 +508,6 @@ public:
bool IsFfmpegCore() const;
bool IsFileOpened() const { return m_file_opend; }
bool IsContainSubFolder() const { return m_contain_sub_folder; }
void SetContainSubFolder(bool contain_sub_folder);
MediaTransControls m_controls;
+291 -314
View File
@@ -14,7 +14,7 @@
IMPLEMENT_DYNAMIC(CSetPathDlg, CTabDlg)
CSetPathDlg::CSetPathDlg(CWnd* pParent /*=NULL*/)
: CTabDlg(IDD_SET_PATH_DIALOG, pParent), m_recent_path(CPlayer::GetInstance().GetRecentPath())
: CTabDlg(IDD_SET_PATH_DIALOG, pParent)
{
}
@@ -25,12 +25,16 @@ CSetPathDlg::~CSetPathDlg()
void CSetPathDlg::QuickSearch(const wstring & key_word)
{
m_search_result.clear();
for (size_t i{}; i < m_recent_path.size(); i++)
{
if (CCommon::StringFindNoCase(m_recent_path[i].path, key_word) != wstring::npos)
m_search_result.push_back(i);
}
// 多用只读引用将来重构RecentPath多线程轻松一些
const deque<PathInfo>& recent_path = CPlayer::GetInstance().GetRecentPath();
m_path_list_info.clear();
m_search_result.clear();
for (size_t i{}; i < recent_path.size(); ++i)
{
m_path_list_info.push_back(recent_path[i]);
if (CCommon::StringFindNoCase(recent_path[i].path, key_word) != wstring::npos)
m_search_result.push_back(i);
}
}
void CSetPathDlg::AdjustColumnWidth()
@@ -44,155 +48,167 @@ void CSetPathDlg::AdjustColumnWidth()
void CSetPathDlg::RefreshTabData()
{
ShowPathList();
SetButtonsEnable(IsSelectedPlayEnable());
SetButtonsEnable();
}
void CSetPathDlg::ShowPathList()
bool CSetPathDlg::SelectValid() const
{
m_path_list.EnableWindow(TRUE);
if (!m_searched) //显示所有项目
{
m_path_list.DeleteAllItems();
CString path_str;
for (size_t i{}; i < m_recent_path.size(); i++)
{
CString str;
str.Format(_T("%d"), i + 1);
m_path_list.InsertItem(i, str);
SetListRowData(i, m_recent_path[i]);
}
}
else //只显示搜索结果的曲目
{
if (m_search_result.empty())
{
m_path_list.DeleteAllItems();
m_path_list.InsertItem(0, _T(""));
m_path_list.SetItemText(0, 1, CCommon::LoadText(IDS_NO_RESULT_TO_SHOW));
m_path_list.EnableWindow(FALSE);
return;
}
int item_num_before = m_path_list.GetItemCount();
int item_num_after = m_search_result.size();
//如果当前列表中项目的数量小于原来的,则直接清空原来列表中所有的项目,重新添加
if (item_num_after < item_num_before)
{
m_path_list.DeleteAllItems();
item_num_before = 0;
}
CString str;
for (int i{}; i < item_num_after; i++)
{
str.Format(_T("%u"), m_search_result[i] + 1);
if (i >= item_num_before) //如果当前列表中的项目数量大于之前的数量,则需要在不够时插入新的项目
{
m_path_list.InsertItem(i, str);
}
m_path_list.SetItemText(i, 0, str);
SetListRowData(i, m_recent_path[m_search_result[i]]);
}
}
size_t index{ m_list_selected };
if (m_searched && index >= 0 && index < m_search_result.size())
index = m_search_result[index];
return index >= 0 && index < m_path_list_info.size();
}
void CSetPathDlg::SetButtonsEnable(bool enable)
PathInfo CSetPathDlg::GetSelPath() const
{
//GetDlgItem(IDOK)->EnableWindow(enable);
//GetDlgItem(IDC_DELETE_PATH_BUTTON)->EnableWindow(enable);
if (SelectValid())
if (m_searched)
return m_path_list_info[m_search_result[m_list_selected]];
else
return m_path_list_info[m_list_selected];
else
return PathInfo();
}
bool CSetPathDlg::SelectedCanPlay() const
{
return SelectValid() && (CPlayer::GetInstance().IsPlaylistMode() || GetSelPath().path != CPlayer::GetInstance().GetCurrentDir2());
}
void CSetPathDlg::SetButtonsEnable()
{
bool enable = SelectedCanPlay();
CWnd* pParent = GetParentWindow();
if (pParent != nullptr)
::SendMessage(pParent->GetSafeHwnd(), WM_PLAY_SELECTED_BTN_ENABLE, WPARAM(enable), 0);
}
void CSetPathDlg::ShowPathList()
{
m_path_list.EnableWindow(TRUE);
if (!m_searched) //显示所有项目
{
// 这里的更新m_path_list_info操作本应有独立方法不过暂时还不必要,先放这里
m_path_list_info.clear();
const deque<PathInfo>& recent_path = CPlayer::GetInstance().GetRecentPath();
std::copy(recent_path.begin(), recent_path.end(), std::back_inserter(m_path_list_info));
m_path_list.DeleteAllItems();
CString path_str;
for (size_t i{}; i < m_path_list_info.size(); i++)
{
CString str;
str.Format(_T("%d"), i + 1);
m_path_list.InsertItem(i, str);
SetListRowData(i, m_path_list_info[i]);
}
}
else //只显示搜索结果的曲目
{
if (m_search_result.empty())
{
m_path_list.DeleteAllItems();
m_path_list.InsertItem(0, _T(""));
m_path_list.SetItemText(0, 1, CCommon::LoadText(IDS_NO_RESULT_TO_SHOW));
m_path_list.EnableWindow(FALSE);
return;
}
int item_num_before = m_path_list.GetItemCount();
int item_num_after = m_search_result.size();
//如果当前列表中项目的数量小于原来的,则直接清空原来列表中所有的项目,重新添加
if (item_num_after < item_num_before)
{
m_path_list.DeleteAllItems();
item_num_before = 0;
}
CString str;
for (int i{}; i < item_num_after; i++)
{
str.Format(_T("%u"), m_search_result[i] + 1);
if (i >= item_num_before) //如果当前列表中的项目数量大于之前的数量,则需要在不够时插入新的项目
{
m_path_list.InsertItem(i, str);
}
m_path_list.SetItemText(i, 0, str); // 设置序号
SetListRowData(i, m_path_list_info[m_search_result[i]]);
}
}
}
void CSetPathDlg::CalculateColumeWidth(vector<int>& width)
{
CRect rect;
m_path_list.GetWindowRect(rect);
width.resize(7);
CRect rect;
m_path_list.GetWindowRect(rect);
width.resize(7);
width[3] = rect.Width() / 12;
width[4] = width[5] = rect.Width() / 10;
width[6] = rect.Width() / 8;
width[4] = width[5] = rect.Width() / 10;
width[6] = rect.Width() / 8;
width[0] = theApp.DPI(40);
width[1] = rect.Width() / 4;
width[2] = rect.Width() - width[1] - width[3] - width[4] - width[5] - width[6] - width[0] - theApp.DPI(20) - 1;
width[0] = theApp.DPI(40);
width[1] = rect.Width() / 4;
width[2] = rect.Width() - width[1] - width[3] - width[4] - width[5] - width[6] - width[0] - theApp.DPI(20) - 1;
}
void CSetPathDlg::SetListRowData(int index, const PathInfo & path_info)
{
CFilePathHelper path_helper(path_info.path);
m_path_list.SetItemText(index, 1, path_helper.GetFolderName().c_str());
m_path_list.SetItemText(index, 2, path_info.path.c_str());
CFilePathHelper path_helper(path_info.path);
m_path_list.SetItemText(index, 1, path_helper.GetFolderName().c_str());
m_path_list.SetItemText(index, 2, path_info.path.c_str());
if (path_info.contain_sub_folder)
m_path_list.SetItemText(index, 3, CCommon::LoadText(IDS_YES));
else
m_path_list.SetItemText(index, 3, _T(""));
CString str;
str.Format(_T("%d"), path_info.track + 1);
m_path_list.SetItemText(index, 4, str);
CString str;
str.Format(_T("%d"), path_info.track + 1);
m_path_list.SetItemText(index, 4, str);
str.Format(_T("%d"), path_info.track_num);
m_path_list.SetItemText(index, 5, str);
str.Format(_T("%d"), path_info.track_num);
m_path_list.SetItemText(index, 5, str);
Time total_time{ path_info.total_time };
m_path_list.SetItemText(index, 6, total_time.toString3().c_str());
}
bool CSetPathDlg::IsSelectedPlayEnable() const
{
return !m_recent_path.empty() && SelectValid() && (GetSelPath().path != CPlayer::GetInstance().GetCurrentDir2() || CPlayer::GetInstance().IsPlaylistMode());
Time total_time{ path_info.total_time };
m_path_list.SetItemText(index, 6, total_time.toString3().c_str());
}
void CSetPathDlg::OnTabEntered()
{
m_path_selected = m_path_list.GetCurSel();
SetButtonsEnable(IsSelectedPlayEnable());
if (!CPlayer::GetInstance().IsPlaylistMode())
m_path_name.SetWindowText(CPlayer::GetInstance().GetCurrentDir2().c_str());
ShowPathList();
m_list_selected = m_path_list.GetCurSel();
SetButtonsEnable();
}
void CSetPathDlg::DoDataExchange(CDataExchange* pDX)
{
CTabDlg::DoDataExchange(pDX);
DDX_Control(pDX, IDC_PATH_EDIT, m_path_name);
//DDX_Control(pDX, IDC_LIST1, m_path_list);
DDX_Control(pDX, IDC_PATH_LIST, m_path_list);
DDX_Control(pDX, IDC_SEARCH_EDIT, m_search_edit);
}
PathInfo CSetPathDlg::GetSelPath() const
{
if (SelectValid())
return m_recent_path[m_path_selected];
else
return PathInfo();
}
bool CSetPathDlg::SelectValid() const
{
return (m_path_selected >= 0 && m_path_selected < static_cast<int>(m_recent_path.size()));
CTabDlg::DoDataExchange(pDX);
DDX_Control(pDX, IDC_PATH_EDIT, m_path_name);
//DDX_Control(pDX, IDC_LIST1, m_path_list);
DDX_Control(pDX, IDC_PATH_LIST, m_path_list);
DDX_Control(pDX, IDC_SEARCH_EDIT, m_search_edit);
}
BEGIN_MESSAGE_MAP(CSetPathDlg, CTabDlg)
// ON_LBN_SELCHANGE(IDC_LIST1, &CSetPathDlg::OnLbnSelchangeList1)
ON_WM_DESTROY()
//ON_BN_CLICKED(IDC_DELETE_PATH_BUTTON, &CSetPathDlg::OnBnClickedDeletePathButton)
ON_NOTIFY(NM_CLICK, IDC_PATH_LIST, &CSetPathDlg::OnNMClickPathList)
ON_NOTIFY(NM_RCLICK, IDC_PATH_LIST, &CSetPathDlg::OnNMRClickPathList)
ON_NOTIFY(NM_DBLCLK, IDC_PATH_LIST, &CSetPathDlg::OnNMDblclkPathList)
ON_WM_GETMINMAXINFO()
ON_WM_SIZE()
ON_BN_CLICKED(IDC_OPEN_FOLDER, &CSetPathDlg::OnBnClickedOpenFolder)
ON_COMMAND(ID_PLAY_PATH, &CSetPathDlg::OnPlayPath)
ON_COMMAND(ID_DELETE_PATH, &CSetPathDlg::OnDeletePath)
ON_COMMAND(ID_BROWSE_PATH, &CSetPathDlg::OnBrowsePath)
ON_COMMAND(ID_CLEAR_INVALID_PATH, &CSetPathDlg::OnClearInvalidPath)
ON_WM_INITMENU()
ON_EN_CHANGE(IDC_SEARCH_EDIT, &CSetPathDlg::OnEnChangeSearchEdit)
//ON_BN_CLICKED(IDC_CLEAR_BUTTON, &CSetPathDlg::OnBnClickedClearButton)
// ON_LBN_SELCHANGE(IDC_LIST1, &CSetPathDlg::OnLbnSelchangeList1)
ON_WM_DESTROY()
//ON_BN_CLICKED(IDC_DELETE_PATH_BUTTON, &CSetPathDlg::OnBnClickedDeletePathButton)
ON_NOTIFY(NM_CLICK, IDC_PATH_LIST, &CSetPathDlg::OnNMClickPathList)
ON_NOTIFY(NM_RCLICK, IDC_PATH_LIST, &CSetPathDlg::OnNMRClickPathList)
ON_NOTIFY(NM_DBLCLK, IDC_PATH_LIST, &CSetPathDlg::OnNMDblclkPathList)
ON_WM_GETMINMAXINFO()
ON_WM_SIZE()
ON_BN_CLICKED(IDC_OPEN_FOLDER, &CSetPathDlg::OnBnClickedOpenFolder)
ON_COMMAND(ID_PLAY_PATH, &CSetPathDlg::OnPlayPath)
ON_COMMAND(ID_DELETE_PATH, &CSetPathDlg::OnDeletePath)
ON_COMMAND(ID_BROWSE_PATH, &CSetPathDlg::OnBrowsePath)
ON_COMMAND(ID_CLEAR_INVALID_PATH, &CSetPathDlg::OnClearInvalidPath)
ON_WM_INITMENU()
ON_EN_CHANGE(IDC_SEARCH_EDIT, &CSetPathDlg::OnEnChangeSearchEdit)
//ON_BN_CLICKED(IDC_CLEAR_BUTTON, &CSetPathDlg::OnBnClickedClearButton)
ON_MESSAGE(WM_SEARCH_EDIT_BTN_CLICKED, &CSetPathDlg::OnSearchEditBtnClicked)
ON_COMMAND(ID_CONTAIN_SUB_FOLDER, &CSetPathDlg::OnContainSubFolder)
END_MESSAGE_MAP()
@@ -203,177 +219,116 @@ END_MESSAGE_MAP()
BOOL CSetPathDlg::OnInitDialog()
{
CTabDlg::OnInitDialog();
CTabDlg::OnInitDialog();
// TODO: 在此添加额外的初始化
// TODO: 在此添加额外的初始化
if(!CPlayer::GetInstance().IsPlaylistMode())
m_path_name.SetWindowText(CPlayer::GetInstance().GetCurrentDir2().c_str());
//设置列表控件主题颜色
//m_path_list.SetColor(theApp.m_app_setting_data.theme_color);
if (!m_recent_path.empty())
m_current_folder_contain_sub_folder = m_recent_path[0].contain_sub_folder;
//设置列表控件主题颜色
//m_path_list.SetColor(theApp.m_app_setting_data.theme_color);
//初始化播放列表控件
vector<int> width;
CalculateColumeWidth(width);
//初始化播放列表控件
vector<int> width;
CalculateColumeWidth(width);
m_path_list.SetExtendedStyle(m_path_list.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_LABELTIP);
m_path_list.InsertColumn(0, CCommon::LoadText(IDS_NUMBER), LVCFMT_LEFT, width[0]);
m_path_list.InsertColumn(1, CCommon::LoadText(IDS_FOLDER), LVCFMT_LEFT, width[1]);
m_path_list.InsertColumn(2, CCommon::LoadText(IDS_PATH), LVCFMT_LEFT, width[2]);
m_path_list.InsertColumn(3, CCommon::LoadText(IDS_CONTAIN_SUB_FOLDER), LVCFMT_LEFT, width[3]);
m_path_list.InsertColumn(4, CCommon::LoadText(IDS_TRACK_PLAYED), LVCFMT_LEFT, width[4]);
m_path_list.InsertColumn(5, CCommon::LoadText(IDS_TRACK_TOTAL_NUM), LVCFMT_LEFT, width[5]);
m_path_list.InsertColumn(6, CCommon::LoadText(IDS_TOTAL_LENGTH), LVCFMT_LEFT, width[6]);
m_path_list.InsertColumn(0, CCommon::LoadText(IDS_NUMBER), LVCFMT_LEFT, width[0]);
m_path_list.InsertColumn(1, CCommon::LoadText(IDS_FOLDER), LVCFMT_LEFT, width[1]);
m_path_list.InsertColumn(2, CCommon::LoadText(IDS_PATH), LVCFMT_LEFT, width[2]);
m_path_list.InsertColumn(3, CCommon::LoadText(IDS_CONTAIN_SUB_FOLDER), LVCFMT_LEFT, width[3]);
m_path_list.InsertColumn(4, CCommon::LoadText(IDS_TRACK_PLAYED), LVCFMT_LEFT, width[4]);
m_path_list.InsertColumn(5, CCommon::LoadText(IDS_TRACK_TOTAL_NUM), LVCFMT_LEFT, width[5]);
m_path_list.InsertColumn(6, CCommon::LoadText(IDS_TOTAL_LENGTH), LVCFMT_LEFT, width[6]);
ShowPathList();
m_search_edit.SetFocus(); //初始时将焦点设置到搜索框
m_search_edit.SetCueBanner(CCommon::LoadText(IDS_SEARCH_HERE), TRUE);
m_search_edit.SetCueBanner(CCommon::LoadText(IDS_SEARCH_HERE), TRUE);
//获取初始时窗口的大小
CRect rect;
GetWindowRect(rect);
m_min_size.cx = rect.Width();
m_min_size.cy = rect.Height();
//获取初始时窗口的大小
CRect rect;
GetWindowRect(rect);
m_min_size.cx = rect.Width();
m_min_size.cy = rect.Height();
////初始化提示信息
//m_Mytip.Create(this, TTS_ALWAYSTIP);
//m_Mytip.AddTool(GetDlgItem(IDC_CLEAR_BUTTON), CCommon::LoadText(IDS_CLEAR_SEARCH_RESULT));
//m_Mytip.AddTool(&m_search_edit, CCommon::LoadText(IDS_INPUT_KEY_WORD));
////初始化提示信息
//m_Mytip.Create(this, TTS_ALWAYSTIP);
//m_Mytip.AddTool(GetDlgItem(IDC_CLEAR_BUTTON), CCommon::LoadText(IDS_CLEAR_SEARCH_RESULT));
//m_Mytip.AddTool(&m_search_edit, CCommon::LoadText(IDS_INPUT_KEY_WORD));
////设置列表控件的提示总是置顶,用于解决如果弹出此窗口的父窗口具有置顶属性时,提示信息在窗口下面的问题
//m_path_list.GetToolTips()->SetWindowPos(&CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
//m_Mytip.SetWindowPos(&CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
////设置列表控件的提示总是置顶,用于解决如果弹出此窗口的父窗口具有置顶属性时,提示信息在窗口下面的问题
//m_path_list.GetToolTips()->SetWindowPos(&CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
//m_Mytip.SetWindowPos(&CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
return FALSE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
//void CSetPathDlg::OnLbnSelchangeList1()
//{
// // TODO: 在此添加控件通知处理程序代码
// m_path_selected = m_path_list.GetCurSel();
//}
void CSetPathDlg::OnDestroy()
{
CTabDlg::OnDestroy();
// TODO: 在此处添加消息处理程序代码
//m_path_selected = m_path_list.GetCurSel();
if (m_folder_selected)
{
PathInfo path_info = GetSelPath();
::SendMessage(theApp.m_pMainWnd->GetSafeHwnd(), WM_PATH_SELECTED, (WPARAM)&path_info, 0);
m_folder_selected = false;
}
else if (!CPlayer::GetInstance().IsPlaylistMode())
{
//如果正在播放的文件夹是否包含子文件夹的状态被改变了
if (!m_recent_path.empty() && m_current_folder_contain_sub_folder != m_recent_path[0].contain_sub_folder)
{
CPlayer::GetInstance().SetContainSubFolder(m_recent_path[0].contain_sub_folder);
}
}
return FALSE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CSetPathDlg::OnNMClickPathList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
if (!m_searched) //如果播放列表不在搜索状态,则当前选中项的行号就是曲目的索引
{
m_path_selected = pNMItemActivate->iItem;
}
else
{
CString str;
str = m_path_list.GetItemText(pNMItemActivate->iItem, 0);
m_path_selected = _ttoi(str) - 1;
}
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
m_list_selected = pNMItemActivate->iItem;
SetButtonsEnable();
bool enable = IsSelectedPlayEnable();
SetButtonsEnable(enable);
*pResult = 0;
*pResult = 0;
}
void CSetPathDlg::OnNMRClickPathList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
m_path_selected = pNMItemActivate->iItem;
bool enable = IsSelectedPlayEnable();
SetButtonsEnable(enable);
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
m_list_selected = pNMItemActivate->iItem;
SetButtonsEnable();
//弹出右键菜单
CMenu* pContextMenu = theApp.m_menu_set.m_media_lib_folder_menu.GetSubMenu(0); //获取第一个弹出菜单
//弹出右键菜单
CMenu* pContextMenu = theApp.m_menu_set.m_media_lib_folder_menu.GetSubMenu(0); //获取第一个弹出菜单
m_path_list.ShowPopupMenu(pContextMenu, pNMItemActivate->iItem, this);
*pResult = 0;
*pResult = 0;
}
void CSetPathDlg::OnNMDblclkPathList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
if (!m_searched) //如果播放列表不在搜索状态,则当前选中项的行号就是曲目的索引
{
m_path_selected = pNMItemActivate->iItem;
}
else
{
CString str;
str = m_path_list.GetItemText(pNMItemActivate->iItem, 0);
m_path_selected = _ttoi(str) - 1;
}
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
m_list_selected = pNMItemActivate->iItem;
OnOK();
bool enable = IsSelectedPlayEnable();
SetButtonsEnable(enable);
if(enable)
OnOK();
*pResult = 0;
*pResult = 0;
}
void CSetPathDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//限制窗口最小大小
lpMMI->ptMinTrackSize.x = m_min_size.cx; //设置最小宽度
lpMMI->ptMinTrackSize.y = m_min_size.cy; //设置最小高度
// TODO: 在此添加消息处理程序代码和/或调用默认值
//限制窗口最小大小
lpMMI->ptMinTrackSize.x = m_min_size.cx; //设置最小宽度
lpMMI->ptMinTrackSize.y = m_min_size.cy; //设置最小高度
CTabDlg::OnGetMinMaxInfo(lpMMI);
CTabDlg::OnGetMinMaxInfo(lpMMI);
}
void CSetPathDlg::OnSize(UINT nType, int cx, int cy)
{
CTabDlg::OnSize(nType, cx, cy);
CTabDlg::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
// TODO: 在此处添加消息处理程序代码
}
void CSetPathDlg::OnOK()
{
// TODO: 在此添加专用代码和/或调用基类
if (SelectValid())
if (SelectedCanPlay())
{
m_folder_selected = true;
}
CTabDlg::OnOK();
CWnd* pParent = GetParentWindow();
if (pParent != nullptr)
{
::PostMessage(pParent->GetSafeHwnd(), WM_COMMAND, IDOK, 0);
PathInfo path_info = GetSelPath();
CPlayer::GetInstance().SetPath(path_info, true);
CTabDlg::OnOK();
CWnd* pParent = GetParentWindow();
if (pParent != nullptr)
{
::PostMessage(pParent->GetSafeHwnd(), WM_COMMAND, IDOK, 0);
}
}
}
@@ -381,119 +336,130 @@ void CSetPathDlg::OnOK()
void CSetPathDlg::OnBnClickedOpenFolder()
{
// TODO: 在此添加控件通知处理程序代码
// 向主窗口发送打开文件夹命令
::SendMessage(theApp.m_pMainWnd->GetSafeHwnd(), WM_COMMAND, ID_FILE_OPEN_FOLDER, 0);
// “打开新路径”处理完成后向媒体库请求关闭对话框
CTabDlg::OnOK();
CWnd* pParent = GetParentWindow();
if (pParent != nullptr)
::PostMessage(pParent->GetSafeHwnd(), WM_COMMAND, IDOK, 0);
static bool include_sub_dir{ false };
// 这里原来使用WM_COMMAND, ID_FILE_OPEN_FOLDER但菜单命令无法返回用户是否点击“取消”
#ifdef COMPILE_IN_WIN_XP
CFolderBrowserDlg folderPickerDlg(this->GetSafeHwnd());
folderPickerDlg.SetInfo(CCommon::LoadText(IDS_OPEN_FOLDER_INFO));
#else
CFilePathHelper current_path(CPlayer::GetInstance().GetCurrentDir());
CFolderPickerDialog folderPickerDlg(current_path.GetParentDir().c_str());
folderPickerDlg.AddCheckButton(IDC_OPEN_CHECKBOX, CCommon::LoadText(IDS_INCLUDE_SUB_DIR), include_sub_dir); //在打开对话框中添加一个复选框
#endif
if (folderPickerDlg.DoModal() == IDOK)
{
#ifndef COMPILE_IN_WIN_XP
BOOL checked;
folderPickerDlg.GetCheckButtonState(IDC_OPEN_CHECKBOX, checked);
include_sub_dir = (checked != FALSE);
#endif
CPlayer::GetInstance().OpenFolder(wstring(folderPickerDlg.GetPathName()), include_sub_dir);
// “打开新路径”处理完成后向媒体库请求关闭对话框
CTabDlg::OnOK();
CWnd* pParent = GetParentWindow();
if (pParent != nullptr)
::PostMessage(pParent->GetSafeHwnd(), WM_COMMAND, IDOK, 0);
}
}
void CSetPathDlg::OnPlayPath()
{
// TODO: 在此添加命令处理程序代码
OnOK();
// TODO: 在此添加命令处理程序代码
OnOK();
}
void CSetPathDlg::OnDeletePath()
{
// TODO: 在此添加命令处理程序代码
if (SelectValid())
{
m_recent_path.erase(m_recent_path.begin() + m_path_selected); //删除选中的路径
ShowPathList(); //重新显示路径列表
// TODO: 在此添加命令处理程序代码
if (SelectValid())
{
wstring del_path = GetSelPath().path;
// 这里删除当前播放有问题,实际只会清除子文件夹bool,以后需要改为切到默认播放列表时删除
deque<PathInfo>& recent_path = CPlayer::GetInstance().GetRecentPath();
auto iter = std::find_if(recent_path.begin(), recent_path.end(), [&](const PathInfo& info) { return info.path == del_path; });
recent_path.erase(iter); // 删除选中的路径
m_searched = false; // 删除后搜索索引可能越界,退出搜索状态
ShowPathList(); // 重新显示路径列表
CRecentFolderAndPlaylist::Instance().Init();
}
}
}
void CSetPathDlg::OnBrowsePath()
{
// TODO: 在此添加命令处理程序代码
if (SelectValid())
ShellExecute(NULL, _T("open"), _T("explorer"), m_recent_path[m_path_selected].path.c_str(), NULL, SW_SHOWNORMAL);
// TODO: 在此添加命令处理程序代码
if (SelectValid())
ShellExecute(NULL, _T("open"), _T("explorer"), GetSelPath().path.c_str(), NULL, SW_SHOWNORMAL);
}
void CSetPathDlg::OnClearInvalidPath()
{
// TODO: 在此添加命令处理程序代码
if (MessageBox(CCommon::LoadText(IDS_CLEAR_PATH_INQUARY), NULL, MB_ICONQUESTION | MB_OKCANCEL) == IDCANCEL)
return;
// TODO: 在此添加命令处理程序代码
if (MessageBox(CCommon::LoadText(IDS_CLEAR_PATH_INQUARY), NULL, MB_ICONQUESTION | MB_OKCANCEL) == IDCANCEL)
return;
int cleard_cnt = CMusicPlayerCmdHelper::CleanUpRecentFolders();
ShowPathList(); //重新显示路径列表
CString info;
info = CCommon::LoadTextFormat(IDS_PATH_CLEAR_COMPLETE, { cleard_cnt });
MessageBox(info, NULL, MB_ICONINFORMATION | MB_OK);
m_searched = false; // 清理后搜索索引可能越界,退出搜索状态
ShowPathList(); // 重新显示路径列表
CRecentFolderAndPlaylist::Instance().Init();
CString info;
info = CCommon::LoadTextFormat(IDS_PATH_CLEAR_COMPLETE, { cleard_cnt });
MessageBox(info, NULL, MB_ICONINFORMATION | MB_OK);
}
void CSetPathDlg::OnInitMenu(CMenu* pMenu)
{
CTabDlg::OnInitMenu(pMenu);
CTabDlg::OnInitMenu(pMenu);
// TODO: 在此处添加消息处理程序代码
bool select_valid{ SelectValid() };
pMenu->EnableMenuItem(ID_PLAY_PATH, MF_BYCOMMAND | (select_valid ? MF_ENABLED : MF_GRAYED));
pMenu->EnableMenuItem(ID_DELETE_PATH, MF_BYCOMMAND | (select_valid ? MF_ENABLED : MF_GRAYED));
pMenu->EnableMenuItem(ID_BROWSE_PATH, MF_BYCOMMAND | (select_valid ? MF_ENABLED : MF_GRAYED));
// TODO: 在此处添加消息处理程序代码
bool select_valid{ SelectValid() };
pMenu->EnableMenuItem(ID_PLAY_PATH, MF_BYCOMMAND | (select_valid ? MF_ENABLED : MF_GRAYED));
pMenu->EnableMenuItem(ID_DELETE_PATH, MF_BYCOMMAND | (select_valid ? MF_ENABLED : MF_GRAYED));
pMenu->EnableMenuItem(ID_BROWSE_PATH, MF_BYCOMMAND | (select_valid ? MF_ENABLED : MF_GRAYED));
pMenu->EnableMenuItem(ID_CONTAIN_SUB_FOLDER, MF_BYCOMMAND | (select_valid ? MF_ENABLED : MF_GRAYED));
bool contain_sub_folder{false};
if (select_valid)
contain_sub_folder = m_recent_path[m_path_selected].contain_sub_folder;
contain_sub_folder = GetSelPath().contain_sub_folder;
pMenu->CheckMenuItem(ID_CONTAIN_SUB_FOLDER, MF_BYCOMMAND | (contain_sub_folder ? MF_CHECKED : MF_UNCHECKED));
}
void CSetPathDlg::OnEnChangeSearchEdit()
{
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CTabDlg::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 如果该控件是 RICHEDIT 控件,它将不
// 发送此通知,除非重写 CTabDlg::OnInitDialog()
// 函数并调用 CRichEditCtrl().SetEventMask(),
// 同时将 ENM_CHANGE 标志“或”运算到掩码中。
// TODO: 在此添加控件通知处理程序代码
CString key_word;
m_search_edit.GetWindowText(key_word);
m_searched = (key_word.GetLength() != 0);
QuickSearch(wstring(key_word));
ShowPathList();
// TODO: 在此添加控件通知处理程序代码
CString key_word;
m_search_edit.GetWindowText(key_word);
m_searched = (key_word.GetLength() != 0);
QuickSearch(wstring(key_word));
ShowPathList();
}
//void CSetPathDlg::OnBnClickedClearButton()
//{
// // TODO: 在此添加控件通知处理程序代码
// if (m_searched)
// {
// //清除搜索结果
// m_searched = false;
// m_search_edit.SetWindowText(_T(""));
// ShowPathList();
// }
//}
BOOL CSetPathDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message == WM_KEYDOWN && pMsg->hwnd != m_search_edit.GetSafeHwnd())
{
if (pMsg->wParam == 'F') //按F键快速查找
{
m_search_edit.SetFocus();
return TRUE;
}
}
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message == WM_KEYDOWN && pMsg->hwnd != m_search_edit.GetSafeHwnd())
{
if (pMsg->wParam == 'F') //按F键快速查找
{
m_search_edit.SetFocus();
return TRUE;
}
}
//if (pMsg->message == WM_MOUSEMOVE)
// m_Mytip.RelayEvent(pMsg);
//if (pMsg->message == WM_MOUSEMOVE)
// m_Mytip.RelayEvent(pMsg);
return CTabDlg::PreTranslateMessage(pMsg);
return CTabDlg::PreTranslateMessage(pMsg);
}
@@ -515,13 +481,24 @@ void CSetPathDlg::OnContainSubFolder()
// TODO: 在此添加命令处理程序代码
if (SelectValid())
{
m_recent_path[m_path_selected].contain_sub_folder = !m_recent_path[m_path_selected].contain_sub_folder;
SetListRowData(m_path_selected, m_recent_path[m_path_selected]); //刷新当前行
//if (m_path_selected == 0) //如果更改了正在播放的文件夹
//{
// PathInfo path_info = m_recent_path[0];
// ::SendMessage(theApp.m_pMainWnd->GetSafeHwnd(), WM_PATH_SELECTED, (WPARAM)&path_info, 0);
//}
}
wstring sel_path = GetSelPath().path; // 当前选中项
// 如果是当前播放则使用CPlayer成员方法更改(会启动播放列表初始化)不需要操作CPlayer::GetInstance().GetRecentPath()
if (!CPlayer::GetInstance().IsPlaylistMode() && CPlayer::GetInstance().GetCurrentDir2() == sel_path)
{
// 这个不一定成功(没取得锁),将来需要加个提示
CPlayer::GetInstance().SetContainSubFolder();
}
else
{
deque<PathInfo>& recent_path = CPlayer::GetInstance().GetRecentPath();
auto iter = std::find_if(recent_path.begin(), recent_path.end(), [&](const PathInfo& info) { return info.path == sel_path; });
if (iter != recent_path.end())
{
PathInfo& it = *iter;
it.contain_sub_folder = !it.contain_sub_folder;
SetListRowData(m_list_selected, it);
}
}
}
}
+47 -53
View File
@@ -2,86 +2,80 @@
#include "afxwin.h"
#include "Common.h"
#include "AudioCommon.h"
#include "afxcmn.h"
#include "ListCtrlEx.h"
#include "TabDlg.h"
#include "SearchEditCtrl.h"
// CSetPathDlg 对话框
#define WM_PATH_SELECTED (WM_USER+107)
// #define WM_PATH_SELECTED (WM_USER+107) 不再使用
class CSetPathDlg : public CTabDlg
{
DECLARE_DYNAMIC(CSetPathDlg)
DECLARE_DYNAMIC(CSetPathDlg)
public:
CSetPathDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CSetPathDlg();
CSetPathDlg(CWnd* pParent = NULL); // 标准构造函数
virtual ~CSetPathDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_SET_PATH_DIALOG };
enum { IDD = IDD_SET_PATH_DIALOG };
#endif
public:
void QuickSearch(const wstring& key_words); //根据关键字执行快速查找m_search_result中
void QuickSearch(const wstring& key_words); //根据关键字执行快速查找(更新m_path_list_info和m_search_result)
void AdjustColumnWidth(); //自动调整列表宽度
void RefreshTabData(); //刷新标签页数据
protected:
deque<PathInfo>& m_recent_path; //最近打开过的路径
int m_path_selected{}; //选择的路径
bool m_searched{ false }; // 是否处于搜索状态
vector<size_t> m_search_result; // 储存快速搜索结果的歌曲序号
CEdit m_path_name;
CListCtrlEx m_path_list;
//CMenu m_menu;
CSearchEditCtrl m_search_edit;
//CToolTipCtrl m_Mytip;
CListCtrlEx m_path_list; // 列表对象
vector<PathInfo> m_path_list_info; // 与列表数据同步
size_t m_list_selected{}; // 选中的列表数据索引(搜索状态下不是m_recent_path的索引)
CSize m_min_size; //窗口的最小大小
CEdit m_path_name;
CSearchEditCtrl m_search_edit;
CSize m_min_size; // 窗口的最小大小
vector<int> m_search_result; //储存快速搜索结果的歌曲序号
bool m_searched{ false }; //是否处理搜索状态
bool m_folder_selected{ false };
bool m_current_folder_contain_sub_folder{ false }; //初始时正在播放的文件夹是否包含子文件夹
protected:
void ShowPathList();
void SetButtonsEnable(bool enable);
void CalculateColumeWidth(vector<int>& width);
void SetListRowData(int index, const PathInfo& path_info);
bool IsSelectedPlayEnable() const; //判断选中路径是否可以播放
// 判断选择是否有效
bool SelectValid() const;
// 获取选择的路径
PathInfo GetSelPath() const;
// 返回当前选中GetSelPath()是否能够播放
bool SelectedCanPlay() const;
// 判断并设置“播放选中”按钮状态
void SetButtonsEnable();
// 更新m_path_list_info和m_path_list,搜索状态下请确保m_search_result不越界
void ShowPathList();
// 计算列宽
void CalculateColumeWidth(vector<int>& width);
void SetListRowData(int index, const PathInfo& path_info);
virtual void OnTabEntered() override;
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
DECLARE_MESSAGE_MAP()
public:
PathInfo GetSelPath() const; //获取选择的路径
//int GetTrack() const;
//int GetPosition() const;
//SortMode GetSortMode() const;
bool SelectValid() const; //判断选择是否有效
virtual BOOL OnInitDialog();
afx_msg void OnDestroy();
//afx_msg void OnBnClickedDeletePathButton();
//virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
afx_msg void OnNMClickPathList(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnNMRClickPathList(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnNMDblclkPathList(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
afx_msg void OnSize(UINT nType, int cx, int cy);
virtual void OnOK();
afx_msg void OnBnClickedOpenFolder();
afx_msg void OnPlayPath();
afx_msg void OnDeletePath();
afx_msg void OnBrowsePath();
afx_msg void OnClearInvalidPath();
afx_msg void OnInitMenu(CMenu* pMenu);
afx_msg void OnEnChangeSearchEdit();
//afx_msg void OnBnClickedClearButton();
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL OnInitDialog();
//afx_msg void OnBnClickedDeletePathButton();
//virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
afx_msg void OnNMClickPathList(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnNMRClickPathList(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnNMDblclkPathList(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
afx_msg void OnSize(UINT nType, int cx, int cy);
virtual void OnOK();
afx_msg void OnBnClickedOpenFolder();
afx_msg void OnPlayPath();
afx_msg void OnDeletePath();
afx_msg void OnBrowsePath();
afx_msg void OnClearInvalidPath();
afx_msg void OnInitMenu(CMenu* pMenu);
afx_msg void OnEnChangeSearchEdit();
//afx_msg void OnBnClickedClearButton();
virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
afx_msg LRESULT OnSearchEditBtnClicked(WPARAM wParam, LPARAM lParam);
public: