mrDarker
2025-10-22 e8a27bb203fe2aff70390a5eca002d7438da9b0f
SourceCode/Bond/Servo/CCarrierSlotGrid.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,195 @@
#include "stdafx.h"
#pragma once
#include <vector>
#ifndef _AFX
#include <afxwin.h>
#endif
// æ”¾åˆ° CCarrierSlotGrid ç±»å®šä¹‰å‰æˆ–内部 public: åŒºéƒ½å¯
enum { CSGN_SEL_CHANGED = 1, CSGN_MAT_CHANGED = 2 };
struct CSG_SEL_CHANGE {
    NMHDR hdr;   // hdr.code = CSGN_SEL_CHANGED
    int   port;  // 0..GetPortCount()-1
    int   slot;  // 0..GetSlotCount()-1
    BOOL  checked;
};
struct CSG_MAT_CHANGE {
    NMHDR hdr;   // hdr.code = CSGN_MAT_CHANGED
    int   port;
    int   slot;
    int   material; // 1=G1, 2=G2
};
class CCarrierSlotGrid : public CWnd
{
public:
    enum MaterialType { MAT_G1 = 1, MAT_G2 = 2 };
    struct SlotCell {
        bool    hasGlass = false;
        CString coreId;
        int     material = MAT_G1;
        bool    checked = false;
    };
    struct PortColumn {
        CString               portName;
        CString               carrierName;
        bool                  allocated = false;
        CString               allocatedBy;
        std::vector<SlotCell> slots;
    };
public:
    CCarrierSlotGrid();
    virtual ~CCarrierSlotGrid();
    BOOL SubclassDlgItem(UINT nID, CWnd* pParent) {
        BOOL ok = CWnd::SubclassDlgItem(nID, pParent);
        if (ok) {
            if (pParent && pParent->GetFont()) SetFont(pParent->GetFont());
            EnsureFonts();
            Invalidate(FALSE);
        }
        return ok;
    }
    virtual void PreSubclassWindow() override;
    // åˆå§‹åŒ–
    void InitGrid(int nPorts, int nSlots);
    void SetColumnWidths(int slotColWidth, int portColWidth);
    void SetRowHeight(int cy);
    void SetHeaderHeight(int cy);
    void SetShowMaterialToggle(BOOL bShow);
    // è¯»/写
    int  GetPortCount() const { return (int)m_ports.size(); }
    int  GetSlotCount() const { return m_nSlots; }
    void SetPortInfo(int portIndex, LPCTSTR portName, LPCTSTR carrierName);
    void SetPortAllocated(int portIndex, BOOL allocated, LPCTSTR byName = nullptr);
    BOOL IsPortAllocated(int portIndex) const;
    void SetSlotGlass(int portIndex, int slotIndex, BOOL hasGlass, LPCTSTR coreId, int material);
    void SetSlotChecked(int portIndex, int slotIndex, BOOL checked, BOOL bNotify = FALSE);
    BOOL GetSlotChecked(int portIndex, int slotIndex) const;
    int  GetSlotMaterialType(int portIndex, int slotIndex) const;
    void SetSlotMaterialType(int portIndex, int slotIndex, int material, BOOL bNotify = TRUE);
    CString GetDisplayId(int portIndex, int slotIndex) const;
    void    CheckAllInPort(int portIndex, BOOL checked, BOOL bNotify = TRUE);
    void RebuildTexts();
    void EnableColumnResize(BOOL enable) { m_bAllowResize = !!enable; Invalidate(FALSE); }
    // è®¡ç®—最佳大小:
// - CalcBestClientSize:内容区域(不含滚动条/非客户区)刚好容纳表头+所有行、全部列
// - CalcBestWindowSize:在当前窗口样式下,将“内容大小”转换为窗口外框大小(会考虑 WS_BORDER/CLIENTEDGE ç­‰ï¼‰
//   é»˜è®¤æŒ‰â€œéšè—æ»šåŠ¨æ¡â€çš„ç›®æ ‡æ¥ç®—ï¼ˆå³ä¸æŠŠ WS_HSCROLL/WS_VSCROLL è®¡å…¥è°ƒæ•´ï¼‰
// è®¡ç®—最佳大小(支持可选安全边距,默认按 DPI çº¦ç­‰äºŽ 2px)
    CSize CalcBestClientSize(int nSlotsOverride = -1) const;
    CSize CalcBestWindowSize(BOOL includeNonClient = TRUE,
        int nSlotsOverride = -1,
        int extraPadX = -1,  // -1 è¡¨ç¤ºæŒ‰ DPI è‡ªåЍ
        int extraPadY = -1) const;
    // æ°¸ä¹…禁用系统滚动条(去掉样式并刷新非客户区)
    void DisableSystemScrollbars();
    // æŠŠçª—口尺寸调到正好容纳所有内容(不出现滚动条)
    void ResizeWindowToFitAll(BOOL includeNonClient = TRUE, int nSlotsOverride = -1);
    // è¿›å…¥/退出无滚动条模式(去样式、清滚动、忽略滚动消息)
    void SetNoScrollbarsMode(BOOL enable);
    // åœ¨â€œæ— æ»šåŠ¨æ¡æ¨¡å¼â€ä¸‹ï¼ŒæŠŠçª—å£å°ºå¯¸è°ƒåˆ°åˆšå¥½å®¹çº³æ‰€æœ‰å†…å®¹ï¼ˆä¸å‡ºçŽ°æ»šåŠ¨æ¡ï¼‰
    void FitWindowToContentNoScroll(BOOL includeNonClient = TRUE, int nSlotsOverride = -1);
protected:
    // æ•°æ®
    int                     m_nSlots = 0;
    std::vector<PortColumn> m_ports;
    BOOL                    m_bShowMatToggle = TRUE;
    // å°ºå¯¸/滚动
    int m_rowHeight = 26;
    int m_headerCY = 28;
    int m_slotColCX = 100;
    std::vector<int> m_portColCXs;
    int m_scrollY = 0;
    int m_scrollX = 0;
    int m_slotColMin = 60;
    int m_portColMin = 80;
    // é¢œè‰²
    COLORREF m_colBg = RGB(255, 255, 255);
    COLORREF m_colAlt = RGB(240, 242, 245);
    COLORREF m_colLock = RGB(255, 244, 214);
    COLORREF m_gridMajor = RGB(210, 214, 220);
    COLORREF m_gridMinor = RGB(220, 224, 230);
    COLORREF m_text = RGB(40, 40, 40);
    COLORREF m_textDim = RGB(150, 150, 150);
    // å­—体
    CFont m_fntText;
    CFont m_fntBold;
    CFont m_fntSmall;
    // æ‹–动列宽
    bool m_bResizing = false;
    int  m_resizeEdge = -1;   // 0=Slot|Port1;1..N-1=Port i|i+1
    int  m_resizeStartX = 0;
    int  m_slotColCXStart = 0;
    std::vector<int> m_portColCXsStart;
    int  m_hitEdgeHover = -1;
    bool m_bAllowResize = true; // â† æ–°å¢žï¼šæ˜¯å¦å…è®¸æ‹–动列宽
    bool m_noScrollbars = false;   // â† æ–°å¢žï¼šæ— æ»šåŠ¨æ¡æ¨¡å¼
    // å·¥å…·
    void EnsureFonts();
    void UpdateScrollRange();
    int  GetTotalContentWidth() const;
    void NotifySelectionChanged(int port, int slot, BOOL checked);
    void NotifyMaterialChanged(int port, int slot, int material);
    // å‡ ä½•
    CRect GetClientRectNoSB() const;
    BOOL  GetCellRect(int row, int sub, CRect& rc) const; // sub: 0=Slot, 1..N=Port
    CRect GetHeaderRect() const;
    CRect GetHeaderItemRect(int iItem) const;
    CRect GetHeaderCheckboxRect(int iItem) const;
    CRect GetCheckboxRect(const CRect& cell) const;
    CRect GetMaterialTagRect(const CRect& cell) const;
    CRect GetStatusDotRect(const CRect& cell) const;
    BOOL IsColumnResizeEnabled() const { return m_bAllowResize ? TRUE : FALSE; }
    int   HitHeaderEdge(CPoint pt) const;
    // ç»˜åˆ¶
    void DrawFlatCheckbox(CDC* pDC, const CRect& r, bool checked, bool disabled);
    void PaintTo(CDC* pDC);
protected:
    // æ¶ˆæ¯
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnPaint();
    afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); // â˜… çºµå‘滚动条
    afx_msg void OnLButtonDown(UINT nFlags, CPoint pt);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint pt);
    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
    afx_msg void OnMouseMove(UINT nFlags, CPoint pt);
    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
    afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
    afx_msg void OnWindowPosChanged(WINDOWPOS* wp);
    DECLARE_MESSAGE_MAP()
};