From d7fbb147a1582e93c3028d8328b2e7eb3736d6e9 Mon Sep 17 00:00:00 2001
From: chenluhua1980 <Chenluhua@qq.com>
Date: 星期四, 08 一月 2026 20:07:42 +0800
Subject: [PATCH] 1.本地控件状态改变后上报EAP

---
 SourceCode/Bond/Servo/CExpandableListCtrl.cpp |  190 +++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 180 insertions(+), 10 deletions(-)

diff --git a/SourceCode/Bond/Servo/CExpandableListCtrl.cpp b/SourceCode/Bond/Servo/CExpandableListCtrl.cpp
index 9022dce..39831cc 100644
--- a/SourceCode/Bond/Servo/CExpandableListCtrl.cpp
+++ b/SourceCode/Bond/Servo/CExpandableListCtrl.cpp
@@ -3,7 +3,11 @@
 
 IMPLEMENT_DYNAMIC(CExpandableListCtrl, CListCtrl)
 
-CExpandableListCtrl::CExpandableListCtrl() {}
+CExpandableListCtrl::CExpandableListCtrl()
+{
+    m_popupCols = { };
+}
+
 CExpandableListCtrl::~CExpandableListCtrl() {}
 
 BEGIN_MESSAGE_MAP(CExpandableListCtrl, CListCtrl)
@@ -91,26 +95,140 @@
     m_rowColors.resize(GetItemCount());
 
     SetRedraw(TRUE);
-    Invalidate();
+    Invalidate(FALSE);
 }
 
