1. 添加Link Signal显示
2. 优化CJobSlotGrid::DrawGrid,支持文本换行
| | |
| | | |
| | | // 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*/) |
| | |
| | | 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 |
| | |
| | | CHMPropertyPage::OnSize(nType, cx, cy); |
| | | |
| | | // TODO: 在此处添加消息处理程序代码 |
| | | if (::IsWindow(m_ctrlSignalPanel.GetSafeHwnd())) { |
| | | CRect rc; |
| | | GetClientRect(&rc); |
| | | rc.DeflateRect(10, 10); |
| | | m_ctrlSignalPanel.MoveWindow(rc); |
| | | } |
| | | } |
| | |
| | | #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 |
| | | { |
| | |
| | | |
| | | private: |
| | | SERVO::CEquipment* m_pEquipment; |
| | | std::vector<SignalInfo> m_vSignalList; |
| | | CJobSlotGrid m_ctrlSignalPanel; |
| | | |
| | | void InitSignalList(); |
| | | void LoadDeviceSignals(); |
| | | |
| | | |
| | | // 对话框数据 |
| | |
| | | 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) { |
| | |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | |