chenluhua1980
2026-01-08 3e91a18f75a75fbe8f646d73e4e68ba107b6750b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
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()
};