+// 鈥斺�� 浼樺寲鍚庣殑灞曞紑/鏀惰捣锛氬眬閮ㄦ彃鍏�/鍒犻櫎锛屼笉鍏ㄩ噺 RebuildVisible 鈥斺�� //
 void CExpandableListCtrl::Expand(Node* n)
 {
     if (!n || n->children.empty()) return;
-    if (!n->expanded) { n->expanded = true; RebuildVisible(); }
+    if (n->expanded) return;
+
+    // 鏈湴宸ュ叿锛氭壘鑺傜偣鍦� m_visible 涓殑琛屽彿
+    auto VisibleIndexOf = [&](Node* x)->int {
+        for (int i = 0; i < (int)m_visible.size(); ++i)
+            if (m_visible[i] == x) return i;
+        return -1;
+    };
+    // 閫掑綊鏀堕泦鈥滃簲褰撳彲瑙佲�濈殑瀛愭爲锛堝彈 expanded 褰卞搷锛�
+    std::vector<Node*> toInsert;
+    std::function<void(Node*)> CollectExpandedSubtree = [&](Node* x) {
+        if (!x) return;
+        for (auto& up : x->children) {
+            Node* ch = up.get();
+            toInsert.push_back(ch);
+            if (ch->expanded && !ch->children.empty())
+                CollectExpandedSubtree(ch);
+        }
+    };
+    // 浠� pos 璧锋彃鍏� nodes锛屽榻� m_visible / ListCtrl / m_rowColors
+    auto InsertRowsAt = [&](int pos, const std::vector<Node*>& nodes) {
+        if (nodes.empty()) return;
+        const int colCount = GetHeaderCtrl() ? GetHeaderCtrl()->GetItemCount() : 1;
+
+        SetRedraw(FALSE);
+
+        // 1) 鍏堟彃 m_visible
+        m_visible.insert(m_visible.begin() + pos, nodes.begin(), nodes.end());
+
+        // 2) 鍐嶆彃 ListCtrl
+        for (int i = 0; i < (int)nodes.size(); ++i) {
+            Node* cur = nodes[i];
+            LVITEM lvi{}; lvi.mask = LVIF_TEXT;
+            lvi.iItem = pos + i;
+            lvi.iSubItem = 0;
+            lvi.pszText = const_cast<LPTSTR>((LPCTSTR)(cur->cols.empty() ? _T("") : cur->cols[0]));
+            InsertItem(&lvi);
+
+            for (int col = 1; col < colCount; ++col) {
+                CString txt = (col < (int)cur->cols.size()) ? cur->cols[col] : _T("");
+                SetItemText(pos + i, col, txt);
+            }
+        }
+
+        // 3) 琛屽彿棰滆壊鏁扮粍鍚屾鎻掑叆榛樿鑹�
+        m_rowColors.insert(m_rowColors.begin() + pos, nodes.size(), RowColor{});
+
+        SetRedraw(TRUE);
+        Invalidate(FALSE);
+    };
+
+    // 鈥斺�� 鏍囪灞曞紑
+    n->expanded = true;
+
+    // 鈥斺�� 鍦� UI 閲屾彃鍏ュ叾鈥滃簲褰撳彲瑙佲�濈殑瀛愭爲
+    const int pos = VisibleIndexOf(n);
+    if (pos < 0) { RebuildVisible(); return; }
+
+    CollectExpandedSubtree(n);
+    InsertRowsAt(pos + 1, toInsert);
 }
 
 void CExpandableListCtrl::Collapse(Node* n)
 {
     if (!n || n->children.empty()) return;
-    if (n->expanded) { n->expanded = false; RebuildVisible(); }
+    if (!n->expanded) return;
+
+    // 鏈湴宸ュ叿锛氭壘鑺傜偣琛屽彿
+    auto VisibleIndexOf = [&](Node* x)->int {
+        for (int i = 0; i < (int)m_visible.size(); ++i)
+            if (m_visible[i] == x) return i;
+        return -1;
+    };
+    // 璁$畻鈥滃綋鍓嶅彲瑙佺殑鎵�鏈夊悗浠f暟閲忊�濓紙鍩轰簬 level 閫掑噺鍒ゆ柇锛�
+    auto CountDescendantsInVisible = [&](Node* x)->int {
+        if (!x) return 0;
+        const int start = VisibleIndexOf(x);
+        if (start < 0) return 0;
+        const int baseLevel = x->level;
+        int cnt = 0;
+        for (int i = start + 1; i < (int)m_visible.size(); ++i) {
+            if (!m_visible[i]) break;
+            if (m_visible[i]->level <= baseLevel) break;
+            ++cnt;
+        }
+        return cnt;
+    };
+    // 浠� UI 鍒犻櫎 pos 寮�濮嬬殑 count 琛岋紝骞跺悓姝� m_visible/m_rowColors
+    auto DeleteRowsAt = [&](int pos, int count) {
+        if (count <= 0) return;
+
+        SetRedraw(FALSE);
+
+        // 鍒� ListCtrl锛氫竴鐩村垹 pos锛屽洜涓哄垹涓�琛屽悗鍚庣画涓婄Щ
+        for (int i = 0; i < count; ++i) {
+            DeleteItem(pos);
+        }
+        // 鍒� m_visible
+        m_visible.erase(m_visible.begin() + pos, m_visible.begin() + pos + count);
+        // 鍒犻鑹�
+        if (pos >= 0 && pos <= (int)m_rowColors.size()) {
+            int end = min((int)m_rowColors.size(), pos + count);
+            m_rowColors.erase(m_rowColors.begin() + pos, m_rowColors.begin() + end);
+        }
+
+        SetRedraw(TRUE);
+        Invalidate(FALSE);
+    };
+
+    // 鈥斺�� 鏍囪鏀惰捣
+    n->expanded = false;
+
+    // 鈥斺�� 鍙垹闄ゅ叾鈥滃綋鍓嶅彲瑙佲�濈殑鎵�鏈夊悗浠�
+    const int pos = VisibleIndexOf(n);
+    if (pos < 0) { RebuildVisible(); return; }
+
+    const int cnt = CountDescendantsInVisible(n);
+    if (cnt > 0) {
+        DeleteRowsAt(pos + 1, cnt);
+    }
 }
 
 void CExpandableListCtrl::Toggle(Node* n)
 {
     if (!n || n->children.empty()) return;
-    n->expanded = !n->expanded;
-    RebuildVisible();
+    if (n->expanded) Collapse(n);
+    else             Expand(n);
 }
 
 CExpandableListCtrl::Node* CExpandableListCtrl::GetNodeByVisibleIndex(int i) const
