#pragma once
|
#include <vector>
|
#include <memory>
|
#include <unordered_map>
|
#include <set>
|
|
|
// ===== ×Ô¶¨Òå֪ͨ£ºµã»÷ÐèÒªµ¯³öÈ«Îĵĵ¥Ôª¸ñ =====
|
#ifndef ELCN_SHOWFULLTEXT
|
#define ELCN_SHOWFULLTEXT (NM_FIRST - 201)
|
struct NMC_ELC_SHOWFULLTEXT {
|
NMHDR hdr; // hwndFrom / idFrom / code = ELCN_SHOWFULLTEXT
|
int iItem; // ÐÐ
|
int iSubItem; // ÁУ¨0-based£©
|
CString text; // ÍêÕûÎı¾
|
};
|
#endif
|
|
class CExpandableListCtrl : public CListCtrl
|
{
|
DECLARE_DYNAMIC(CExpandableListCtrl)
|
|
public:
|
struct Node {
|
Node* parent = nullptr;
|
std::vector<std::unique_ptr<Node>> children;
|
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* 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();
|
|
// ÉèÖÃÄÄЩÁÐÐèÒª¡°±»½Ø¶ÏÔò֪ͨ¸¸´°¿ÚÏÔʾȫÎÄ¡±£¨0-basedÁкţ©
|
void SetPopupFullTextColumns(const std::vector<int>& cols);
|
|
std::set<int> m_popupCols; // ÐèҪ֪ͨµÄÁм¯ºÏ
|
bool _IsCellTruncated(int row, int col, const CString& text) const;
|
|
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<std::unique_ptr<Node>> m_roots; // ¶¥²ã½Úµã
|
std::vector<Node*> 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<Node*, RowColor> m_colorByNode; // Ê÷½ÚµãÑÕÉ«
|
std::vector<RowColor> m_rowColors; // °´µ±Ç°¿É¼ûÐкŵÄÑÕÉ«£¨¼æÈݾɴúÂ룩
|
|
BOOL m_preserveSelHighlight = TRUE; // TRUE=Ñ¡ÖÐʱÓÅÏÈϵͳ¸ßÁÁ
|
};
|