From e15e0d2f9305e71cd160f1ddceab93c7889eab20 Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期四, 05 六月 2025 17:37:33 +0800
Subject: [PATCH] 1. 解决自定义按钮资源泄露问题 2. 增加Slot点击回调和鼠标悬停/点击高亮效果

---
 SourceCode/Bond/Servo/CPageGraph2.cpp |    5 +
 SourceCode/Bond/Servo/BlButton.cpp    |    8 +-
 SourceCode/Bond/Servo/JobSlotGrid.h   |   14 ++++
 SourceCode/Bond/Servo/JobSlotGrid.cpp |  111 +++++++++++++++++++++++++++++++++++-
 4 files changed, 129 insertions(+), 9 deletions(-)

diff --git a/SourceCode/Bond/Servo/BlButton.cpp b/SourceCode/Bond/Servo/BlButton.cpp
index 5eb7694..2bddd2b 100644
--- a/SourceCode/Bond/Servo/BlButton.cpp
+++ b/SourceCode/Bond/Servo/BlButton.cpp
@@ -219,8 +219,7 @@
 		hFont = (HFONT)pFont->GetSafeHandle();
 	}
 
-
-	::SelectObject(hDC, hFont);
+	HFONT hOldFont = (HFONT)::SelectObject(hDC, hFont);
 	::SetBkMode(hDC, TRANSPARENT);
 	::SetTextColor(hDC, m_crText[state]);
 
@@ -237,6 +236,7 @@
 		}
 		DrawTextA(hDC, szText, (int)strlen(szText), &rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
 	}
+	::SelectObject(hDC, hOldFont);
 
 
 	// 是否有小圆点
@@ -283,8 +283,8 @@
 		::Polygon(hDC, pt, 3);
 		::SelectObject(hDC, hOldBrush);
 		::SelectObject(hDC, hOldPen);
-		::DeleteObject(hBrush);
-		::DeleteObject(hPen);
+		::DeleteObject(hbrDrop);     // 正确释放小三角使用的画刷
+		::DeleteObject(hPenDrop);    // 正确释放小三角的笔
 	}
 }
 
diff --git a/SourceCode/Bond/Servo/CPageGraph2.cpp b/SourceCode/Bond/Servo/CPageGraph2.cpp
index 6f06274..d2a356e 100644
--- a/SourceCode/Bond/Servo/CPageGraph2.cpp
+++ b/SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -128,6 +128,11 @@
 
 		CHMPropertyDlg dlg(pEquipment->getName().c_str(), 658, 788);
 
