1 #pragma once 2 #include "CPlayerUIBase.h" 3 #include "ListCache.h" 4 5 class CUiSearchBox; 6 7 //定义界面元素 8 namespace UiElement 9 { 10 //所有界面元素的基类 11 class Element 12 { 13 public: 14 struct Value //一个布局的数值 15 { 16 Value(bool _is_vertical, Element* _owner); 17 void FromString(const std::string str); 18 int GetValue(CRect parent_rect) const; // 获取实际显示的数值 19 bool IsValid() const; // 返回true说明设置过数值 20 private: 21 int value{ 0 }; // 如果is_percentate为true则值为百分比,否则为实际值 22 bool valid{ false }; // 如果还没有设置过数值,则为false 23 bool is_percentage{ false }; // 数值是否为百分比 24 bool is_vertical{ false }; // 数值是否为垂直方向的 25 Element* owner; 26 }; 27 Value margin_left{ false, this }; 28 Value margin_right{ false, this }; 29 Value margin_top{ true, this }; 30 Value margin_bottom{ true, this }; 31 Value x{ false, this }; 32 Value y{ true, this }; 33 Value width{ false, this }; 34 Value height{ true, this }; 35 Value max_width{ false, this }; 36 Value max_height{ true, this }; 37 Value min_width{ false, this }; 38 Value min_height{ true, this }; 39 Value hide_width{ false, this }; 40 Value hide_height{ true, this }; 41 int proportion{ 0 }; 42 43 Element* pParent{}; //父元素 44 std::vector<std::shared_ptr<Element>> childLst; //子元素列表 45 std::string name; 46 47 virtual void Draw(); //绘制此元素 48 virtual bool IsEnable(CRect parent_rect) const; 49 virtual int GetMaxWidth(CRect parent_rect) const; 50 virtual int GetWidth(CRect parent_rect) const; 51 virtual int GetHeight(CRect parent_rect) const; 52 virtual bool IsWidthValid() const; 53 virtual bool IsHeightValid() const; 54 CRect GetRect() const; //获取此元素在界面中的矩形区域 55 void SetRect(CRect _rect); 56 virtual void ClearRect(); 57 Element* RootElement(); //获取根节点 58 //遍历所有界面元素 59 //visible_only为true时,遇到stackElement时,只遍历stackElement下面可见的子节点 60 void IterateAllElements(std::function<bool(UiElement::Element*)> func, bool visible_only = false); 61 void SetUi(CPlayerUIBase* _ui); 62 void AddChild(std::shared_ptr<Element> child); 63 64 //鼠标消息虚函数。 65 //即使鼠标的位置不在当前元素的矩形区域内,函数仍然会响应,因此在重写这些虚函数时需要先使用rect.PtInRect(point)判断鼠标位置是否在矩形区域内。 LButtonUp(CPoint point)66 virtual void LButtonUp(CPoint point) {} LButtonDown(CPoint point)67 virtual void LButtonDown(CPoint point) {} MouseMove(CPoint point)68 virtual void MouseMove(CPoint point) {} RButtunUp(CPoint point)69 virtual bool RButtunUp(CPoint point) { return false; } RButtonDown(CPoint point)70 virtual void RButtonDown(CPoint point) {} MouseWheel(int delta,CPoint point)71 virtual bool MouseWheel(int delta, CPoint point) { return false; } DoubleClick(CPoint point)72 virtual bool DoubleClick(CPoint point) { return false; } MouseLeave()73 virtual void MouseLeave() {} 74 75 protected: 76 CRect ParentRect() const; 77 virtual void CalculateRect(); //计算此元素在界面中的矩形区域 78 static void IterateElements(UiElement::Element* parent_element, std::function<bool(UiElement::Element*)> func, bool visible_only = false); 79 80 CRect rect; //用于保存计算得到的元素的矩形区域 81 CPlayerUIBase* ui{}; 82 }; 83 84 namespace TooltipIndex 85 { 86 const int PLAYLIST = 900; 87 const int TAB_ELEMENT = 901; 88 const int PLAYLIST_DROP_DOWN_BTN = 902; 89 const int PLAYLIST_MENU_BTN = 903; 90 const int SEARCHBOX_CLEAR_BTN = 904; 91 } 92 93 //布局 94 class Layout : public Element 95 { 96 public: 97 enum Type 98 { 99 Vertical, 100 Horizontal, 101 }; 102 Type type; 103 void CalculateChildrenRect(); //计算布局中所有子元素的位置 104 virtual void Draw() override; 105 }; 106 107 //包含多个元素的堆叠元素,同时只能显示一个元素 108 class StackElement : public Element 109 { 110 public: 111 void SetCurrentElement(int index); 112 void SwitchDisplay(bool previous = false); 113 virtual void Draw() override; 114 bool click_to_switch{}; //鼠标点击时切换 115 bool hover_to_switch{}; //鼠标指向时切换 116 bool scroll_to_switch{}; //鼠标滚轮切换 117 bool show_indicator{}; 118 int indicator_offset{}; 119 bool mouse_hover{}; 120 IPlayerUI::UIButton indicator{}; //指示器 121 int GetCurIndex() const; 122 123 protected: 124 std::shared_ptr<Element> CurrentElement(); 125 std::shared_ptr<Element> GetElement(int index); 126 127 int cur_index{}; 128 }; 129 130 //半透明的矩形 131 class Rectangle : public Element 132 { 133 public: 134 bool no_corner_radius{}; 135 bool theme_color{ true }; 136 CPlayerUIBase::ColorMode color_mode{ CPlayerUIBase::RCM_AUTO }; 137 virtual void Draw() override; 138 }; 139 140 //按钮 141 class Button : public Element 142 { 143 public: 144 CPlayerUIBase::BtnKey key; //按钮的类型 145 bool big_icon{}; //如果为false,则图标尺寸为16x16,否则为20x20 146 bool show_text{}; //是否在图标右侧显示文本 147 int font_size{ 9 }; //字体大小,仅在show_text为true时有效 148 virtual void Draw() override; 149 void FromString(const std::string& key_type); 150 virtual int GetMaxWidth(CRect parent_rect) const override; 151 virtual void ClearRect() override; 152 }; 153 154 //文本 155 class Text : public Element 156 { 157 public: 158 std::wstring text; 159 Alignment align{}; //对齐方式 160 enum Style //文本的样式 161 { 162 Static, //静止的文本 163 Scroll, //滚动的文本 164 Scroll2 //另一种滚动的文本(只朝一个方向滚动) 165 }; 166 Style style; 167 168 enum Type //文本的类型 169 { 170 UserDefine, //用户指定(text的值) 171 Title, //歌曲标题 172 Artist, //歌曲艺术家 173 Album, //歌曲唱片集 174 ArtistTitle, //艺术家 - 标题 175 ArtistAlbum, //艺术家 - 唱片集 176 Format, //歌曲格式 177 PlayTime, //播放时间 178 PlayTimeAndVolume //显示为播放时间,如果正在调整音量,则显示当前音量,一段时间后恢复 179 }; 180 181 Type type; 182 int font_size{ 9 }; 183 bool width_follow_text{}; 184 CPlayerUIBase::ColorMode color_mode{ CPlayerUIBase::RCM_AUTO }; 185 bool show_volume{}; //当type为PlayTimeAndVolume时有效,如果为true,则显示为音量 186 187 virtual void Draw() override; 188 virtual int GetMaxWidth(CRect parent_rect) const override; 189 std::wstring GetText() const; 190 191 private: 192 mutable CDrawCommon::ScrollInfo scroll_info; 193 }; 194 195 //专辑封面 196 class AlbumCover : public Element 197 { 198 public: 199 bool square{}; 200 bool show_info{}; 201 virtual void Draw() override; 202 virtual void CalculateRect() override; 203 }; 204 205 //频谱分析 206 class Spectrum : public Element 207 { 208 public: 209 bool draw_reflex{}; //是否绘制倒影 210 bool fixed_width{}; //每个柱形是否使用相同的宽度 211 Alignment align{ Alignment::LEFT }; //对齐方式 212 CUIDrawer::SpectrumCol type{ CUIDrawer::SC_64 }; //频谱分析的类型 213 virtual void Draw() override; 214 virtual bool IsEnable(CRect parent_rect) const override; 215 }; 216 217 //曲目信息(包含播放状态、文件名、歌曲标识、速度) 218 class TrackInfo : public Element 219 { 220 public: 221 int font_size{ 9 }; 222 virtual void Draw() override; 223 }; 224 225 //工具栏 226 class Toolbar : public Element 227 { 228 public: 229 bool show_translate_btn{}; //是否在工具栏上显示“显示歌词翻译”按钮 230 virtual void Draw() override; 231 }; 232 233 //进度条 234 class ProgressBar : public Element 235 { 236 public: 237 bool show_play_time{}; 238 bool play_time_both_side{}; 239 virtual void Draw() override; 240 }; 241 242 //歌词 243 class Lyrics : public Element 244 { 245 public: 246 bool no_background = false; // 总是不使用歌词背景 247 bool use_default_font = false; // 固定使用默认字体 248 int font_size{ 9 }; // 使用默认字体时的字号 249 bool show_song_info = false; //没有歌词时总是显示歌曲信息 250 virtual void Draw() override; 251 virtual void ClearRect() override; 252 protected: 253 bool IsParentRectangle() const; //判断父元素中是否有矩形元素 254 }; 255 256 //音量 257 class Volume : public Element 258 { 259 public: 260 bool show_text{ true }; //是否在音量图标旁边显示文本 261 bool adj_btn_on_top{ false }; //音量调节按钮是否显示在音量图标的上方 262 virtual void Draw() override; 263 }; 264 265 //节拍指示 266 class BeatIndicator : public Element 267 { 268 public: 269 virtual void Draw() override; 270 }; 271 272 //列表元素 273 class ListElement : public Element 274 { 275 public: 276 friend class CPlayerUIBase; 277 278 virtual void Draw() override; 279 virtual void LButtonUp(CPoint point) override; 280 virtual void LButtonDown(CPoint point) override; 281 virtual void MouseMove(CPoint point) override; 282 virtual bool RButtunUp(CPoint point) override; 283 void ShowContextMenu(CMenu* menu, CWnd* cmd_reciver); 284 virtual void RButtonDown(CPoint point) override; 285 virtual bool MouseWheel(int delta, CPoint point) override; 286 virtual void MouseLeave() override; 287 virtual bool DoubleClick(CPoint point) override; 288 virtual void ClearRect() override; 289 290 void EnsureItemVisible(int index); //确保指定项在播放列表中可见 291 void EnsureHighlightItemVisible(); //确保高亮行可见 292 void RestrictOffset(); //将播放列表偏移量限制在正确的范围 293 void CalculateItemRects(); //计算播放列表中每一项的矩形区域,保存在playlist_info.item_rects中 294 int ItemHeight() const; 295 void SetItemSelected(int index); //设置单个项目选中 296 int GetItemSelected() const; //获取单个项目选中 297 void SetItemsSelected(const vector<int>& indexes); //设置多个项目选中 298 void GetItemsSelected(vector<int>& indexes) const; //获取多个项目选中 299 bool IsItemSelected(int index) const; //判断指定行是否选中 300 bool IsMultipleSelected() const; //是否选中了超过1个项目 301 302 void SelectAll(); //全选(仅IsMultipleSelectionEnable返回true时支持) 303 void SelectNone(); //取消所有选择 304 void SelectReversed(); //反向选择(仅IsMultipleSelectionEnable返回true时支持) 305 306 virtual std::wstring GetItemText(int row, int col) = 0; 307 virtual int GetRowCount() = 0; 308 virtual int GetColumnCount() = 0; 309 virtual int GetColumnWidth(int col, int total_width) = 0; GetIcon(int row)310 virtual IconMgr::IconType GetIcon(int row) { return IconMgr::IT_NO_ICON; } HasIcon()311 virtual bool HasIcon() { return false; } GetEmptyString()312 virtual std::wstring GetEmptyString() { return std::wstring(); } //列表为空时显示的文本 GetHighlightRow()313 virtual int GetHighlightRow() { return -1; } GetColumnScrollTextWhenSelected()314 virtual int GetColumnScrollTextWhenSelected() { return -1; } //获取选中时需要滚动显示的列 ShowTooltip()315 virtual bool ShowTooltip() { return false; } GetToolTipText(int row)316 virtual std::wstring GetToolTipText(int row) { return std::wstring(); } GetToolTipIndex()317 virtual int GetToolTipIndex() const { return 0; } GetContextMenu(bool item_selected)318 virtual CMenu* GetContextMenu(bool item_selected) { return nullptr; } GetCmdRecivedWnd()319 virtual CWnd* GetCmdRecivedWnd() { return nullptr; } //获取右键菜单命令的接收窗口,如果返回空指针,则在CUIWindowCmdHelper中响应 OnDoubleClicked()320 virtual void OnDoubleClicked() {}; OnClicked()321 virtual void OnClicked() {}; GetHoverButtonCount()322 virtual int GetHoverButtonCount() { return 0; } //获取鼠标指向一行时要显示的按钮数量 GetHoverButtonColumn()323 virtual int GetHoverButtonColumn() { return 0; } //获取鼠标指向时要显示的按钮所在列 GetHoverButtonIcon(int index,int row)324 virtual IconMgr::IconType GetHoverButtonIcon(int index, int row) { return IconMgr::IT_NO_ICON; } //获取鼠标指向一行时按钮的图标 GetHoverButtonTooltip(int index,int row)325 virtual std::wstring GetHoverButtonTooltip(int index, int row) { return std::wstring(); } //获取鼠标指向一行时按钮的鼠标提示 OnHoverButtonClicked(int btn_index,int row)326 virtual void OnHoverButtonClicked(int btn_index, int row) {} //响应鼠标指向时按钮点击 327 IPlayerUI::UIButton& GetHoverButtonState(int btn_index); //获取储存鼠标指向时按钮信息的结构体 GetUnHoverIconCount(int row)328 virtual int GetUnHoverIconCount(int row) { return 0; } //获取鼠标未指向的行要显示的图标数量(列为GetHoverButtonColumn返回的列) GetUnHoverIcon(int index,int row)329 virtual IconMgr::IconType GetUnHoverIcon(int index, int row) { return IconMgr::IT_NO_ICON; } //获取鼠标未指向的行要显示的图标 330 IsMultipleSelectionEnable()331 virtual bool IsMultipleSelectionEnable() { return false; } //是否允许多选 332 virtual void OnRowCountChanged(); //当列表行数发生变化时响应此函数 333 334 virtual void QuickSearch(const std::wstring& key_word); //根据关键执行快速搜索(筛选出匹配的项) 335 virtual bool IsItemMatchKeyWord(int row, const std::wstring& key_word); //判断指定行是否匹配关键字(用于快速搜索功能,默认匹配每一列中的文本,只要有一列的文本匹配就返回true,派生类可重写此函数) 336 337 int GetDisplayRowCount(); //获取要显示的行数。(处于搜索状态时返回搜索结果数量,正常状态下同GetRowCount) 338 bool IsRowDisplayed(int row); //判断一行是否显示。(仅处于搜索状态时不匹配的行会返回false) 339 SetRelatedSearchBox(SearchBox * search_box)340 void SetRelatedSearchBox(SearchBox* search_box) { related_search_box = search_box; } 341 342 int item_height{ 28 }; 343 int font_size{ 9 }; 344 345 private: 346 void DisplayRowToAbsoluteRow(int& row); //将显示的行号转换为绝对行号 347 void AbsoluteRowToDisplayRow(int& row); //将绝对行号转换为显示的行号 348 int GetDisplayedIndexByPoint(CPoint point); 349 350 protected: 351 int GetListIndexByPoint(CPoint point); 352 353 protected: 354 bool mouse_pressed{ }; //鼠标左键是否按下 355 bool hover{}; //指标指向播放列表区域 356 CPoint mouse_pos; //鼠标指向的区域 357 CPoint mouse_pressed_pos; //鼠标按下时的位置 358 int mouse_pressed_offset{}; //鼠标按下时播放列表的位移 359 int playlist_offset{}; //当前播放列表滚动的位移 360 std::set<int> items_selected; //选中的序号 361 CDrawCommon::ScrollInfo selected_item_scroll_info; //绘制选中项滚动文本的结构体 362 std::vector<CRect> item_rects; //播放列表中每个项目的矩形区域 363 CRect scrollbar_rect{}; //滚动条的位置 364 CRect scrollbar_handle_rect; //滚动条把手的位置 365 bool scrollbar_hover{}; //鼠标指向滚动条 366 bool scrollbar_handle_pressed{}; //滚动条把手被按下 367 int scroll_handle_length_comp{}; //计算滚动条把手长度时的补偿量 368 std::map<int, IPlayerUI::UIButton> hover_buttons; //鼠标指向时的按钮 369 int last_row_count{}; 370 private: 371 std::vector<int> search_result; //保存搜索结果的序号 372 bool searched{}; //是否处于搜索状态 373 SearchBox* related_search_box{}; //关联的键框 374 }; 375 376 377 //播放列表 378 class Playlist : public ListElement 379 { 380 public: 381 enum Column 382 { 383 COL_INDEX, 384 COL_TRACK, 385 COL_TIME, 386 COL_MAX 387 }; 388 389 //鼠标指向一行时显示的按钮 390 enum BtnKey 391 { 392 BTN_PLAY, 393 BTN_ADD, 394 BTN_FAVOURITE, 395 BTN_MAX 396 }; 397 398 // 通过 ListElement 继承 399 std::wstring GetItemText(int row, int col) override; 400 int GetRowCount() override; 401 int GetColumnCount() override; 402 virtual int GetColumnWidth(int col, int total_width) override; 403 virtual std::wstring GetEmptyString() override; 404 virtual int GetHighlightRow() override; 405 virtual int GetColumnScrollTextWhenSelected() override; 406 virtual bool ShowTooltip() override; 407 virtual std::wstring GetToolTipText(int row) override; 408 virtual int GetToolTipIndex() const override; 409 virtual CMenu* GetContextMenu(bool item_selected) override; 410 virtual CWnd* GetCmdRecivedWnd() override; 411 virtual void OnDoubleClicked() override; 412 virtual void OnClicked() override; 413 virtual int GetHoverButtonCount() override; 414 virtual int GetHoverButtonColumn() override; 415 virtual IconMgr::IconType GetHoverButtonIcon(int index, int row) override; 416 virtual std::wstring GetHoverButtonTooltip(int index, int row) override; 417 virtual void OnHoverButtonClicked(int btn_index, int row) override; 418 virtual int GetUnHoverIconCount(int row) override; 419 virtual IconMgr::IconType GetUnHoverIcon(int index, int row) override; 420 IsMultipleSelectionEnable()421 virtual bool IsMultipleSelectionEnable() override { return true; } 422 virtual void OnRowCountChanged() override; 423 424 virtual bool IsItemMatchKeyWord(int row, const std::wstring& key_word); 425 426 private: 427 int last_highlight_row{ -1 }; 428 }; 429 430 //最近播放 431 class RecentPlayedList : public ListElement 432 { 433 public: 434 enum Column 435 { 436 COL_NAME, 437 COL_COUNT, 438 COL_MAX 439 }; 440 static CListCache m_list_cache; // 为RecentPlayedList的绘制缓存最近播放的ListItem,Draw之前调用reload 441 virtual void Draw() override; 442 443 // 通过 ListElement 继承 444 std::wstring GetItemText(int row, int col) override; 445 int GetRowCount() override; 446 int GetColumnCount() override; 447 int GetColumnWidth(int col, int total_width) override; 448 virtual int GetColumnScrollTextWhenSelected() override; 449 virtual IconMgr::IconType GetIcon(int row) override; 450 virtual bool HasIcon() override; 451 virtual void OnDoubleClicked() override; 452 virtual CMenu* GetContextMenu(bool item_selected) override; 453 virtual int GetHoverButtonCount() override; 454 virtual int GetHoverButtonColumn() override; 455 virtual IconMgr::IconType GetHoverButtonIcon(int index, int row) override; 456 virtual std::wstring GetHoverButtonTooltip(int index, int row) override; 457 virtual void OnHoverButtonClicked(int btn_index, int row) override; 458 }; 459 460 //媒体库项目列表 461 class MediaLibItemList : public ListElement 462 { 463 public: 464 CMediaClassifier::ClassificationType type{}; 465 466 enum Column 467 { 468 COL_NAME, 469 COL_COUNT, 470 COL_MAX 471 }; 472 473 //鼠标指向一行时显示的按钮 474 enum BtnKey 475 { 476 BTN_PLAY, 477 BTN_ADD, 478 BTN_MAX 479 }; 480 481 // 通过 ListElement 继承 482 std::wstring GetItemText(int row, int col) override; 483 int GetRowCount() override; 484 int GetColumnCount() override; 485 int GetColumnWidth(int col, int total_width) override; 486 virtual std::wstring GetEmptyString() override; 487 virtual int GetHighlightRow() override; 488 virtual int GetColumnScrollTextWhenSelected() override; 489 virtual CMenu* GetContextMenu(bool item_selected) override; 490 virtual void OnDoubleClicked() override; 491 virtual int GetHoverButtonCount() override; 492 virtual int GetHoverButtonColumn() override; 493 virtual IconMgr::IconType GetHoverButtonIcon(int index, int row) override; 494 virtual std::wstring GetHoverButtonTooltip(int index, int row) override; 495 virtual void OnHoverButtonClicked(int btn_index, int row) override; 496 private: 497 int last_highlight_row{ -1 }; 498 }; 499 500 //当前播放列表指示 501 class PlaylistIndicator : public Element 502 { 503 public: 504 static CListCache m_list_cache; // 为PlaylistIndicator的绘制缓存当前播放的ListItem,Draw之前调用reload 505 virtual void Draw() override; 506 virtual void LButtonUp(CPoint point) override; 507 virtual void LButtonDown(CPoint point) override; 508 virtual void MouseMove(CPoint point) override; 509 virtual void MouseLeave() override; 510 virtual void ClearRect() override; 511 512 int font_size{ 9 }; 513 514 IPlayerUI::UIButton btn_drop_down; 515 IPlayerUI::UIButton btn_menu; 516 CRect rect_name; 517 }; 518 519 class ClassicalControlBar : public Element 520 { 521 public: 522 ClassicalControlBar(); 523 virtual void Draw() override; 524 525 public: 526 bool show_switch_display_btn{}; 527 }; 528 529 //导航栏 530 class NavigationBar : public Element 531 { 532 public: 533 virtual void Draw() override; 534 virtual void LButtonUp(CPoint point) override; 535 virtual void MouseMove(CPoint point) override; 536 virtual bool RButtunUp(CPoint point) override; 537 virtual void MouseLeave() override; 538 539 enum IconType 540 { 541 ICON_AND_TEXT, 542 ICON_ONLY, 543 TEXT_ONLY 544 }; 545 546 enum Orientation 547 { 548 Horizontal, 549 Vertical, 550 }; 551 552 IconType icon_type{}; 553 Orientation orientation{ Horizontal }; 554 int item_space{}; 555 int item_height{ 28 }; 556 int font_size{ 9 }; 557 std::vector<std::string> tab_list; 558 std::vector<CRect> item_rects; 559 std::vector<std::wstring> labels; 560 int SelectedIndex(); 561 int hover_index{ -1 }; 562 private: 563 void FindStackElement(); //查找StackElement 564 bool find_stack_element{}; //如果已经查找过StackElement,则为true 565 StackElement* stack_element{}; 566 int selected_index{}; 567 int last_hover_index{ -1 }; 568 }; 569 570 //媒体库的文件夹列表 571 class MediaLibFolder : public ListElement 572 { 573 public: 574 static CListCache m_list_cache; 575 virtual void Draw() override; 576 577 enum Column 578 { 579 COL_NAME, 580 COL_COUNT, 581 COL_MAX 582 }; 583 584 //鼠标指向一行时显示的按钮 585 enum BtnKey 586 { 587 BTN_PLAY, 588 BTN_ADD, 589 BTN_MAX 590 }; 591 592 // 通过 ListElement 继承 593 std::wstring GetItemText(int row, int col) override; 594 int GetRowCount() override; 595 int GetColumnCount() override; 596 int GetColumnWidth(int col, int total_width) override; 597 virtual int GetHighlightRow() override; 598 virtual int GetColumnScrollTextWhenSelected() override; 599 virtual CMenu* GetContextMenu(bool item_selected) override; 600 virtual void OnDoubleClicked() override; 601 virtual int GetHoverButtonCount() override; 602 virtual int GetHoverButtonColumn() override; 603 virtual IconMgr::IconType GetHoverButtonIcon(int index, int row) override; 604 virtual std::wstring GetHoverButtonTooltip(int index, int row) override; 605 virtual void OnHoverButtonClicked(int btn_index, int row) override; 606 }; 607 608 //媒体库的播放列表列表 609 class MediaLibPlaylist : public ListElement 610 { 611 public: 612 static CListCache m_list_cache; 613 virtual void Draw() override; 614 enum Column 615 { 616 COL_NAME, 617 COL_COUNT, 618 COL_MAX 619 }; 620 621 // 通过 ListElement 继承 622 std::wstring GetItemText(int row, int col) override; 623 int GetRowCount() override; 624 int GetColumnCount() override; 625 int GetColumnWidth(int col, int total_width) override; 626 virtual int GetHighlightRow() override; 627 virtual int GetColumnScrollTextWhenSelected() override; 628 virtual CMenu* GetContextMenu(bool item_selected) override; 629 virtual void OnDoubleClicked() override; 630 virtual int GetHoverButtonCount() override; 631 virtual int GetHoverButtonColumn() override; 632 virtual IconMgr::IconType GetHoverButtonIcon(int index, int row) override; 633 virtual std::wstring GetHoverButtonTooltip(int index, int row) override; 634 virtual void OnHoverButtonClicked(int btn_index, int row) override; 635 }; 636 637 //我喜欢的音乐列表 638 class MyFavouriteList : public ListElement 639 { 640 public: 641 enum Column 642 { 643 COL_INDEX, 644 COL_TRACK, 645 COL_TIME, 646 COL_MAX 647 }; 648 649 //鼠标指向一行时显示的按钮 650 enum BtnKey 651 { 652 BTN_PLAY, 653 BTN_ADD, 654 BTN_MAX 655 }; 656 657 // 通过 ListElement 继承 658 std::wstring GetItemText(int row, int col) override; 659 int GetRowCount() override; 660 int GetColumnCount() override; 661 int GetColumnWidth(int col, int total_width) override; 662 virtual int GetHighlightRow() override; 663 virtual int GetColumnScrollTextWhenSelected() override; 664 virtual CMenu* GetContextMenu(bool item_selected) override; 665 virtual void OnDoubleClicked() override; 666 virtual std::wstring GetEmptyString() override; 667 virtual int GetHoverButtonCount() override; 668 virtual int GetHoverButtonColumn() override; 669 virtual IconMgr::IconType GetHoverButtonIcon(int index, int row) override; 670 virtual std::wstring GetHoverButtonTooltip(int index, int row) override; 671 virtual void OnHoverButtonClicked(int btn_index, int row) override; 672 virtual bool IsMultipleSelectionEnable() override; 673 }; 674 675 //所有曲目列表 676 class AllTracksList : public ListElement 677 { 678 public: 679 enum Column 680 { 681 COL_INDEX, 682 COL_TRACK, 683 COL_TIME, 684 COL_MAX 685 }; 686 687 //鼠标指向一行时显示的按钮 688 enum BtnKey 689 { 690 BTN_PLAY, 691 BTN_ADD, 692 BTN_FAVOURITE, 693 BTN_MAX 694 }; 695 696 // 通过 ListElement 继承 697 std::wstring GetItemText(int row, int col) override; 698 int GetRowCount() override; 699 int GetColumnCount() override; 700 int GetColumnWidth(int col, int total_width) override; 701 virtual int GetHighlightRow() override; 702 virtual int GetColumnScrollTextWhenSelected() override; 703 virtual CMenu* GetContextMenu(bool item_selected) override; 704 virtual void OnDoubleClicked() override; 705 virtual std::wstring GetEmptyString() override; 706 virtual int GetHoverButtonCount() override; 707 virtual int GetHoverButtonColumn() override; 708 virtual IconMgr::IconType GetHoverButtonIcon(int index, int row) override; 709 virtual std::wstring GetHoverButtonTooltip(int index, int row) override; 710 virtual void OnHoverButtonClicked(int btn_index, int row) override; 711 virtual int GetUnHoverIconCount(int row) override; 712 virtual IconMgr::IconType GetUnHoverIcon(int index, int row) override; 713 virtual bool IsMultipleSelectionEnable() override; 714 715 private: 716 int last_highlight_row{ -1 }; 717 }; 718 719 //迷你频谱 720 class MiniSpectrum : public Element 721 { 722 public: 723 virtual void Draw() override; 724 }; 725 726 //占位符 727 class PlaceHolder : public Element 728 { 729 public: 730 virtual int GetWidth(CRect parent_rect) const override; 731 virtual int GetHeight(CRect parent_rect) const override; 732 virtual bool IsWidthValid() const override; 733 734 bool show_when_use_system_titlebar{}; //仅当开启“使用系统标准标题栏”时才显示 735 736 private: 737 bool IsHide() const; 738 }; 739 740 //树控件 741 //派生类只需要继承GetRootNodes函数返回树的数据即可 742 class TreeElement : public ListElement 743 { 744 public: 745 //树的一个节点 746 struct Node 747 { 748 std::map<int, std::wstring> texts; //一行的文本,key是列号,value是文本 749 std::vector<std::shared_ptr<Node>> child_list; //子节点列表 750 Node* parent{}; //父节点 751 bool collapsed{}; //是否折叠 752 753 void AddChild(std::shared_ptr<Node> child); 754 int GetLevel() const; //获取节点的级别,如果节点没有父节点,则级别为0 755 756 //按顺序遍历子节点 757 //func:遍历节点时的回调函数,如果要结束遍历,则返回true,否则返回false 758 //ignore_invisible:忽略被折叠的节点 759 void IterateNodeInOrder(std::function<bool(Node*)> func, bool ignore_invisible); 760 }; 761 762 virtual std::vector<std::shared_ptr<Node>>& GetRootNodes() = 0; //获取顶级节点 763 764 int GetItemLevel(int row); //获取该行的级别(级别每加1,第一列会缩进一定距离) 765 bool IsCollapsable(int row); //该行是否可以折叠(如果为true,则显示折叠图标) 766 bool IsCollapsed(int row); //该行是否折叠 767 768 // 通过 Element 继承 769 virtual void LButtonUp(CPoint point) override; 770 virtual void MouseMove(CPoint point) override; 771 virtual void MouseLeave() override; 772 virtual bool DoubleClick(CPoint point) override; 773 774 // 通过 ListElement 继承 775 std::wstring GetItemText(int row, int col) override; 776 int GetRowCount() override; 777 //树控件不使用基类ListElement的搜索逻辑 778 virtual void QuickSearch(const std::wstring& key_word) override; 779 virtual void OnRowCountChanged() override; 780 781 std::map<int, CRect> collapsd_rects; //折叠标志的矩形区域(key是行) 782 int collaps_indicator_hover_row{ -1 }; //鼠标指向的折叠标志的行号 783 784 protected: 785 int GetNodeIndex(const Node* node); //查找一个节点的序号(如果节点被折叠或不存在则返回-1) 786 Node* GetNodeByIndex(int index); //根据一个节点的序号查找节点(忽略被折叠的节点) 787 bool IsNodeMathcKeyWord(const Node* node, const std::wstring& key_word); //判断一个节点是否匹配关键字 788 bool IsNodeDisplayed(const Node* node); 789 void IterateDisplayedNodeInOrder(std::function<bool(Node*)> func); //遍历所有可见的节点 790 std::set<const Node*> tree_search_result; //保存搜索结果 791 bool tree_searched{}; //是否处于搜索状态 792 }; 793 794 class TestTree : public TreeElement 795 { 796 public: 797 TestTree(); 798 static std::shared_ptr<Node> CreateNode(std::wstring name, std::shared_ptr<Node> parent); 799 GetIcon(int row)800 virtual IconMgr::IconType GetIcon(int row) { return IconMgr::IT_Folder; } HasIcon()801 virtual bool HasIcon() { return true; } 802 virtual int GetColumnCount() override; 803 virtual int GetColumnWidth(int col, int total_width) override; 804 virtual std::vector<std::shared_ptr<Node>>& GetRootNodes() override; 805 806 private: 807 std::vector<std::shared_ptr<Node>> root_nodes; 808 }; 809 810 //媒体库中的文件夹浏览 811 class FolderExploreTree : public TreeElement 812 { 813 public: 814 enum Column 815 { 816 COL_NAME, 817 COL_COUNT, 818 COL_MAX 819 }; 820 821 //鼠标指向一行时显示的按钮 822 enum BtnKey 823 { 824 BTN_PLAY, 825 BTN_ADD, 826 BTN_MAX 827 }; 828 829 static std::shared_ptr<Node> CreateNode(std::wstring name, int song_num, std::shared_ptr<Node> parent); 830 static std::wstring GetNodePath(Node* node); //获取一个节点的路径 831 std::wstring GetSelectedPath(); //获取选中节点的路径 832 GetIcon(int row)833 virtual IconMgr::IconType GetIcon(int row) { return IconMgr::IT_Folder; } HasIcon()834 virtual bool HasIcon() { return true; } 835 virtual int GetColumnCount() override; 836 virtual int GetColumnWidth(int col, int total_width) override; 837 virtual int GetColumnScrollTextWhenSelected() override; 838 virtual CMenu* GetContextMenu(bool item_selected) override; 839 virtual void OnDoubleClicked() override; 840 virtual std::wstring GetEmptyString() override; 841 virtual int GetHoverButtonCount() override; 842 virtual int GetHoverButtonColumn() override; 843 virtual IconMgr::IconType GetHoverButtonIcon(int index, int row) override; 844 virtual std::wstring GetHoverButtonTooltip(int index, int row) override; 845 virtual void OnHoverButtonClicked(int btn_index, int row) override; 846 virtual bool IsMultipleSelectionEnable() override; 847 848 virtual std::vector<std::shared_ptr<Node>>& GetRootNodes() override; 849 }; 850 851 //搜索框 852 class SearchBox : public Element 853 { 854 public: 855 SearchBox(); 856 ~SearchBox(); 857 void InitSearchBoxControl(CWnd* pWnd); //初始化搜索框控件。pWnd:父窗口 858 void OnKeyWordsChanged(); 859 void Clear(); GetListElement()860 ListElement* GetListElement() { return list_element; } 861 862 virtual void Draw() override; 863 virtual void MouseMove(CPoint point) override; 864 virtual void MouseLeave() override; 865 virtual void LButtonUp(CPoint point) override; 866 virtual void LButtonDown(CPoint point) override; 867 868 bool hover{}; //如果鼠标指向搜索框,则为true 869 std::wstring key_word; //搜索框中的文本 870 CUiSearchBox* search_box_ctrl{}; //搜索框控件 871 CRect icon_rect; //图标的区域 872 CPlayerUIBase::UIButton clear_btn; //清除按钮 873 874 private: 875 void FindListElement(); //查找ListElement 876 bool find_list_element{}; //如果已经查找过ListElement,则为true 877 ListElement* list_element{}; //关联的ListElement 878 }; 879 } 880 881 ///////////////////////////////////////////////////////////////////////////////////////// 882 class CElementFactory 883 { 884 public: 885 std::shared_ptr<UiElement::Element> CreateElement(const std::string& name, CPlayerUIBase* ui); 886 }; 887