xref: /MusicPlayer2/MusicPlayer2/MediaClassifyDlg.cpp (revision 965ce478a79b0d21e8a6e2ade0490efa175855dd)
1 // MediaClassfyDlg.cpp: 实现文件
2 //
3 
4 #include "stdafx.h"
5 #include "MusicPlayer2.h"
6 #include "MediaClassifyDlg.h"
7 #include "Playlist.h"
8 #include "InputDlg.h"
9 #include "MusicPlayerCmdHelper.h"
10 #include "PropertyDlg.h"
11 #include "AddToPlaylistDlg.h"
12 #include "SongDataManager.h"
13 #include "Player.h"
14 
15 
16 // CMediaClassifyDlg 对话框
17 
IMPLEMENT_DYNAMIC(CMediaClassifyDlg,CMediaLibTabDlg)18 IMPLEMENT_DYNAMIC(CMediaClassifyDlg, CMediaLibTabDlg)
19 
20 CMediaClassifyDlg::CMediaClassifyDlg(CMediaClassifier::ClassificationType type, CWnd* pParent /*=nullptr*/)
21     : CMediaLibTabDlg(IDD_MEDIA_CLASSIFY_DIALOG, pParent), m_type(type),
22     m_classifer(type, theApp.m_media_lib_setting_data.hide_only_one_classification)
23 {
24     if (m_type == CMediaClassifier::CT_ARTIST)
25         m_default_str = theApp.m_str_table.LoadText(L"TXT_EMPTY_ARTIST");
26     else if (m_type == CMediaClassifier::CT_ALBUM)
27         m_default_str = theApp.m_str_table.LoadText(L"TXT_EMPTY_ALBUM");
28     else if (m_type == CMediaClassifier::CT_GENRE)
29         m_default_str = theApp.m_str_table.LoadText(L"TXT_EMPTY_GENRE");
30     else if (m_type == CMediaClassifier::CT_YEAR)
31         m_default_str = theApp.m_str_table.LoadText(L"TXT_EMPTY_YEAR");
32 }
33 
~CMediaClassifyDlg()34 CMediaClassifyDlg::~CMediaClassifyDlg()
35 {
36 }
37 
RefreshData()38 void CMediaClassifyDlg::RefreshData()
39 {
40     m_classifer.SetHideOnlyOneClassification(theApp.m_media_lib_setting_data.hide_only_one_classification);
41     if (m_initialized)
42     {
43         m_classifer.ClassifyMedia();
44         ShowClassifyList();
45     }
46 }
47 
SetLeftListSel(wstring item)48 bool CMediaClassifyDlg::SetLeftListSel(wstring item)
49 {
50     int list_size = static_cast<int>(m_list_data_left.size());
51     item = ListItem(LT_MEDIA_LIB, item, m_type).GetDisplayName();   // 将空item转换为用于显示的<未知xxx>
52     //遍历左侧列表,寻找匹配匹配的项目
53     for (int i = 0; i < list_size; i++)
54     {
55         const wstring& name = m_list_data_left[i][0];
56         if (CCommon::StringCompareNoCase(name, item))
57         {
58             m_classify_list_ctrl.SetCurSel(i);
59             ClassifyListClicked(i);
60             return true;
61         }
62     }
63     //如果在媒体库中设置了“将只有一项的分类归到其他类中”,则要寻找的项目可能在“其他”类中
64     int other_index{ -1 };              //项目在“其他”类中的索引
65     //在“其他”类中寻找
66     auto iter = m_classifer.GetMeidaList().find(STR_OTHER_CLASSIFY_TYPE);
67     if (iter != m_classifer.GetMeidaList().end())
68     {
69         int i = 0;
70         for (const auto& song : iter->second)
71         {
72             if (m_type == CMediaClassifier::CT_ARTIST)
73             {
74                 vector<wstring> artist_list;
75                 song.GetArtistList(artist_list);
76                 if (CCommon::IsItemInVector(artist_list, item))
77                 {
78                     other_index = i;
79                     break;
80                 }
81             }
82             else if (m_type == CMediaClassifier::CT_ALBUM)
83             {
84                 if (item == song.GetAlbum())
85                 {
86                     other_index = i;
87                     break;
88                 }
89             }
90             i++;
91         }
92     }
93 
94     if (other_index >= 0)
95     {
96         m_classify_list_ctrl.SetCurSel(m_classify_list_ctrl.GetItemCount() - 1);        //在左侧列表中选中“其他”类
97         ClassifyListClicked(m_classify_list_ctrl.GetItemCount() - 1);
98         m_song_list_ctrl.SetCurSel(other_index);
99         return true;
100     }
101     return false;
102 }
103 
RefreshSongList()104 void CMediaClassifyDlg::RefreshSongList()
105 {
106     ShowSongList();
107 }
108 
ShowClassifyList()109 void CMediaClassifyDlg::ShowClassifyList()
110 {
111     CWaitCursor wait_cursor;
112     auto& media_list{ m_searched ? m_search_result : m_classifer.GetMeidaList() };
113     m_list_data_left.clear();
114     for (const auto& item : media_list)
115     {
116         if (item.first == STR_OTHER_CLASSIFY_TYPE)       //跳过“其他”分类
117             continue;
118 
119         wstring item_name = item.first;
120         if (item_name.empty())
121         {
122             item_name = m_default_str;
123         }
124 
125         CListCtrlEx::RowData row_data;
126         row_data[0] = item_name;
127         row_data[1] = std::to_wstring(item.second.size());
128         m_list_data_left.push_back(std::move(row_data));
129     }
130 
131     if (m_type == CMediaClassifier::CT_BITRATE)
132     {
133         //如果类型是比特率,则对其进行自定义排序
134         std::sort(m_list_data_left.begin(), m_list_data_left.end(), [](const CListCtrlEx::RowData& a, const CListCtrlEx::RowData& b)
135             {
136                 wstring str_a = a.at(0);
137                 wstring str_b = b.at(0);
138 
139                 auto normalize_string = [](wstring& str)
140                 {
141                     if (!str.empty() && (str[0] < L'0' || str[0] > L'9'))
142                         str = str.substr(1);
143                     if (str.size() < 5)
144                         str = wstring(5 - str.size(), L'0') + str;
145                 };
146 
147                 normalize_string(str_a);
148                 normalize_string(str_b);
149                 return str_a < str_b;
150             });
151     }
152 
153     //将“其他”分类放到列表的最后面
154     auto iter = media_list.find(STR_OTHER_CLASSIFY_TYPE);
155     if (iter != media_list.end())
156     {
157         CListCtrlEx::RowData row_data;
158         row_data[0] = theApp.m_str_table.LoadText(L"TXT_CLASSIFY_OTHER");
159         row_data[1] = std::to_wstring(iter->second.size());
160         m_list_data_left.push_back(std::move(row_data));
161     }
162     m_classify_list_ctrl.SetListData(&m_list_data_left);
163 }
164 
ShowSongList()165 void CMediaClassifyDlg::ShowSongList()
166 {
167     CWaitCursor wait_cursor;
168     auto& media_list{ m_searched ? m_search_result : m_classifer.GetMeidaList() };
169 
170     m_list_data_right.clear();
171     m_right_items.clear();
172     int highlight_item{ -1 };
173     int right_index{ 0 };
174     for (int index : m_left_selected_items)
175     {
176         CString str_selected = GetClassifyListSelectedString(index);
177 
178         auto iter = media_list.find(wstring(str_selected));
179         if (iter != media_list.end())
180         {
181             for (const auto& item : iter->second)
182             {
183                 const SongInfo& song{ CSongDataManager::GetInstance().GetSongInfo3(item) };
184                 m_right_items.push_back(song);  // 更新显示列表同时存储一份右侧列表SongInfo
185 
186                 //判断正在播放项
187                 if (song.IsSameSong(CPlayer::GetInstance().GetCurrentSongInfo()))
188                     highlight_item = right_index;
189 
190                 CListCtrlEx::RowData row_data;
191                 row_data[COL_TITLE] = song.GetTitle();
192                 row_data[COL_ARTIST] = song.GetArtist();
193                 row_data[COL_ALBUM] = song.GetAlbum();
194                 std::wstring track_str;
195                 if (song.track != 0)
196                     track_str = std::to_wstring(song.track);
197                 row_data[COL_TRACK] = track_str;
198                 row_data[COL_GENRE] = song.GetGenre();
199                 row_data[COL_BITRATE] = (song.bitrate == 0 ? L"-" : std::to_wstring(song.bitrate));
200                 row_data[COL_PATH] = song.file_path;
201                 m_list_data_right.push_back(std::move(row_data));
202 
203                 right_index++;
204             }
205         }
206     }
207 
208     m_song_list_ctrl.SetListData(&m_list_data_right);
209     if (CPlayer::GetInstance().IsMediaLibMode())
210     {
211         m_song_list_ctrl.SetHightItem(highlight_item);
212         m_song_list_ctrl.EnsureVisible(highlight_item, FALSE);
213     }
214 }
215 
GetClassifyListSelectedString(int index) const216 CString CMediaClassifyDlg::GetClassifyListSelectedString(int index) const
217 {
218     CString str_selected = m_classify_list_ctrl.GetItemText(index, 0);
219     if (str_selected == m_default_str.c_str())
220         str_selected.Empty();
221     if (str_selected == theApp.m_str_table.LoadText(L"TXT_CLASSIFY_OTHER").c_str())
222         str_selected = STR_OTHER_CLASSIFY_TYPE;
223     return str_selected;
224 }
225 
ClassifyListClicked(int index)226 void CMediaClassifyDlg::ClassifyListClicked(int index)
227 {
228     m_left_selected = true;
229     m_classify_list_ctrl.GetItemSelected(m_left_selected_items);    //获取选中的项目
230     if (index < 0)
231     {
232         SetButtonsEnable(false);
233         return;
234     }
235 
236     CString str_selected = GetClassifyListSelectedString(index);
237     static size_t last_selected_count = 0;
238     if (last_selected_index != index || last_selected_count != m_left_selected_items.size())
239     {
240         m_classify_selected = str_selected;
241         ShowSongList();
242         last_selected_index = index;
243         last_selected_count = m_left_selected_items.size();
244     }
245     m_right_selected_item = -1;           // 点击左侧列表时清空右侧列表选中项
246     m_right_selected_items.clear();
247     m_song_list_ctrl.SelectNone();
248 
249     SetButtonsEnable(/*(index >= 0 && index < m_classify_list_ctrl.GetItemCount()) ||*/ !m_left_selected_items.empty());
250 
251 }
252 
SongListClicked(int index)253 void CMediaClassifyDlg::SongListClicked(int index)
254 {
255     m_left_selected = false;
256     m_right_selected_item = index;
257     m_song_list_ctrl.GetItemSelected(m_right_selected_items);
258     SetButtonsEnable(/*(index >=0 && index < m_song_list_ctrl.GetItemCount()) ||*/ !m_right_selected_items.empty());
259 }
260 
IsItemMatchKeyWord(const SongInfo & song,const wstring & key_word)261 bool CMediaClassifyDlg::IsItemMatchKeyWord(const SongInfo& song, const wstring& key_word)
262 {
263     if (m_type == CMediaClassifier::CT_ARTIST)
264         return IsItemMatchKeyWord(song.artist, key_word);
265     else if (m_type == CMediaClassifier::CT_ALBUM)
266         return IsItemMatchKeyWord(song.album, key_word);
267     else if (m_type == CMediaClassifier::CT_GENRE)
268         return IsItemMatchKeyWord(song.genre, key_word);
269     else if (m_type == CMediaClassifier::CT_YEAR)
270         return IsItemMatchKeyWord(song.get_year(), key_word);
271     return false;
272 }
273 
IsItemMatchKeyWord(const wstring & str,const wstring & key_word)274 bool CMediaClassifyDlg::IsItemMatchKeyWord(const wstring& str, const wstring& key_word)
275 {
276     return theApp.m_chinese_pingyin_res.IsStringMatchWithPingyin(key_word, str);
277 }
278 
QuickSearch(const wstring & key_word)279 void CMediaClassifyDlg::QuickSearch(const wstring& key_word)
280 {
281     m_search_result.clear();
282     std::vector<SongInfo> other_list;
283     for (const auto& item : m_classifer.GetMeidaList())
284     {
285         if (item.first == STR_OTHER_CLASSIFY_TYPE)
286         {
287             for (const auto& song : item.second)
288             {
289                 if (IsItemMatchKeyWord(song, key_word))
290                     other_list.push_back(song);
291             }
292         }
293         else
294         {
295             if (IsItemMatchKeyWord(item.first, key_word))
296                 m_search_result[item.first] = item.second;
297         }
298     }
299     if (!other_list.empty())
300         m_search_result[STR_OTHER_CLASSIFY_TYPE] = other_list;
301 }
302 
SetButtonsEnable()303 void CMediaClassifyDlg::SetButtonsEnable()
304 {
305     bool play_enable;
306     if (m_left_selected)
307         play_enable = (m_classify_list_ctrl.GetCurSel() >= 0);
308     else
309         play_enable = (m_song_list_ctrl.GetCurSel() >= 0);
310     SetButtonsEnable(play_enable);
311 }
312 
SetButtonsEnable(bool enable)313 void CMediaClassifyDlg::SetButtonsEnable(bool enable)
314 {
315     CWnd* pParent = GetParentWindow();
316     ::SendMessage(pParent->GetSafeHwnd(), WM_PLAY_SELECTED_BTN_ENABLE, WPARAM(enable), 0);
317 }
318 
OnTabEntered()319 void CMediaClassifyDlg::OnTabEntered()
320 {
321     SetButtonsEnable();
322     if (!m_initialized)
323     {
324         CWaitCursor wait_cursor;
325         m_classifer.ClassifyMedia();
326         ShowClassifyList();
327 
328         //设置左侧列表默认选中项
329         if (CPlayer::GetInstance().IsMediaLibMode())
330             SetLeftListSel(CPlayer::GetInstance().GetMedialibItemName());
331 
332         m_initialized = true;
333     }
334 }
335 
GetNewPlaylistName() const336 wstring CMediaClassifyDlg::GetNewPlaylistName() const
337 {
338     std::wstring default_name;
339     //如果选中了左侧列表,则添加到新建播放列表时名称自动填上选中项的名称
340     if (m_classify_selected != STR_OTHER_CLASSIFY_TYPE)
341         default_name = m_classify_selected;
342     CCommon::FileNameNormalize(default_name);
343     return default_name;
344 }
345 
GetClassificationType() const346 CMediaClassifier::ClassificationType CMediaClassifyDlg::GetClassificationType() const
347 {
348     return m_type;
349 }
350 
GetClassificationItemName() const351 std::wstring CMediaClassifyDlg::GetClassificationItemName() const
352 {
353     if (m_left_selected_items.size() > 1)    // 左侧列表有多个选中项时返回<其他>
354         return STR_OTHER_CLASSIFY_TYPE;
355     return m_classify_selected;
356 }
357 
CalculateClassifyListColumeWidth(std::vector<int> & width)358 void CMediaClassifyDlg::CalculateClassifyListColumeWidth(std::vector<int>& width)
359 {
360     CRect rect;
361     m_classify_list_ctrl.GetWindowRect(rect);
362     width.resize(2);
363 
364     width[1] = theApp.DPI(50);
365     width[0] = rect.Width() - width[1] - theApp.DPI(20) - 1;
366 }
367 
GetSongsSelected(std::vector<SongInfo> & song_list) const368 void CMediaClassifyDlg::GetSongsSelected(std::vector<SongInfo>& song_list) const
369 {
370     if (m_left_selected)
371     {
372         //如果选中了左侧列表,则把选中分类下的所有曲目的路径添加到song_list中
373         song_list.clear();
374         auto& media_list{ m_searched ? m_search_result : m_classifer.GetMeidaList() };
375         for (int index : m_left_selected_items)
376         {
377             wstring str_selected{ GetClassifyListSelectedString(index) };
378             auto iter = media_list.find(str_selected);
379             if (iter != media_list.end())
380             {
381                 for (const auto& item : iter->second)
382                 {
383                     song_list.push_back(item);
384                 }
385             }
386         }
387     }
388     else
389     {
390         CMediaLibTabDlg::GetSongsSelected(song_list);
391     }
392 }
393 
GetSongList() const394 const vector<SongInfo>& CMediaClassifyDlg::GetSongList() const
395 {
396     return m_right_items;
397 }
398 
GetItemSelected() const399 int CMediaClassifyDlg::GetItemSelected() const
400 {
401     return m_right_selected_item;
402 }
403 
GetItemsSelected() const404 const vector<int>& CMediaClassifyDlg::GetItemsSelected() const
405 {
406     return m_right_selected_items;
407 }
408 
AfterDeleteFromDisk(const std::vector<SongInfo> & files)409 void CMediaClassifyDlg::AfterDeleteFromDisk(const std::vector<SongInfo>& files)
410 {
411     //删除成功,则刷新列表
412     m_classifer.RemoveFiles(files);
413     ShowSongList();
414 }
415 
GetSelectedString() const416 wstring CMediaClassifyDlg::GetSelectedString() const
417 {
418     return m_selected_string;
419 }
420 
DoDataExchange(CDataExchange * pDX)421 void CMediaClassifyDlg::DoDataExchange(CDataExchange* pDX)
422 {
423     CMediaLibTabDlg::DoDataExchange(pDX);
424     DDX_Control(pDX, IDC_CLASSIFY_LIST, m_classify_list_ctrl);
425     DDX_Control(pDX, IDC_SONG_LIST, m_song_list_ctrl);
426     DDX_Control(pDX, IDC_MFCEDITBROWSE1, m_search_edit);
427     DDX_Control(pDX, IDC_HSPLITER_STATIC, m_splitter_ctrl);
428 }
429 
430 
BEGIN_MESSAGE_MAP(CMediaClassifyDlg,CMediaLibTabDlg)431 BEGIN_MESSAGE_MAP(CMediaClassifyDlg, CMediaLibTabDlg)
432     ON_NOTIFY(NM_CLICK, IDC_CLASSIFY_LIST, &CMediaClassifyDlg::OnNMClickClassifyList)
433     ON_NOTIFY(NM_RCLICK, IDC_CLASSIFY_LIST, &CMediaClassifyDlg::OnNMRClickClassifyList)
434     ON_EN_CHANGE(IDC_MFCEDITBROWSE1, &CMediaClassifyDlg::OnEnChangeMfceditbrowse1)
435     ON_MESSAGE(WM_SEARCH_EDIT_BTN_CLICKED, &CMediaClassifyDlg::OnSearchEditBtnClicked)
436     ON_NOTIFY(NM_CLICK, IDC_SONG_LIST, &CMediaClassifyDlg::OnNMClickSongList)
437     ON_NOTIFY(NM_RCLICK, IDC_SONG_LIST, &CMediaClassifyDlg::OnNMRClickSongList)
438     ON_NOTIFY(NM_DBLCLK, IDC_CLASSIFY_LIST, &CMediaClassifyDlg::OnNMDblclkClassifyList)
439     ON_NOTIFY(NM_DBLCLK, IDC_SONG_LIST, &CMediaClassifyDlg::OnNMDblclkSongList)
440     ON_NOTIFY(HDN_ITEMCLICK, 0, &CMediaClassifyDlg::OnHdnItemclickSongList)
441     ON_WM_SIZE()
442     ON_WM_DESTROY()
443     ON_WM_INITMENU()
444 END_MESSAGE_MAP()
445 
446 
447 // CMediaClassifyDlg 消息处理程序
448 
449 
450 BOOL CMediaClassifyDlg::OnInitDialog()
451 {
452     CMediaLibTabDlg::OnInitDialog();
453 
454     // TODO:  在此添加额外的初始化
455 
456     //初始化左侧列表
457     m_classify_list_ctrl.SetExtendedStyle(m_classify_list_ctrl.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_LABELTIP);
458     wstring title_name;
459     if (m_type == CMediaClassifier::CT_ARTIST)
460         title_name = theApp.m_str_table.LoadText(L"TXT_ARTIST");
461     else if (m_type == CMediaClassifier::CT_ALBUM)
462         title_name = theApp.m_str_table.LoadText(L"TXT_ALBUM");
463     else if (m_type == CMediaClassifier::CT_GENRE)
464         title_name = theApp.m_str_table.LoadText(L"TXT_GENRE");
465     else if (m_type == CMediaClassifier::CT_YEAR)
466         title_name = theApp.m_str_table.LoadText(L"TXT_YEAR");
467     else if (m_type == CMediaClassifier::CT_TYPE)
468         title_name = theApp.m_str_table.LoadText(L"TXT_FILE_TYPE");
469     else if (m_type == CMediaClassifier::CT_BITRATE)
470         title_name = theApp.m_str_table.LoadText(L"TXT_BITRATE");
471     else if (m_type == CMediaClassifier::CT_RATING)
472         title_name = theApp.m_str_table.LoadText(L"TXT_RATING");
473     CRect rc_classify_list;
474     m_classify_list_ctrl.GetWindowRect(rc_classify_list);
475     std::vector<int> width;
476     CalculateClassifyListColumeWidth(width);
477     m_classify_list_ctrl.InsertColumn(0, title_name.c_str(), LVCFMT_LEFT, width[0]);
478     m_classify_list_ctrl.InsertColumn(1, theApp.m_str_table.LoadText(L"TXT_NUM_OF_TRACK").c_str(), LVCFMT_LEFT, width[1]);
479     //ShowClassifyList();
480 
481     //初始化右侧列表
482     m_song_list_ctrl.SetExtendedStyle(m_song_list_ctrl.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_LABELTIP);
483     //CRect rc_song_list;
484     //m_song_list_ctrl.GetWindowRect(rc_song_list);
485     m_song_list_ctrl.InsertColumn(0, theApp.m_str_table.LoadText(L"TXT_TITLE").c_str(), LVCFMT_LEFT, theApp.DPI(150));
486     m_song_list_ctrl.InsertColumn(1, theApp.m_str_table.LoadText(L"TXT_ARTIST").c_str(), LVCFMT_LEFT, theApp.DPI(100));
487     m_song_list_ctrl.InsertColumn(2, theApp.m_str_table.LoadText(L"TXT_ALBUM").c_str(), LVCFMT_LEFT, theApp.DPI(150));
488     m_song_list_ctrl.InsertColumn(3, theApp.m_str_table.LoadText(L"TXT_TRACK_NUM").c_str(), LVCFMT_LEFT, theApp.DPI(60));
489     m_song_list_ctrl.InsertColumn(4, theApp.m_str_table.LoadText(L"TXT_GENRE").c_str(), LVCFMT_LEFT, theApp.DPI(100));
490     m_song_list_ctrl.InsertColumn(5, theApp.m_str_table.LoadText(L"TXT_BITRATE").c_str(), LVCFMT_LEFT, theApp.DPI(60));
491     m_song_list_ctrl.InsertColumn(6, theApp.m_str_table.LoadText(L"TXT_FILE_PATH").c_str(), LVCFMT_LEFT, theApp.DPI(600));
492     m_song_list_ctrl.SetCtrlAEnable(true);
493 
494     if (m_type == CMediaClassifier::CT_ARTIST)
495         m_search_edit.SetCueBanner(theApp.m_str_table.LoadText(L"TXT_SEARCH_PROMPT_ARTIST").c_str(), TRUE);
496     else if (m_type == CMediaClassifier::CT_ALBUM)
497         m_search_edit.SetCueBanner(theApp.m_str_table.LoadText(L"TXT_SEARCH_PROMPT_ALBUM").c_str(), TRUE);
498     else if (m_type == CMediaClassifier::CT_GENRE)
499         m_search_edit.SetCueBanner(theApp.m_str_table.LoadText(L"TXT_SEARCH_PROMPT_GENRE").c_str(), TRUE);
500     else if (m_type == CMediaClassifier::CT_YEAR)
501         m_search_edit.SetCueBanner(theApp.m_str_table.LoadText(L"TXT_SEARCH_PROMPT_YEAR").c_str(), TRUE);
502     else if (m_type == CMediaClassifier::CT_TYPE)
503         m_search_edit.SetCueBanner(theApp.m_str_table.LoadText(L"TXT_SEARCH_PROMPT_FILE_TYPE").c_str(), TRUE);
504     else if (m_type == CMediaClassifier::CT_BITRATE)
505         m_search_edit.SetCueBanner(theApp.m_str_table.LoadText(L"TXT_SEARCH_PROMPT_BITRATE").c_str(), TRUE);
506     else if (m_type == CMediaClassifier::CT_RATING)
507         m_search_edit.EnableWindow(FALSE);
508     else
509         m_search_edit.SetCueBanner(theApp.m_str_table.LoadText(L"TXT_SEARCH_PROMPT").c_str(), TRUE);
510 
511     //初始化分隔条
512     m_splitter_ctrl.AttachCtrlAsLeftPane(IDC_CLASSIFY_LIST);
513     m_splitter_ctrl.AttachCtrlAsLeftPane(IDC_MFCEDITBROWSE1);
514     m_splitter_ctrl.AttachCtrlAsRightPane(IDC_SONG_LIST);
515 
516     return TRUE;  // return TRUE unless you set the focus to a control
517                   // 异常: OCX 属性页应返回 FALSE
518 }
519 
520 
OnNMClickClassifyList(NMHDR * pNMHDR,LRESULT * pResult)521 void CMediaClassifyDlg::OnNMClickClassifyList(NMHDR* pNMHDR, LRESULT* pResult)
522 {
523     LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
524     // TODO: 在此添加控件通知处理程序代码
525     ClassifyListClicked(pNMItemActivate->iItem);
526     *pResult = 0;
527 }
528 
529 
OnNMRClickClassifyList(NMHDR * pNMHDR,LRESULT * pResult)530 void CMediaClassifyDlg::OnNMRClickClassifyList(NMHDR* pNMHDR, LRESULT* pResult)
531 {
532     LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
533     // TODO: 在此添加控件通知处理程序代码
534     ClassifyListClicked(pNMItemActivate->iItem);
535     m_selected_string = m_classify_list_ctrl.GetItemText(pNMItemActivate->iItem, pNMItemActivate->iSubItem);
536 
537     if (!m_left_selected_items.empty())
538     {
539         //弹出右键菜单
540         CMenu* pMenu = theApp.m_menu_mgr.GetMenu(MenuMgr::LibLeftMenu);
541         ASSERT(pMenu != nullptr);
542         if (pMenu != nullptr)
543         {
544             m_classify_list_ctrl.ShowPopupMenu(pMenu, pNMItemActivate->iItem, this);
545         }
546     }
547 
548     *pResult = 0;
549 }
550 
551 
OnEnChangeMfceditbrowse1()552 void CMediaClassifyDlg::OnEnChangeMfceditbrowse1()
553 {
554     // TODO:  如果该控件是 RICHEDIT 控件,它将不
555     // 发送此通知,除非重写 CMediaLibTabDlg::OnInitDialog()
556     // 函数并调用 CRichEditCtrl().SetEventMask(),
557     // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
558 
559     // TODO:  在此添加控件通知处理程序代码
560     CString str;
561     m_search_edit.GetWindowText(str);
562     QuickSearch(wstring(str));
563     m_searched = !str.IsEmpty();
564     ShowClassifyList();
565     m_song_list_ctrl.DeleteAllItems();
566     last_selected_index = -2;
567 }
568 
569 
OnSearchEditBtnClicked(WPARAM wParam,LPARAM lParam)570 afx_msg LRESULT CMediaClassifyDlg::OnSearchEditBtnClicked(WPARAM wParam, LPARAM lParam)
571 {
572     //点击搜索框中的叉按钮时清除搜索结果
573     if (m_searched)
574     {
575         //清除搜索结果
576         m_searched = false;
577         m_search_edit.SetWindowText(_T(""));
578         ShowClassifyList();
579         m_song_list_ctrl.DeleteAllItems();
580     }
581     return 0;
582 }
583 
584 
OnNMClickSongList(NMHDR * pNMHDR,LRESULT * pResult)585 void CMediaClassifyDlg::OnNMClickSongList(NMHDR* pNMHDR, LRESULT* pResult)
586 {
587     LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
588     // TODO: 在此添加控件通知处理程序代码
589     SongListClicked(pNMItemActivate->iItem);
590     *pResult = 0;
591 }
592 
593 
OnNMRClickSongList(NMHDR * pNMHDR,LRESULT * pResult)594 void CMediaClassifyDlg::OnNMRClickSongList(NMHDR* pNMHDR, LRESULT* pResult)
595 {
596     LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
597     // TODO: 在此添加控件通知处理程序代码
598     SongListClicked(pNMItemActivate->iItem);
599     m_selected_string = m_song_list_ctrl.GetItemText(pNMItemActivate->iItem, pNMItemActivate->iSubItem);
600 
601     if (!m_right_selected_items.empty())
602     {
603         //弹出右键菜单
604         CMenu* pMenu = theApp.m_menu_mgr.GetMenu(MenuMgr::LibRightMenu);
605         ASSERT(pMenu != nullptr);
606         if (pMenu != nullptr)
607         {
608             m_song_list_ctrl.ShowPopupMenu(pMenu, pNMItemActivate->iItem, this);
609         }
610     }
611 
612     *pResult = 0;
613 }
614 
615 
OnNMDblclkClassifyList(NMHDR * pNMHDR,LRESULT * pResult)616 void CMediaClassifyDlg::OnNMDblclkClassifyList(NMHDR* pNMHDR, LRESULT* pResult)
617 {
618     LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
619     // TODO: 在此添加控件通知处理程序代码
620     OnOK();
621     *pResult = 0;
622 }
623 
624 
OnNMDblclkSongList(NMHDR * pNMHDR,LRESULT * pResult)625 void CMediaClassifyDlg::OnNMDblclkSongList(NMHDR* pNMHDR, LRESULT* pResult)
626 {
627     LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
628     // TODO: 在此添加控件通知处理程序代码
629     OnOK();
630     *pResult = 0;
631 }
632 
633 
OnHdnItemclickSongList(NMHDR * pNMHDR,LRESULT * pResult)634 void CMediaClassifyDlg::OnHdnItemclickSongList(NMHDR* pNMHDR, LRESULT* pResult)
635 {
636     LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);
637     // TODO: 在此添加控件通知处理程序代码
638 
639     if (phdr->hdr.hwndFrom == m_song_list_ctrl.GetHeaderCtrl()->GetSafeHwnd())
640     {
641         static bool ascending = false;
642         ascending = !ascending;
643 
644         static int last_item = -1;
645         if (last_item != phdr->iItem)
646         {
647             last_item = phdr->iItem;
648             ascending = true;
649         }
650 
651         //对右侧列表排序
652         if (m_left_selected_items.size() == 1)  //仅当左侧列表选中了一项时处理
653         {
654             auto& media_list{ m_searched ? m_search_result : m_classifer.GetMeidaList() };
655             auto iter = media_list.find(m_classify_selected);
656             if (iter != media_list.end())
657             {
658                 SortMode sort_mode = SM_UNSORT;
659                 switch (phdr->iItem)
660                 {
661                 case CMediaClassifyDlg::COL_TITLE: sort_mode = ascending ? SM_U_TITLE : SM_D_TITLE; break;
662                 case CMediaClassifyDlg::COL_ARTIST: sort_mode = ascending ? SM_U_ARTIST : SM_D_ARTIST; break;
663                 case CMediaClassifyDlg::COL_ALBUM: sort_mode = ascending ? SM_U_ALBUM : SM_D_ALBUM; break;
664                 case CMediaClassifyDlg::COL_TRACK: sort_mode = ascending ? SM_U_TRACK : SM_D_TRACK; break;
665                 case CMediaClassifyDlg::COL_GENRE: sort_mode = ascending ? SM_U_GENRE : SM_D_GENRE; break;
666                 case CMediaClassifyDlg::COL_BITRATE: sort_mode = ascending ? SM_U_BITRATE : SM_D_BITRATE; break;
667                 case CMediaClassifyDlg::COL_PATH: sort_mode = ascending ? SM_U_PATH : SM_D_PATH; break;
668                 default: break;
669                 }
670                 if (sort_mode != SM_UNSORT)
671                 {
672                     std::sort(iter->second.begin(), iter->second.end(), SongInfo::GetSortFunc(sort_mode));
673                     ShowSongList();
674                 }
675             }
676         }
677     }
678 
679     *pResult = 0;
680 }
681 
682 
OnSize(UINT nType,int cx,int cy)683 void CMediaClassifyDlg::OnSize(UINT nType, int cx, int cy)
684 {
685     CMediaLibTabDlg::OnSize(nType, cx, cy);
686 
687     // TODO: 在此处添加消息处理程序代码
688     if (nType != SIZE_MINIMIZED && m_classify_list_ctrl.m_hWnd)
689     {
690         std::vector<int> width;
691         CalculateClassifyListColumeWidth(width);
692         for (size_t i{}; i < width.size(); i++)
693             m_classify_list_ctrl.SetColumnWidth(i, width[i]);
694     }
695 }
696 
697 
OnDestroy()698 void CMediaClassifyDlg::OnDestroy()
699 {
700     CMediaLibTabDlg::OnDestroy();
701 
702     // TODO: 在此处添加消息处理程序代码
703     m_classifer.ClearResult();
704 }
705 
706 
OnInitMenu(CMenu * pMenu)707 void CMediaClassifyDlg::OnInitMenu(CMenu* pMenu)
708 {
709     CMediaLibTabDlg::OnInitMenu(pMenu);
710 
711     //设置“添加到播放列表”子菜单状态
712     //未选中状态不会弹出右键菜单,因此“添加到播放列表”子菜单全部设置为可用状态
713     for (UINT id = ID_ADD_TO_DEFAULT_PLAYLIST; id < ID_ADD_TO_MY_FAVOURITE + ADD_TO_PLAYLIST_MAX_SIZE + 1; id++)
714     {
715         pMenu->EnableMenuItem(id, MF_BYCOMMAND | MF_ENABLED);
716     }
717     pMenu->EnableMenuItem(ID_ADD_TO_NEW_PLAYLIST, MF_BYCOMMAND | MF_ENABLED);
718     pMenu->EnableMenuItem(ID_ADD_TO_OTHER_PLAYLIST, MF_BYCOMMAND | MF_ENABLED);
719 }
720