@@ -132,7 +250,6 @@
     for (int i = 0; i < (int)m_visible.size(); ++i) {
         if (m_visible[i] == n) {
             RedrawItems(i, i);
-            UpdateWindow();
             return;
         }
     }
@@ -147,7 +264,6 @@
         for (int i = 0; i < (int)m_visible.size(); ++i) {
             if (m_visible[i] == n) {
                 RedrawItems(i, i);
-                UpdateWindow();
                 return;
             }
         }
@@ -179,7 +295,6 @@
     m_rowColors[row] = rc;
 
     RedrawItems(row, row);
-    UpdateWindow();
 }
 
 CRect CExpandableListCtrl::expanderRectForRow(int row) const
@@ -249,6 +364,38 @@
             }
         }
     }
+
+    // 鈥斺�� 鑻ョ偣鍑诲埌闇�瑕佲�滃叏鏂囨樉绀衡�濈殑鍒楋紝鍒欏悜鐖剁獥鍙e彂閫佽嚜瀹氫箟閫氱煡 鈥斺�� //
+    if (!m_popupCols.empty()) {
+        LPNMITEMACTIVATE pia2 = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
+
+        // 鐢� SubItemHitTest 鏇寸簿鍑嗘嬁鍒板垪
+        LVHITTESTINFO ht{};
+        ht.pt = pia2->ptAction;
+        int hit = SubItemHitTest(&ht);
+        if (hit >= 0 && ht.iItem >= 0 && ht.iSubItem >= 0) {
+            const int row = ht.iItem;
+            const int col = ht.iSubItem;
+
+            if (m_popupCols.count(col)) {
+                CString full = GetItemText(row, col);
+                if (!full.IsEmpty() && _IsCellTruncated(row, col, full)) {
+                    NMC_ELC_SHOWFULLTEXT nm{};
+                    nm.hdr.hwndFrom = m_hWnd;
+                    nm.hdr.idFrom = GetDlgCtrlID();
+                    nm.hdr.code = ELCN_SHOWFULLTEXT;
+                    nm.iItem = row;
+                    nm.iSubItem = col;
+                    nm.text = full;
+
+                    if (CWnd* pParent = GetParent()) {
+                        pParent->SendMessage(WM_NOTIFY, nm.hdr.idFrom, reinterpret_cast<LPARAM>(&nm));
+                    }
+                }
+            }
+        }
+    }
+
     *pResult = 0;
 }
 
@@ -438,7 +585,30 @@
     DeleteAllItems();
     SetRedraw(TRUE);
 
-    Invalidate();
+    Invalidate(FALSE);
 }
 
+void CExpandableListCtrl::SetPopupFullTextColumns(const std::vector<int>& cols)
+{
+    m_popupCols.clear();
+    for (int c : cols) m_popupCols.insert(c);
+}
 
+bool CExpandableListCtrl::_IsCellTruncated(int row, int col, const CString& text) const
+{
+    if (text.IsEmpty()) return false;
+
+    // 鍗曞厓鏍兼樉绀哄尯鍩熷搴�
+    CRect rcCell;
+    if (!const_cast<CExpandableListCtrl*>(this)->GetSubItemRect(row, col, LVIR_BOUNDS, rcCell))
+        return false;
+
+    // 鐢ㄦ帶浠跺瓧浣撴祴閲忔枃鏈儚绱犲
+    CClientDC dc(const_cast<CExpandableListCtrl*>(this));
+    CFont* pOld = dc.SelectObject(const_cast<CExpandableListCtrl*>(this)->GetFont());
+    CSize sz = dc.GetTextExtent(text);
+    dc.SelectObject(pOld);
+
+    const int kPadding = 8; // 棰勭暀涓�鐐硅竟璺�/鐪佺暐鍙蜂綑閲�
+    return sz.cx > (rcCell.Width() - kPadding);
+}

--
Gitblit v1.9.3