mrDarker
2025-06-06 4597db5a8e60149028e87d57692d61b97c456350
1. 添加Link Signal显示
2. 优化CJobSlotGrid::DrawGrid,支持文本换行
已修改3个文件
135 ■■■■ 文件已修改
SourceCode/Bond/Servo/CEquipmentPage1.cpp 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipmentPage1.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/JobSlotGrid.cpp 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CEquipmentPage1.cpp
@@ -9,6 +9,10 @@
// CEquipmentPage1 对话框
#define SIGNAL_GRID_ROWS 8
#define SIGNAL_GRID_COLS 8
#define SIGNAL_GRID_SIZE (SIGNAL_GRID_ROWS * SIGNAL_GRID_COLS)
IMPLEMENT_DYNAMIC(CEquipmentPage1, CHMPropertyPage)
CEquipmentPage1::CEquipmentPage1(CWnd* pParent /*=nullptr*/)
@@ -45,11 +49,64 @@
    m_pEquipment = pEquipment;
}
void CEquipmentPage1::InitSignalList()
{
    m_vSignalList.clear();
    // 写入设备的信号名称,默认状态为 false,默认都可点击(输出)
    m_vSignalList.push_back({ _T("Upstream\r\nInline"), false, true });
    m_vSignalList.push_back({ _T("Upstream\r\nTrouble"), false, true });
    m_vSignalList.push_back({ _T("Interlock"), false, false });
    m_vSignalList.push_back({ _T("Send\r\nAble"), false, true });
    m_vSignalList.push_back({ _T("Receive\r\nStart"), false, false });
    m_vSignalList.push_back({ _T("Job\r\nTransfer"), false, false });
    m_vSignalList.push_back({ _T("Receive\r\nComplete"), false, false });
    m_vSignalList.push_back({ _T("Shutter\r\nState"), false, false });
    // TODO: 添加更多信号,最多 64 个
    // 补齐至 SIGNAL_GRID_SIZE 项
    while (m_vSignalList.size() < SIGNAL_GRID_SIZE) {
        m_vSignalList.push_back({ _T(""), false, false });
    }
}
void CEquipmentPage1::LoadDeviceSignals()
{
    m_ctrlSignalPanel.SetGridSize(SIGNAL_GRID_ROWS, SIGNAL_GRID_COLS);
    for (int i = 0; i < SIGNAL_GRID_SIZE; ++i) {
        int row = i / SIGNAL_GRID_COLS;
        int col = i % SIGNAL_GRID_COLS;
        const auto& signal = m_vSignalList[i];
        // 显示状态(用颜色表示 ON/OFF)
        m_ctrlSignalPanel.SetSlotText(row, col, signal.strName);
        m_ctrlSignalPanel.SetSlotStatus(row, col, signal.bCurrentState);
        m_ctrlSignalPanel.SetSlotClickable(row, col, signal.bClickable);
        m_ctrlSignalPanel.SetTextFont(_T("Microsoft YaHei"), 10);
    }
    m_ctrlSignalPanel.SetSlotClickCallback([this](int nRow, int nCol) {
        int index = nRow * SIGNAL_GRID_COLS + nCol;
        if (index >= 0 && index < (int)m_vSignalList.size() && m_vSignalList[index].bClickable) {
            CString strMsg;
            strMsg.Format(_T("点击信号:%s"), m_vSignalList[index].strName);
            AfxMessageBox(strMsg);
        }
    });
}
BOOL CEquipmentPage1::OnInitDialog()
{
    CHMPropertyPage::OnInitDialog();
    // TODO:  在此添加额外的初始化
    m_ctrlSignalPanel.Create(AfxRegisterWndClass(0), _T("SignalGrid"), WS_CHILD | WS_VISIBLE, CRect(0, 0, 100, 100), this, 1002);
    m_ctrlSignalPanel.SetColors(RGB(0, 200, 0), RGB(220, 220, 220));
    InitSignalList();
    LoadDeviceSignals();
    return TRUE;  // return TRUE unless you set the focus to a control
                  // 异常: OCX 属性页应返回 FALSE
@@ -77,4 +134,10 @@
    CHMPropertyPage::OnSize(nType, cx, cy);
    // TODO: 在此处添加消息处理程序代码
    if (::IsWindow(m_ctrlSignalPanel.GetSafeHwnd())) {
        CRect rc;
        GetClientRect(&rc);
        rc.DeflateRect(10, 10);
        m_ctrlSignalPanel.MoveWindow(rc);
    }
}
SourceCode/Bond/Servo/CEquipmentPage1.h
@@ -1,9 +1,17 @@
#pragma once
#include "CHMPropertyPage.h"
#include "CEquipment.h"
#include "JobSlotGrid.h"
// CEquipmentPage1 对话框
struct SignalInfo
{
    CString strName;       // 信号名称
    bool bCurrentState;    // 当前状态(ON/OFF)
    bool bClickable;       // 是否允许点击
};
class CEquipmentPage1 : public CHMPropertyPage
{
@@ -17,6 +25,11 @@
private:
    SERVO::CEquipment* m_pEquipment;
    std::vector<SignalInfo> m_vSignalList;
    CJobSlotGrid m_ctrlSignalPanel;
    void InitSignalList();
    void LoadDeviceSignals();
// 对话框数据
SourceCode/Bond/Servo/JobSlotGrid.cpp
@@ -229,9 +229,22 @@
    CRect rect;
    GetClientRect(&rect);
    if (m_nCols == 0 || m_nRows == 0) {
        return;
    }
    // 计算格子尺寸
    int nCellWidth = rect.Width() / m_nCols;
    int nCellHeight = rect.Height() / m_nRows;
    // 字体设置
    CFont* pOldFont = pDC->SelectObject(&m_fontText);
    pDC->SetBkMode(TRANSPARENT);
    pDC->SetTextColor(RGB(0, 0, 0));
    // 定义颜色常量
    constexpr COLORREF COLOR_HOVER = RGB(200, 230, 255);
    constexpr COLORREF COLOR_CLICK = RGB(0, 120, 215);
    for (int i = 0; i < m_nRows; ++i) {
        for (int j = 0; j < m_nCols; ++j) {
@@ -241,29 +254,39 @@
            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;
            // 选择填充颜色
            COLORREF fillColor = m_vSlotStatus[i][j] ? m_colorHasJob : m_colorNoJob;
            if (IsSlotClickable(i, j)) {
                if (bIsClicking)
                    fillColor = COLOR_CLICK;
                else if (bIsHover)
                    fillColor = COLOR_HOVER;
            }
            // 画背景
            CBrush brush(fillColor);
            pDC->FillRect(&cellRect, &brush);
            // 绘制背景(高效替代 CBrush)
            pDC->FillSolidRect(&cellRect, fillColor);
            // 边框
            // 绘制边框
            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);
            // 获取文字(安全)
            CString strText;
            if (i < m_vSlotText.size() && j < m_vSlotText[i].size()) {
                strText = m_vSlotText[i][j];
            }
            if (!strText.IsEmpty()) {
                // 先计算文字高度(支持换行)
                CRect calcRect = cellRect;
                pDC->DrawText(strText, &calcRect, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX | DT_CALCRECT);
                // 重新设定居中绘制区域
                CRect textRect = cellRect;
                textRect.top += (cellRect.Height() - calcRect.Height()) / 2;
                // 实际绘制文字
                pDC->DrawText(strText, &textRect, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX);
            }
        }
    }