SourceCode/Bond/Servo/CEquipmentPage1.cpp
@@ -13,6 +13,9 @@
#define SIGNAL_GRID_COLS 8
#define SIGNAL_GRID_SIZE (SIGNAL_GRID_ROWS * SIGNAL_GRID_COLS)
#define TIMER_ID_SIGNAL_UPDATE  1001
#define TIMER_INTERVAL_MS       1000  // 每 1 秒更新一次
IMPLEMENT_DYNAMIC(CEquipmentPage1, CHMPropertyPage)
CEquipmentPage1::CEquipmentPage1(CWnd* pParent /*=nullptr*/)
@@ -36,6 +39,7 @@
   ON_WM_CTLCOLOR()
   ON_WM_DESTROY()
   ON_WM_SIZE()
   ON_WM_TIMER()
END_MESSAGE_MAP()
@@ -51,28 +55,9 @@
   if (m_pEquipment != nullptr) {
      InitSignalListForDevice(pEquipment->getID());
      LoadSignalPanelUI();
   }
   else {
      m_nCurrentDeviceID = 0;
      m_vSignalList.clear();
      m_ctrlSignalPanel.ClearAll();
   }
}
void CEquipmentPage1::LoadSignalPanelUI()
{
   if (!::IsWindow(m_ctrlSignalPanel.GetSafeHwnd())) {
      return;
   }
   for (int i = 0; i < SIGNAL_GRID_SIZE; ++i) {
      int nRow = i / SIGNAL_GRID_COLS;
      int nCol = i % SIGNAL_GRID_COLS;
      const auto& signal = m_vSignalList[i];
      m_ctrlSignalPanel.SetSlotText(nRow, nCol, signal.strName);
      m_ctrlSignalPanel.SetSlotClickable(nRow, nCol, signal.bClickable);
      ResetSignalPanel();
   }
}
@@ -117,8 +102,8 @@
      CString strSignalName = tokens[1];
      bool bClickable = _ttoi(tokens[2]) ? TRUE : FALSE;
      if (nDeviceID <= 0 || strSignalName.IsEmpty()) {
         TRACE(_T("CSV 数据无效 [行 %d]:设备ID或信号名为空。\n"), nLineNum);
      if (nDeviceID <= 0 || nDeviceID > 999 || strSignalName.IsEmpty()) {
         TRACE(_T("CSV 行 %d:无效设备ID=%d 或信号名为空\n"), nLineNum, nDeviceID);
         continue;
      }
@@ -138,7 +123,6 @@
   auto it = m_mapSignalListByID.find(nDeviceID);
   if (it != m_mapSignalListByID.end()) {
      m_vSignalList = it->second;
      UpdateAllSignalStatesFromDevice();
   }
   else {
      TRACE(_T("Warning: No signals found for DeviceID=%d\n"), nDeviceID);
@@ -148,6 +132,9 @@
   while (m_vSignalList.size() < SIGNAL_GRID_SIZE) {
      m_vSignalList.push_back({ _T(""), false, false });
   }
   InitSignalSlotTextAndClickable();
   UpdateAllSignalStatesFromDevice();
}
void CEquipmentPage1::UpdateSignalState(int nRow, int nCol, bool bNewState)
@@ -161,10 +148,28 @@
      return;
   }
   m_vSignalList[nIndex].bCurrentState = bNewState;
   m_ctrlSignalPanel.SetSlotStatus(nRow, nCol, bNewState);
   if (m_vSignalList[nIndex].bCurrentState != bNewState) {
      m_vSignalList[nIndex].bCurrentState = bNewState;
      m_ctrlSignalPanel.SetSlotStatus(nRow, nCol, bNewState);
   TRACE(_T("UpdateSignalState: [%d, %d] = %d\n"), nRow, nCol, bNewState);
      TRACE(_T("[Device %d] UpdateSignalState: [%d, %d] = %d\n"), m_nCurrentDeviceID, nRow, nCol, bNewState);
   }
}
void CEquipmentPage1::InitSignalSlotTextAndClickable()
{
   if (!::IsWindow(m_ctrlSignalPanel.GetSafeHwnd())) {
      return;
   }
   for (int i = 0; i < SIGNAL_GRID_SIZE; ++i) {
      int nRow = i / SIGNAL_GRID_COLS;
      int nCol = i % SIGNAL_GRID_COLS;
      const auto& signal = m_vSignalList[i];
      m_ctrlSignalPanel.SetSlotText(nRow, nCol, signal.strName);
      m_ctrlSignalPanel.SetSlotClickable(nRow, nCol, signal.bClickable);
   }
}
void CEquipmentPage1::UpdateAllSignalStatesFromDevice()
@@ -175,10 +180,21 @@
   for (int nRow = 0; nRow < SIGNAL_GRID_ROWS; ++nRow) {
      for (int nCol = 0; nCol < SIGNAL_GRID_COLS; ++nCol) {
         BOOL bCurrentState = m_pEquipment->isLinkSignalOn(nRow, nCol);
         BOOL bCurrentState = m_pEquipment->isLinkSignalUpstreamOn(nRow, nCol);
         UpdateSignalState(nRow, nCol, bCurrentState);
      }
   }
}
void CEquipmentPage1::ResetSignalPanel()
{
   if (!::IsWindow(m_ctrlSignalPanel.GetSafeHwnd())) {
      return;
   }
   m_ctrlSignalPanel.ClearAll();
   m_vSignalList.clear();
   m_nCurrentDeviceID = 0;
}
BOOL CEquipmentPage1::OnInitDialog()
@@ -194,8 +210,8 @@
      int index = nRow * SIGNAL_GRID_COLS + nCol;
      if (index >= 0 && index < (int)m_vSignalList.size() && m_vSignalList[index].bClickable && m_pEquipment != nullptr) {
         // 读取当前状态并切换
         const BOOL bCurrentState = m_pEquipment->isLinkSignalOn(nRow, nCol);
         m_pEquipment->setLinkSignal(nRow, nCol, !bCurrentState);
         const BOOL bCurrentState = m_pEquipment->isLinkSignalUpstreamOn(nRow, nCol);
         m_pEquipment->setLinkSignalUpstream(nRow, nCol, !bCurrentState);
      }
   });
