LAPTOP-SNT8I5JK\Boounion
2024-12-02 df0863b2c29fa227d186e6b8aeb4a856dcae12f3
SourceCode/Bond/BondEq/View/IOMonitoringDlg.cpp
@@ -5,7 +5,10 @@
#include "BondEq.h"
#include "afxdialogex.h"
#include "IOMonitoringDlg.h"
#include "ToolUnits.h"
#define TIMER_INIT            1
#define TIMER_READ_PLC_DATA      2
// CIOMonitoringDlg 对话框
@@ -51,6 +54,12 @@
   // 计算页数
   m_nCurrentPage = 1;
   m_nTotalPages = (m_displayData.size() + m_nRowsPerPage - 1) / m_nRowsPerPage;
}
void CIOMonitoringDlg::SetPLC(CPLC* pPLC)
{
   ASSERT(pPLC);
   m_pPLC = pPLC;
}
CFont* CIOMonitoringDlg::GetOrCreateFont(int nFontSize)
@@ -177,7 +186,41 @@
      x += colWidthLarge + groupSpacing;
      // 创建第 2 组 (3, 4, 5)
      CreateStaticControl(x, y, colWidthSmall, rowHeight, _T("OFF"), true, AlignCenter);
      CreateStaticControl(x, y, colWidthSmall, rowHeight, _T("OFF"), true, AlignCenter, [this, i]() {
         // 自定义点击事件的逻辑
         auto* pControl = static_cast<CBLLabel*>(m_staticControls[i * m_nCols + 3]);
         CString currentText;
         pControl->GetWindowText(currentText);
         BOOL bOn = FALSE;
         if (currentText == _T("OFF")) {
            //pControl->SetBkColor(RGB(0, 255, 0)); // 绿色背景
            //pControl->SetText(_T("ON"));          // 更新文本为 ON
            bOn = TRUE;
         }
         else {
            //pControl->SetBkColor(RGB(255, 0, 0)); // 红色背景
            //pControl->SetText(_T("OFF"));         // 更新文本为 OFF
            bOn = FALSE;
         }
         pControl = static_cast<CBLLabel*>(m_staticControls[i * m_nCols + 4]);
         pControl->GetWindowText(currentText);
         int nAddress;
         MC::SOFT_COMPONENT component;
         if (ParsePLCAddress(currentText, component, nAddress) && m_pPLC) {
            TRACE("地址解析成功: %s\n", currentText);
            m_pPLC->writeBit(component, nAddress, bOn, [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
               if (flag == 0) {
                  TRACE("写入成功: 地址: %d, 值: %lu\n", addr, value);
               }
               else {
                  TRACE("写入失败: 地址: %d, 错误码: %d\n", addr, flag);
               }
            });
         }
      });
      x += colWidthSmall;
      CreateStaticControl(x, y, colWidthSmall, rowHeight, _T("Y1010"), false, AlignCenter);
      x += colWidthSmall;
