| | |
| | | #pragma once |
| | | #include <vector> |
| | | #include <memory> |
| | | #include <unordered_map> |
| | | |
| | | class CExpandableListCtrl : public CListCtrl |
| | | { |
| | |
| | | std::vector<CString> cols; // 各列文本 |
| | | bool expanded = false; |
| | | int level = 0; // 缩进层级 |
| | | |
| | | Node(int nCols = 1) : cols(nCols) {} |
| | | }; |
| | | |
| | | CExpandableListCtrl(); |
| | | virtual ~CExpandableListCtrl(); |
| | | |
| | | // 数据构建 |
| | | // ===== 树数据构建(需要折叠功能时使用;纯平列表可忽略) ===== |
| | | Node* InsertRoot(const std::vector<CString>& cols); |
| | | Node* InsertChild(Node* parent, const std::vector<CString>& cols); |
| | | |
| | | // 展开/折叠 |
| | | void Expand(Node* n); |
| | | void Collapse(Node* n); |
| | | void Toggle(Node* n); |
| | | |
| | | // 刷新可见列表 |
| | | void RebuildVisible(); |
| | | |
| | | // 便捷:通过可见行号取 Node* |
| | | 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; // 首列展开按钮区域 |
| | | virtual void PreSubclassWindow(); |
| | | |
| | | protected: |
| | | // 消息 |
| | | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); |
| | | afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); |
| | | DECLARE_MESSAGE_MAP() |
| | | void computeColorsForRow(int row, COLORREF& outText, COLORREF& outBk) const; |
| | | |
| | | private: |
| | | std::vector<std::unique_ptr<Node>> m_roots; // 顶层节点 |
| | |
| | | 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<Node*, RowColor> m_colorByNode; // 树节点颜色 |
| | | std::vector<RowColor> m_rowColors; // 按当前可见行号的颜色(兼容旧代码) |
| | | |
| | | BOOL m_preserveSelHighlight = TRUE; // TRUE=选中时优先系统高亮 |
| | | }; |
| | | |
| | | |