@@ -210,8 +226,10 @@
   // 如果设备已设置,则初始化信号列表
   if (m_pEquipment != nullptr) {
      InitSignalListForDevice(m_pEquipment->getID());
      LoadSignalPanelUI();
   }
   KillTimer(TIMER_ID_SIGNAL_UPDATE);
   SetTimer(TIMER_ID_SIGNAL_UPDATE, TIMER_INTERVAL_MS, nullptr);
   return TRUE;  // return TRUE unless you set the focus to a control
              // 异常: OCX 属性页应返回 FALSE
@@ -232,7 +250,10 @@
   CHMPropertyPage::OnDestroy();
   // TODO: 在此处添加消息处理程序代码
   m_ctrlSignalPanel.DestroyWindow();
   KillTimer(TIMER_ID_SIGNAL_UPDATE);
   if (::IsWindow(m_ctrlSignalPanel.GetSafeHwnd())) {
      m_ctrlSignalPanel.DestroyWindow();
   }
}
void CEquipmentPage1::OnSize(UINT nType, int cx, int cy)
@@ -247,3 +268,14 @@
      m_ctrlSignalPanel.MoveWindow(rc);
   }
}
void CEquipmentPage1::OnTimer(UINT_PTR nIDEvent)
{
   if (nIDEvent == TIMER_ID_SIGNAL_UPDATE) {
      if (m_pEquipment && !m_vSignalList.empty()) {
         UpdateAllSignalStatesFromDevice();
      }
   }
   CHMPropertyPage::OnTimer(nIDEvent);
}