+		CEquipmentPage1* pPage1 = new CEquipmentPage1();
+		pPage1->setEquipment(pEquipment);
+		pPage1->Create(IDD_PAGE_EQUIPMENT1);
+		dlg.addPage(pPage1, "Link Signal");
+
 		if (_strcmpi(pEquipment->getClassName(), "CLoadPort") == 0) {
 			CPagePortProperty* pPageA = new CPagePortProperty();
 			pPageA->setLoadPort((SERVO::CLoadPort*)pEquipment);
diff --git a/SourceCode/Bond/Servo/JobSlotGrid.cpp b/SourceCode/Bond/Servo/JobSlotGrid.cpp
index cf7df72..12a4c2f 100644
--- a/SourceCode/Bond/Servo/JobSlotGrid.cpp
+++ b/SourceCode/Bond/Servo/JobSlotGrid.cpp
@@ -10,6 +10,10 @@
 BEGIN_MESSAGE_MAP(CJobSlotGrid, CWnd)
     ON_WM_PAINT()
     ON_WM_ERASEBKGND()
+    ON_WM_MOUSEMOVE()
+    ON_WM_MOUSELEAVE()
+    ON_WM_LBUTTONDOWN()
+    ON_WM_LBUTTONUP()
 END_MESSAGE_MAP()
 
 CJobSlotGrid::CJobSlotGrid() {
@@ -48,6 +52,7 @@
     m_nRows = nRows;
     m_nCols = nCols;
     m_vSlotStatus.assign(nRows, std::vector<bool>(nCols, false));
+    m_vSlotClickable.assign(nRows, std::vector<bool>(nCols, false));
 
     // 鍒濆鍖栨枃鏈暟缁�
     m_vSlotText.assign(nRows, std::vector<CString>(nCols));
@@ -130,8 +135,88 @@
     Invalidate();
 }
 
+void CJobSlotGrid::SetSlotClickable(int nRow, int nCol, bool bClickable)
+{
+    if (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols) {
+        m_vSlotClickable[nRow][nCol] = bClickable;
+    }
+}
+
+bool CJobSlotGrid::IsSlotClickable(int nRow, int nCol) const
+{
+    if (nRow >= 0 && nRow < m_nRows && nCol >= 0 && nCol < m_nCols) {
+        return m_vSlotClickable[nRow][nCol];
+    }
+    return false;
+}
+
+void CJobSlotGrid::SetSlotClickCallback(SlotClickCallback fnCallback)
+{
+    m_fnSlotClickCallback = fnCallback;
+}
+
 BOOL CJobSlotGrid::OnEraseBkgnd(CDC* pDC) {
     return TRUE;
+}
+
+void CJobSlotGrid::OnMouseMove(UINT nFlags, CPoint point)
+{
+    TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd };
+    ::TrackMouseEvent(&tme);
+
+    CRect rect;
+    GetClientRect(&rect);
+    int nCellWidth = rect.Width() / m_nCols;
+    int nCellHeight = rect.Height() / m_nRows;
+
+    int nCol = point.x / nCellWidth;
+    int nRow = point.y / nCellHeight;
+
+    if (nRow != m_ptHover.y || nCol != m_ptHover.x) {
+        m_ptHover = CPoint(nCol, nRow);
+        Invalidate();
+    }
+
+    CWnd::OnMouseMove(nFlags, point);
+}
+
+void CJobSlotGrid::OnMouseLeave()
+{
+    m_ptHover = CPoint(-1, -1);
+    Invalidate();
+
+    CWnd::OnMouseLeave();
+}
+
+void CJobSlotGrid::OnLButtonDown(UINT nFlags, CPoint point)
+{
+    m_bLButtonDown = true;
+    Invalidate();
+
+    CWnd::OnLButtonDown(nFlags, point);
+}
+
+void CJobSlotGrid::OnLButtonUp(UINT nFlags, CPoint point)
+{
+    m_bLButtonDown = false;
+    Invalidate();
+
+    // 淇濇寔鍘熸湁閫昏緫涓嶅彉
+    CRect rect;
+    GetClientRect(&rect);
+    int nCellWidth = rect.Width() / m_nCols;
+    int nCellHeight = rect.Height() / m_nRows;
+
+    int nCol = point.x / nCellWidth;
+    int nRow = point.y / nCellHeight;
+
+    if (IsSlotClickable(nRow, nCol)) {
+        if (m_fnSlotClickCallback) {
+            m_fnSlotClickCallback(nRow, nCol);
+        }
+    }
+
+    CWnd::OnLButtonUp(nFlags, point);
 }
 
 void CJobSlotGrid::OnPaint() {
@@ -152,14 +237,30 @@
         for (int j = 0; j < m_nCols; ++j) {
             CRect cellRect(j * nCellWidth, i * nCellHeight, (j + 1) * nCellWidth, (i + 1) * nCellHeight);
 
-            // 鑳屾櫙
-            CBrush* pBrush = m_vSlotStatus[i][j] ? &m_brushHasJob : &m_brushNoJob;
-            pDC->FillRect(&cellRect, pBrush);
+            // 鍒ゆ柇鐘舵�侊細鎮仠 / 鎸変笅
+            bool bIsHover = (m_ptHover.x == j && m_ptHover.y == i);
+            bool bIsClicking = bIsHover && m_bLButtonDown;
+
+            // 閫夋嫨棰滆壊
+            COLORREF fillColor;
+            if (bIsClicking) {
+                fillColor = RGB(0, 120, 215);   // 榧犳爣鎸変笅鑹�
+            }
+            else if (bIsHover) {
+                fillColor = RGB(200, 230, 255); // 鎮仠楂樹寒
+            }
+            else {
+                fillColor = m_vSlotStatus[i][j] ? m_colorHasJob : m_colorNoJob;
+            }
+
+            // 鐢昏儗鏅�
+            CBrush brush(fillColor);
+            pDC->FillRect(&cellRect, &brush);
 
             // 杈规
             pDC->DrawEdge(&cellRect, EDGE_SUNKEN, BF_RECT);
 
-            // 鏂囧瓧锛堝眳涓級
+            // 鏂囨湰
             pDC->SetBkMode(TRANSPARENT);
             pDC->SetTextColor(RGB(0, 0, 0));
             pDC->DrawText(m_vSlotText[i][j], &cellRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
@@ -167,4 +268,4 @@
     }
 
     pDC->SelectObject(pOldFont);
-}
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/JobSlotGrid.h b/SourceCode/Bond/Servo/JobSlotGrid.h
index f904aea..c00dea9 100644
--- a/SourceCode/Bond/Servo/JobSlotGrid.h
+++ b/SourceCode/Bond/Servo/JobSlotGrid.h
@@ -1,6 +1,9 @@
 #pragma once
 #include <afxwin.h>
 #include <vector>
+#include <functional>
+
+using SlotClickCallback = std::function<void(int nRow, int nCol)>;
 
 class CJobSlotGrid : public CWnd
 {
@@ -16,15 +19,24 @@
     void SetSlotText(int nRow, int nCol, const CString& strText);
     void SetTextFont(const CString& strFontName, int nPointSize);
     void ClearAll();
+    void SetSlotClickable(int nRow, int nCol, bool bClickable);
+    bool IsSlotClickable(int nRow, int nCol) const;
+    void SetSlotClickCallback(SlotClickCallback fnCallback);
 
 protected:
     afx_msg void OnPaint();
     afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+    afx_msg void OnMouseLeave();
+    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
     DECLARE_MESSAGE_MAP()
 
 private:
     int m_nRows;
     int m_nCols;
+    bool m_bLButtonDown = false;             // 鼠标是否按下
+    CPoint m_ptHover{ -1, -1 };   // 当前悬停的 cell 索引(row, col)
     CFont m_fontText;
     COLORREF m_colorHasJob;
     COLORREF m_colorNoJob;
@@ -32,6 +44,8 @@
     CBrush m_brushNoJob;
     std::vector<std::vector<bool>> m_vSlotStatus;
     std::vector<std::vector<CString>> m_vSlotText;
+    std::vector<std::vector<bool>> m_vSlotClickable;
+    SlotClickCallback m_fnSlotClickCallback;
 
     void DrawGrid(CDC* pDC);
 };
\ No newline at end of file

--
Gitblit v1.9.3