1 // FindListDlg.cpp: 实现文件
2 //
3
4 #include "stdafx.h"
5 #include "MusicPlayer2.h"
6 #include "afxdialogex.h"
7 #include "FindListDlg.h"
8 #include "UiMediaLibItemMgr.h"
9 #include "MusicPlayerCmdHelper.h"
10 #include "FolderPropertiesDlg.h"
11 #include "PlaylistPropertiesDlg.h"
12 #include "MediaLibItemPropertiesDlg.h"
13
14 // CFindListDlg 对话框
15
IMPLEMENT_DYNAMIC(CFindListDlg,CTabDlg)16 IMPLEMENT_DYNAMIC(CFindListDlg, CTabDlg)
17
18 CFindListDlg::CFindListDlg(CWnd* pParent /*=nullptr*/)
19 : CTabDlg(IDD_FIND_LIST_DIALOG, pParent)
20 {
21
22 }
23
~CFindListDlg()24 CFindListDlg::~CFindListDlg()
25 {
26 }
27
InitListData()28 void CFindListDlg::InitListData()
29 {
30 if (!m_initialized)
31 {
32 m_list_data.clear();
33 //添加所有最近播放项目
34 CListCache list_cache(LT_ALL);
35 list_cache.reload();
36 AddListCacheData(list_cache);
37 //添加媒体库项目
38 AddMediaLibItem(CMediaClassifier::CT_ARTIST);
39 AddMediaLibItem(CMediaClassifier::CT_ALBUM);
40 AddMediaLibItem(CMediaClassifier::CT_GENRE);
41 AddMediaLibItem(CMediaClassifier::CT_YEAR);
42 AddMediaLibItem(CMediaClassifier::CT_TYPE);
43 //添加媒体库中的所有文件夹
44 AddAllFolders();
45
46 //设置到列表
47 ShowList();
48
49 m_initialized = true;
50 }
51 }
52
OnTabEntered()53 void CFindListDlg::OnTabEntered()
54 {
55 if (!m_initialized)
56 SetPlaySelectedEnable(false);
57 else
58 SetPlaySelectedEnable(m_list_ctrl.GetCurSel() > 0);
59 InitListData();
60 }
61
AddListCacheData(const CListCache & list_cache)62 void CFindListDlg::AddListCacheData(const CListCache& list_cache)
63 {
64 for (int i{}; i < list_cache.size(); i++)
65 {
66 CListCtrlEx::RowData row_data;
67 const auto& list_data = list_cache.at(i);
68 row_data[COL_NAME] = list_data.GetDisplayName();
69 row_data[COL_TRACK_NUM] = std::to_wstring(list_data.total_num);
70 m_list_data.push_back(std::move(row_data));
71 FindListItem list_item;
72 list_item.list_data = list_data;
73 list_item.item_from = ItemFrom::RECENT_PLAYED;
74 m_all_list_items.push_back(list_item);
75 }
76 }
77
AddMediaLibItem(CMediaClassifier::ClassificationType type)78 void CFindListDlg::AddMediaLibItem(CMediaClassifier::ClassificationType type)
79 {
80 //这里考虑即使没有在媒体库设置中勾选“将只有一项的分类归到其他类中”,也应该添加所有项目
81 int item_count = CUiMediaLibItemMgr::Instance().GetItemCount(type);
82 for (int i{}; i < item_count; i++)
83 {
84 ListItem list_data;
85 list_data.type = LT_MEDIA_LIB;
86 list_data.medialib_type = type;
87 list_data.path = CUiMediaLibItemMgr::Instance().GetItemName(type, i);
88 list_data.total_num = CUiMediaLibItemMgr::Instance().GetItemSongCount(type, i);
89 auto iter = std::find(m_all_list_items.begin(), m_all_list_items.end(), list_data);
90 //不添加重复的项目
91 if (iter == m_all_list_items.end())
92 {
93 FindListItem list_item;
94 list_item.list_data = list_data;
95 list_item.item_from = ItemFrom::MEDIALIB_ITEM;
96 m_all_list_items.push_back(list_item);
97 CListCtrlEx::RowData row_data;
98 row_data[COL_NAME] = CUiMediaLibItemMgr::Instance().GetItemDisplayName(type, i);
99 row_data[COL_TRACK_NUM] = std::to_wstring(list_data.total_num);
100 m_list_data.push_back(std::move(row_data));
101 }
102 }
103 }
104
AddAllFolders()105 void CFindListDlg::AddAllFolders()
106 {
107 const auto& folder_nodes = CUiFolderExploreMgr::Instance().GetRootNodes();
108 for (const auto& folder_node : folder_nodes)
109 {
110 //遍历每个顶级文件夹节点
111 folder_node->IterateNodeInOrder([&](UiElement::TreeElement::Node* node) -> bool {
112 std::wstring folder_path = UiElement::FolderExploreTree::GetNodePath(node); //文件夹路径
113 std::wstring track_num = node->texts[UiElement::FolderExploreTree::COL_COUNT]; //曲目数
114 ListItem list_data;
115 list_data.type = LT_FOLDER;
116 list_data.path = folder_path + L'\\'; //文件夹路径末尾添加一个反斜杠,使得其格式和CListCache中的文件夹一致
117 list_data.total_num = _wtoi(track_num.c_str());
118 auto iter = std::find(m_all_list_items.begin(), m_all_list_items.end(), list_data);
119 //不添加重复的项目
120 if (iter == m_all_list_items.end())
121 {
122 FindListItem list_item;
123 list_item.list_data = list_data;
124 list_item.item_from = ItemFrom::FOLDER_EXPLORE;
125 m_all_list_items.push_back(list_item);
126 CListCtrlEx::RowData row_data;
127 row_data[COL_NAME] = folder_path;
128 row_data[COL_TRACK_NUM] = track_num;
129 m_list_data.push_back(std::move(row_data));
130 }
131 return false;
132 }, false);
133 }
134 }
135
ShowList()136 void CFindListDlg::ShowList()
137 {
138 if (m_searched)
139 m_list_ctrl.SetListData(&m_list_data_searched);
140 else
141 m_list_ctrl.SetListData(&m_list_data);
142
143 //更新图标
144 if (m_searched)
145 {
146 for (int i{}; i < static_cast<int>(m_search_result.size()); i++)
147 {
148 int index = m_search_result[i];
149 if (index >= 0 && index < static_cast<int>(m_all_list_items.size()))
150 {
151 IconMgr::IconType icon = m_all_list_items[index].list_data.GetTypeIcon();
152 m_list_ctrl.SetItemIcon(i, theApp.m_icon_mgr.GetHICON(icon, IconMgr::IconStyle::IS_OutlinedDark, IconMgr::IconSize::IS_DPI_16));
153 }
154 }
155 }
156 else
157 {
158 for (int i{}; i < static_cast<int>(m_all_list_items.size()); i++)
159 {
160 IconMgr::IconType icon = m_all_list_items[i].list_data.GetTypeIcon();
161 m_list_ctrl.SetItemIcon(i, theApp.m_icon_mgr.GetHICON(icon, IconMgr::IconStyle::IS_OutlinedDark, IconMgr::IconSize::IS_DPI_16));
162 }
163 }
164 }
165
QuickSearch(const wstring & key_word)166 void CFindListDlg::QuickSearch(const wstring& key_word)
167 {
168 m_list_data_searched.clear();
169 m_search_result.clear();
170 if (!key_word.empty())
171 {
172 for (int i{}; i < static_cast<int>(m_list_data.size()); ++i)
173 {
174 const auto& item{ m_list_data[i] };
175 const vector<int> search_col{ COL_NAME };
176 for (int col : search_col)
177 {
178 if (theApp.m_chinese_pingyin_res.IsStringMatchWithPingyin(key_word, item.at(col)))
179 {
180 m_list_data_searched.push_back(item);
181 m_search_result.push_back(i);
182 break;
183 }
184 }
185 }
186 }
187 }
188
SetPlaySelectedEnable(bool enable)189 void CFindListDlg::SetPlaySelectedEnable(bool enable)
190 {
191 CWnd* pParent = GetParentWindow();
192 ::SendMessage(pParent->GetSafeHwnd(), WM_PLAY_SELECTED_BTN_ENABLE, WPARAM(enable), 0);
193 }
194
GetSelectedItem() const195 CFindListDlg::FindListItem CFindListDlg::GetSelectedItem() const
196 {
197 FindListItem list_item;
198 int cur_sel = m_list_ctrl.GetCurSel();
199 if (m_searched)
200 {
201 if (cur_sel >= 0 && cur_sel < static_cast<int>(m_search_result.size()))
202 {
203 int index = m_search_result[cur_sel];
204 if (index >= 0 && index < static_cast<int>(m_all_list_items.size()))
205 {
206 list_item = m_all_list_items[index];
207 }
208 }
209 }
210 else
211 {
212 if (cur_sel >= 0 && cur_sel < static_cast<int>(m_all_list_items.size()))
213 {
214 list_item = m_all_list_items[cur_sel];
215 }
216 }
217 return list_item;
218 }
219
DoDataExchange(CDataExchange * pDX)220 void CFindListDlg::DoDataExchange(CDataExchange* pDX)
221 {
222 CTabDlg::DoDataExchange(pDX);
223 DDX_Control(pDX, IDC_SONG_LIST, m_list_ctrl);
224 DDX_Control(pDX, IDC_SEARCH_EDIT, m_search_edit);
225 }
226
227
BEGIN_MESSAGE_MAP(CFindListDlg,CTabDlg)228 BEGIN_MESSAGE_MAP(CFindListDlg, CTabDlg)
229 ON_MESSAGE(WM_SEARCH_EDIT_BTN_CLICKED, &CFindListDlg::OnSearchEditBtnClicked)
230 ON_EN_CHANGE(IDC_SEARCH_EDIT, &CFindListDlg::OnEnChangeSearchEdit)
231 ON_NOTIFY(NM_CLICK, IDC_SONG_LIST, &CFindListDlg::OnNMClickSongList)
232 ON_WM_SIZE()
233 ON_NOTIFY(NM_DBLCLK, IDC_SONG_LIST, &CFindListDlg::OnNMDblclkSongList)
234 ON_NOTIFY(NM_RCLICK, IDC_SONG_LIST, &CFindListDlg::OnNMRClickSongList)
235 ON_COMMAND(ID_PLAY_ITEM, &CFindListDlg::OnPlayItem)
236 ON_COMMAND(ID_COPY_TEXT, &CFindListDlg::OnCopyText)
237 ON_COMMAND(ID_VIEW_IN_MEDIA_LIB, &CFindListDlg::OnViewInMediaLib)
238 ON_COMMAND(ID_LIB_RECENT_PLAYED_ITEM_PROPERTIES, &CFindListDlg::OnLibRecentPlayedItemProperties)
239 ON_WM_INITMENU()
240 END_MESSAGE_MAP()
241
242
243 // CFindListDlg 消息处理程序
244
245
246 BOOL CFindListDlg::OnInitDialog()
247 {
248 CTabDlg::OnInitDialog();
249
250 //初始化列表控件
251 m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_LABELTIP);
252 m_list_ctrl.InsertColumn(COL_NAME, theApp.m_str_table.LoadText(L"TXT_NAME").c_str(), LVCFMT_LEFT, theApp.DPI(320));
253 m_list_ctrl.InsertColumn(COL_TRACK_NUM, theApp.m_str_table.LoadText(L"TXT_NUM_OF_TRACK").c_str(), LVCFMT_LEFT, theApp.DPI(140));
254 m_list_ctrl.SetCtrlAEnable(true);
255 m_list_ctrl.SetRowHeight(theApp.DPI(24), theApp.DPI(18));
256
257 m_search_edit.SetCueBanner(theApp.m_str_table.LoadText(L"TXT_SEARCH_PROMPT_ALL_LIST").c_str(), TRUE);
258
259
260 return TRUE; // return TRUE unless you set the focus to a control
261 // 异常: OCX 属性页应返回 FALSE
262 }
263
264
OnOK()265 void CFindListDlg::OnOK()
266 {
267 //获取选中的项目
268 FindListItem list_item = GetSelectedItem();
269 if (!list_item.list_data.empty())
270 {
271 CMusicPlayerCmdHelper helper;
272 helper.OnListItemSelected(list_item.list_data, true);
273 }
274
275 CTabDlg::OnOK();
276 }
277
278
OnSearchEditBtnClicked(WPARAM wParam,LPARAM lParam)279 afx_msg LRESULT CFindListDlg::OnSearchEditBtnClicked(WPARAM wParam, LPARAM lParam)
280 {
281 //点击搜索框中的叉按钮时清除搜索结果
282 if (m_searched)
283 {
284 //清除搜索结果
285 m_searched = false;
286 m_search_edit.SetWindowText(_T(""));
287 ShowList();
288 }
289 return 0;
290 }
291
292
OnEnChangeSearchEdit()293 void CFindListDlg::OnEnChangeSearchEdit()
294 {
295 // TODO: 如果该控件是 RICHEDIT 控件,它将不
296 // 发送此通知,除非重写 CTabDlg::OnInitDialog()
297 // 函数并调用 CRichEditCtrl().SetEventMask(),
298 // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
299
300 CString str;
301 m_search_edit.GetWindowText(str);
302 QuickSearch(wstring(str));
303 m_searched = !str.IsEmpty();
304 ShowList();
305 }
306
307
OnNMClickSongList(NMHDR * pNMHDR,LRESULT * pResult)308 void CFindListDlg::OnNMClickSongList(NMHDR* pNMHDR, LRESULT* pResult)
309 {
310 LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
311 // TODO: 在此添加控件通知处理程序代码
312 SetPlaySelectedEnable(pNMItemActivate->iItem != -1);
313
314 *pResult = 0;
315 }
316
317
OnSize(UINT nType,int cx,int cy)318 void CFindListDlg::OnSize(UINT nType, int cx, int cy)
319 {
320 CTabDlg::OnSize(nType, cx, cy);
321
322 if (m_list_ctrl.m_hWnd != NULL && nType != SIZE_MINIMIZED)
323 {
324 //调整列表中项目的宽度
325 CRect rect;
326 m_list_ctrl.GetWindowRect(rect);
327 int list_width{ rect.Width() - theApp.DPI(20) - 1 }; //列表控件宽度减去留给垂直滚动条的宽度余量
328 int width0, width1;
329 width1 = theApp.DPI(60);
330 width0 = list_width - width1;
331 m_list_ctrl.SetColumnWidth(COL_NAME, width0);
332 m_list_ctrl.SetColumnWidth(COL_TRACK_NUM, width1);
333 }
334 }
335
336
OnNMDblclkSongList(NMHDR * pNMHDR,LRESULT * pResult)337 void CFindListDlg::OnNMDblclkSongList(NMHDR* pNMHDR, LRESULT* pResult)
338 {
339 LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
340 OnPlayItem();
341 *pResult = 0;
342 }
343
344
OnNMRClickSongList(NMHDR * pNMHDR,LRESULT * pResult)345 void CFindListDlg::OnNMRClickSongList(NMHDR* pNMHDR, LRESULT* pResult)
346 {
347 LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
348
349 //弹出右键菜单
350 CMenu* pContextMenu = theApp.m_menu_mgr.GetMenu(MenuMgr::FindListMenu);
351 m_list_ctrl.ShowPopupMenu(pContextMenu, pNMItemActivate->iItem, this);
352 *pResult = 0;
353 }
354
355
OnPlayItem()356 void CFindListDlg::OnPlayItem()
357 {
358 //向父窗口发送IDOK命令
359 CWnd* pParent = GetParentWindow();
360 ::SendMessage(pParent->GetSafeHwnd(), WM_COMMAND, IDOK, 0);
361 }
362
363
OnCopyText()364 void CFindListDlg::OnCopyText()
365 {
366 FindListItem list_item = GetSelectedItem();
367 if (list_item.list_data.empty())
368 return;
369 if (!CCommon::CopyStringToClipboard(list_item.list_data.GetDisplayName()))
370 AfxMessageBox(theApp.m_str_table.LoadText(L"MSG_COPY_CLIPBOARD_FAILED").c_str(), MB_ICONWARNING);
371 }
372
373
OnViewInMediaLib()374 void CFindListDlg::OnViewInMediaLib()
375 {
376 FindListItem list_item = GetSelectedItem();
377 if (list_item.list_data.empty())
378 return;
379 CMusicPlayerCmdHelper helper;
380 helper.OnViewInMediaLib(list_item.list_data);
381 }
382
383
OnLibRecentPlayedItemProperties()384 void CFindListDlg::OnLibRecentPlayedItemProperties()
385 {
386 FindListItem list_item = GetSelectedItem();
387 if (list_item.list_data.empty())
388 return;
389 if (list_item.list_data.type == LT_FOLDER)
390 {
391 CFolderPropertiesDlg dlg(list_item.list_data);
392 dlg.DoModal();
393 }
394 else if (list_item.list_data.type == LT_PLAYLIST)
395 {
396 CPlaylistPropertiesDlg dlg(list_item.list_data);
397 dlg.DoModal();
398 }
399 else if (list_item.list_data.type == LT_MEDIA_LIB)
400 {
401 CMediaLibItemPropertiesDlg dlg(list_item.list_data);
402 dlg.DoModal();
403 }
404 }
405
406
OnInitMenu(CMenu * pMenu)407 void CFindListDlg::OnInitMenu(CMenu* pMenu)
408 {
409 CTabDlg::OnInitMenu(pMenu);
410
411 FindListItem list_item = GetSelectedItem();
412 bool select_valid = m_list_ctrl.GetCurSel() >= 0;
413 pMenu->EnableMenuItem(ID_PLAY_ITEM, MF_BYCOMMAND | (select_valid ? MF_ENABLED : MF_GRAYED));
414 pMenu->EnableMenuItem(ID_COPY_TEXT, MF_BYCOMMAND | (select_valid ? MF_ENABLED : MF_GRAYED));
415 pMenu->EnableMenuItem(ID_VIEW_IN_MEDIA_LIB, MF_BYCOMMAND | (select_valid && (list_item.item_from == ItemFrom::RECENT_PLAYED || list_item.item_from == ItemFrom::MEDIALIB_ITEM) ? MF_ENABLED : MF_GRAYED));
416 pMenu->EnableMenuItem(ID_LIB_RECENT_PLAYED_ITEM_PROPERTIES, MF_BYCOMMAND | (select_valid && list_item.item_from == ItemFrom::RECENT_PLAYED ? MF_ENABLED : MF_GRAYED));
417 }
418