@@ -185,7 +228,7 @@
   }
}
void CIOMonitoringDlg::CreateStaticControl(int x, int y, int width, int height, const CString& text, bool hasBorder, TextAlign alignment)
void CIOMonitoringDlg::CreateStaticControl(int x, int y, int width, int height, const CString& text, bool hasBorder, TextAlign alignment, std::function<void()> clickCallback)
{
   // 创建动态控件
   CBLLabel* pStatic = new CBLLabel();
@@ -205,6 +248,11 @@
   pStatic->SetFontSize(nSize);
   pStatic->SetDynamicFont(TRUE);
   // 设置回调
   if (clickCallback) {
      pStatic->SetClickCallback(clickCallback);
   }
   // 存储控件指针
   m_staticControls.push_back(pStatic);
}
@@ -214,11 +262,18 @@
   int startIndex = (m_nCurrentPage - 1) * m_nRowsPerPage;
   int endIndex = min(startIndex + m_nRowsPerPage, static_cast<int>(m_displayData.size()));
   m_inputPLCAddresses.clear();
   m_outputPLCAddresses.clear();
   for (int i = 0; i < m_nRowsPerPage; ++i) {
      int row = i;
      if (startIndex + i < endIndex) {
         const auto& data = m_displayData[startIndex + i];
         // 添加 PLC 地址到容器中
         m_inputPLCAddresses.push_back(CString(data.inputAddress.c_str()));      // 1 列
         m_outputPLCAddresses.push_back(CString(data.outputAddress.c_str()));   // 4 列
         // 显示控件并设置内容
         m_staticControls[row * m_nCols + 0]->SetWindowText(_T("OFF"));
@@ -263,10 +318,127 @@
   m_staticControls.clear();
}
bool CIOMonitoringDlg::ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr)
{
   if (address.GetLength() < 2) {
      return false;
   }
   // 提取组件类型(第一个字符)
   TCHAR componentChar = address[0];
   switch (componentChar) {
   case 'D':
      component = MC::SOFT_COMPONENT::D;
      break;
   case 'M':
      component = MC::SOFT_COMPONENT::M;
      break;
   case 'X':
      component = MC::SOFT_COMPONENT::X;
      break;
   case 'Y':
      component = MC::SOFT_COMPONENT::Y;
      break;
   default:
      return false;
   }
   CString hexAddress = address.Mid(1);
   addr = _tcstoul(hexAddress, nullptr, 16);
   return true;
}
void CIOMonitoringDlg::UpdatePLCStates()
{
   // 示例:从 PLC 获取值,这里用随机值模拟
   //for (size_t i = 0; i < m_inputPLCAddresses.size(); ++i) {
   //   // 模拟获取输入状态
   //   bool inputState = (rand() % 2 == 0); // 偶尔为 true/false
   //   auto* inputControl = static_cast<CBLLabel*>(m_staticControls[i * m_nCols + 0]);
   //   inputControl->SetBkColor(inputState ? RGB(0, 255, 0) : RGB(255, 0, 0));
   //   inputControl->SetText(inputState ? _T("ON") : _T("OFF"));
   //}
   //for (size_t i = 0; i < m_outputPLCAddresses.size(); ++i) {
   //   // 模拟获取输出状态
   //   bool outputState = (rand() % 2 == 0); // 偶尔为 true/false
   //   auto* outputControl = static_cast<CBLLabel*>(m_staticControls[i * m_nCols + 3]);
   //   outputControl->SetBkColor(outputState ? RGB(0, 255, 0) : RGB(255, 0, 0));
   //   outputControl->SetText(outputState ? _T("ON") : _T("OFF"));
   //}
   // 输入地址的读取
   if (!m_inputPLCAddresses.empty()) {
      // 获取起始地址和长度
      CString startAddressStr = m_inputPLCAddresses.front();
      CString endAddressStr = m_inputPLCAddresses.back();
      MC::SOFT_COMPONENT component;
      int startAddress, endAddress;
      // 解析起始和结束地址
      if (ParsePLCAddress(startAddressStr, component, startAddress) &&
         ParsePLCAddress(endAddressStr, component, endAddress)) {
         int inputSize = endAddress - startAddress + 1;
         // 回调处理输入数据
         auto funOnReadInput = [this, startAddress](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) {
            if (nDataSize == (unsigned int)(m_inputPLCAddresses.size()) && flag == 0) {
               for (size_t i = 0; i < m_inputPLCAddresses.size(); ++i) {
                  int offset = i;
                  int value = CToolUnits::toInt16(&pData[offset]);
                  auto* inputControl = static_cast<CBLLabel*>(m_staticControls[i * m_nCols + 0]); // 第 0 列
                  inputControl->SetBkColor(value ? RGB(0, 255, 0) : RGB(255, 0, 0)); // 更新背景颜色
                  inputControl->SetText(value ? _T("ON") : _T("OFF"));               // 更新文本
               }
            }
         };
         // 读取输入数据
         m_pPLC->readData(component, startAddress, inputSize, funOnReadInput);
      }
   }
   // 输出地址的读取
   if (!m_outputPLCAddresses.empty()) {
      // 获取起始地址和长度
      CString startAddressStr = m_outputPLCAddresses.front();
      CString endAddressStr = m_outputPLCAddresses.back();
      MC::SOFT_COMPONENT component;
      int startAddress, endAddress;
      // 解析起始和结束地址
      if (ParsePLCAddress(startAddressStr, component, startAddress) &&
         ParsePLCAddress(endAddressStr, component, endAddress)) {
         int outputSize = endAddress - startAddress + 1;
         // 回调处理输出数据
         auto funOnReadOutput = [this, startAddress](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) {
            if (nDataSize == (unsigned int)(m_outputPLCAddresses.size()) && flag == 0) {
               for (size_t i = 0; i < m_outputPLCAddresses.size(); ++i) {
                  int offset = i;
                  int value = CToolUnits::toInt16(&pData[offset]);
                  auto* outputControl = static_cast<CBLLabel*>(m_staticControls[i * m_nCols + 3]); // 第 3 列
                  outputControl->SetBkColor(value ? RGB(0, 255, 0) : RGB(255, 0, 0)); // 更新背景颜色
                  outputControl->SetText(value ? _T("ON") : _T("OFF"));               // 更新文本
               }
            }
         };
         // 读取输出数据
         m_pPLC->readData(component, startAddress, outputSize, funOnReadOutput);
      }
   }
}
BEGIN_MESSAGE_MAP(CIOMonitoringDlg, CDialogEx)
   ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CIOMonitoringDlg::OnBnClickedButtonPrevPage)
   ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CIOMonitoringDlg::OnBnClickedButtonNextPage)
   ON_WM_SIZE()
   ON_WM_TIMER()
   ON_WM_CLOSE()
END_MESSAGE_MAP()
@@ -331,6 +503,8 @@
   CreateDynamicControls();
   DisplayCurrentPage();
   SetTimer(TIMER_READ_PLC_DATA, 500, nullptr);
   return TRUE;  // return TRUE unless you set the focus to a control
   // 异常: OCX 属性页应返回 FALSE
}
@@ -374,3 +548,21 @@
      AfxMessageBox(_T("已经是最后一页!"));
   }
}
void CIOMonitoringDlg::OnTimer(UINT_PTR nIDEvent)
{
   // TODO: 在此添加消息处理程序代码和/或调用默认值
   if (TIMER_READ_PLC_DATA == nIDEvent) {
      ASSERT(m_pPLC);
      UpdatePLCStates();
      Sleep(100);
   }
   CDialogEx::OnTimer(nIDEvent);
}
void CIOMonitoringDlg::OnClose()
{
   // TODO: 在此添加消息处理程序代码和/或调用默认值
   KillTimer(TIMER_READ_PLC_DATA);
   CDialogEx::OnClose();
}