LAPTOP-SNT8I5JK\Boounion
2025-08-20 5652c0bf59490f923e87b63251ad3f88b541636f
1.能展开的ListCtrl, +号换为三角形;
已修改1个文件
86 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CExpandableListCtrl.cpp 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CExpandableListCtrl.cpp
@@ -168,50 +168,74 @@
    case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
    {
        int row = (int)pCD->nmcd.dwItemSpec;
        int col = pCD->iSubItem;
        const int row = (int)pCD->nmcd.dwItemSpec;
        const int col = pCD->iSubItem;
        CDC* pDC = CDC::FromHandle(pCD->nmcd.hdc);
        // 仅在首列绘制展开按钮与缩进引导
        if (col == 0) {
            CRect rc;
            GetSubItemRect(row, 0, LVIR_BOUNDS, rc);
            // 默认文本让系统画:我们先画按钮和缩进背景,再返回 CDRF_DODEFAULT
        if (col == 0)
        {
            CRect rc; GetSubItemRect(row, 0, LVIR_BOUNDS, rc);
            Node* n = GetNodeByVisibleIndex(row);
            if (n) {
                // 绘制展开三角/方块
                if (!n->children.empty()) {
                    CRect box = expanderRectForRow(row);
                    // 小方框
                    pDC->Rectangle(box);
            if (!n) { *pResult = CDRF_DODEFAULT; return; }
                    // 画“+”或“-”
                    CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
                    CPen* oldPen = pDC->SelectObject(&pen);
                    // 横线
                    pDC->MoveTo(box.left + 2, box.CenterPoint().y);
                    pDC->LineTo(box.right - 2, box.CenterPoint().y);
                    if (!n->expanded) {
                        // 竖线(表示 + 号)
                        pDC->MoveTo(box.CenterPoint().x, box.top + 2);
                        pDC->LineTo(box.CenterPoint().x, box.bottom - 2);
                    }
                    pDC->SelectObject(oldPen);
            // 1) 背景/前景颜色:按是否选中
            const bool selected = (GetItemState(row, LVIS_SELECTED) & LVIS_SELECTED) != 0;
            const bool focusOnCtrl = (GetSafeHwnd() == ::GetFocus());
            COLORREF bk = selected ? GetSysColor(focusOnCtrl ? COLOR_HIGHLIGHT : COLOR_3DFACE)
                : ListView_GetBkColor(m_hWnd);
            COLORREF txt = selected ? GetSysColor(focusOnCtrl ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT)
                : ListView_GetTextColor(m_hWnd);
            // 仅在需要时填充背景(避免“黑一片”)
            CBrush bkBrush(bk);
            pDC->FillRect(rc, &bkBrush);
            // 2) 展开/折叠指示
            if (!n->children.empty())
            {
                CRect box = expanderRectForRow(row);
                // 画三角(▶/▼),并恢复画笔/画刷
                HGDIOBJ oldPen = pDC->SelectObject(GetStockObject(BLACK_PEN));
                HGDIOBJ oldBrush = pDC->SelectObject(GetStockObject(BLACK_BRUSH));
                POINT tri[3];
                if (n->expanded) { // ▼
                    tri[0] = { box.left + 2, box.top + 2 };
                    tri[1] = { box.right - 2, box.top + 2 };
                    tri[2] = { box.CenterPoint().x, box.bottom - 2 };
                }
                // 把文本左边界右移,留出缩进与按钮空间
                // 这里不改系统绘制的文本起点,而是通过在文本前置空格的方式处理更简单:
                // 我们直接改显示文本(性能足够):在 RebuildVisible 时已经填了纯文本。
                // 如果你要精准控制文本位置,可以改 OWNERDRAW 或自绘文本。
                else {           // ▶
                    tri[0] = { box.left + 2, box.top + 2 };
                    tri[1] = { box.right - 2, box.CenterPoint().y };
                    tri[2] = { box.left + 2, box.bottom - 2 };
                }
                pDC->Polygon(tri, 3);
                pDC->SelectObject(oldPen);
                pDC->SelectObject(oldBrush);
            }
            // 3) 文本:右移避免遮挡
            const int indentPx = n->level * 16;
            CRect textRc = rc;
            textRc.left = rc.left + m_expanderPadding + indentPx + m_expanderSize + m_textGap;
            pDC->SetBkMode(TRANSPARENT);
            pDC->SetTextColor(txt);
            CString txt0 = n->cols.empty() ? _T("") : n->cols[0];
            pDC->DrawText(txt0, textRc, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_END_ELLIPSIS);
            // 首列自绘完毕
            *pResult = CDRF_SKIPDEFAULT;
            return;
        }
        // 其他列默认绘制
        *pResult = CDRF_DODEFAULT;
        return;
    }
    }
    *pResult = CDRF_DODEFAULT;
}