#pragma once #include #include #include class CExpandableListCtrl : public CListCtrl { DECLARE_DYNAMIC(CExpandableListCtrl) public: struct Node { Node* parent = nullptr; std::vector> children; std::vector cols; // ¸÷ÁÐÎı¾ bool expanded = false; int level = 0; // Ëõ½ø²ã¼¶ Node(int nCols = 1) : cols(nCols) {} }; CExpandableListCtrl(); virtual ~CExpandableListCtrl(); // ===== Ê÷Êý¾Ý¹¹½¨£¨ÐèÒªÕÛµþ¹¦ÄÜʱʹÓã»´¿Æ½Áбí¿ÉºöÂÔ£© ===== Node* InsertRoot(const std::vector& cols); Node* InsertChild(Node* parent, const std::vector& cols); void Expand(Node* n); void Collapse(Node* n); void Toggle(Node* n); void RebuildVisible(); Node* GetNodeByVisibleIndex(int i) const; // ===== ÐÐÅäÉ« API ===== // A) °´ Node* ×ÅÉ«£¨ÓÃÓÚÊ÷/¿ÉÕÛµþ³¡¾°£¬Ë÷Òý±ä»¯²»ÊÜÓ°Ï죩 void SetNodeColor(Node* n, COLORREF text, COLORREF bk); void ClearNodeColor(Node* n); void ClearAllColors(); // B) ¼æÈݾɽӿڣº°´¡°¿É¼ûÐкš±×ÅÉ«£¨ÓëÄãµ±Ç°Ò³Ãæ´úÂëÒ»Ö£© void SetItemColor(DWORD_PTR iItem, COLORREF TextColor, COLORREF TextBkColor); // ¼æÈÝ ListCtrlEx void SetItemColorByVisibleIndex(int row, COLORREF text, COLORREF bk); // ͬÉϱðÃû // Ñ¡ÖÐÐÐÊÇ·ñʹÓÃϵͳ¸ßÁÁ£¨TRUE£¬Ä¬ÈÏ£©£» // ÈôΪ FALSE£¬ÔòÑ¡ÖÐʱÈÔÏÔʾ×Ô¶¨ÒåÑÕÉ« void SetPreserveSelectionHighlight(BOOL b) { m_preserveSelHighlight = b; } // Çå³ýÊ÷ void ClearTree(); protected: virtual void PreSubclassWindow(); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) override; DECLARE_MESSAGE_MAP() private: void appendVisible(Node* n); CRect expanderRectForRow(int row) const; // Ê×ÁÐÕ¹¿ª°´Å¥ÇøÓò void computeColorsForRow(int row, COLORREF& outText, COLORREF& outBk) const; private: std::vector> m_roots; // ¶¥²ã½Úµã std::vector m_visible; // Õ¹¿ªºóµÄ¿É¼û½Úµã˳Ðò int m_expanderPadding = 6; // Ê×ÁÐÄÚ²à±ß¾à int m_expanderSize = 10; // СÈý½Ç/·½¿é´óС int m_textGap = 6; struct RowColor { COLORREF text = CLR_DEFAULT; COLORREF bk = CLR_DEFAULT; bool hasText = false; bool hasBk = false; }; // ÑÕÉ«£¨Á½Â·À´Ô´£¬ÓÅÏȼ¶£ºNode* > Ðкţ© std::unordered_map m_colorByNode; // Ê÷½ÚµãÑÕÉ« std::vector m_rowColors; // °´µ±Ç°¿É¼ûÐкŵÄÑÕÉ«£¨¼æÈݾɴúÂ룩 BOOL m_preserveSelHighlight = TRUE; // TRUE=Ñ¡ÖÐʱÓÅÏÈϵͳ¸ßÁÁ };