LAPTOP-SNT8I5JK\Boounion
2024-12-12 016703bb359382dc1de4ac204da47b6f29c55c81
SourceCode/Bond/BondEq/View/IOMonitoringDlg.cpp
@@ -9,6 +9,12 @@
#define TIMER_INIT            1
#define TIMER_READ_PLC_DATA      2
#define TIMER_READ_UPDATE      3
#define LABEL_ID_BEGIN         2000
#define   ADDR_WND            _T("ADDR_WND")
#define ID_MSG_IO_CLICK         WM_USER + 101
// CIOMonitoringDlg 对话框
@@ -19,7 +25,7 @@
{
   m_nCurrentPage = 1;
   m_nTotalPages = 1;
   m_nRowsPerPage = 10;
   m_nRowsPerPage = 16;
   m_nCols = 6;
}
@@ -53,7 +59,7 @@
   // 计算页数
   m_nCurrentPage = 1;
   m_nTotalPages = (m_displayData.size() + m_nRowsPerPage - 1) / m_nRowsPerPage;
   m_nTotalPages = ((int)m_displayData.size() + m_nRowsPerPage - 1) / m_nRowsPerPage;
}
void CIOMonitoringDlg::SetPLC(CPLC* pPLC)
@@ -155,7 +161,7 @@
   ScreenToClient(&nextButtonRect);
   int buttonHeight = prevButtonRect.Height();     // 按钮的高度
   int topMargin = rect.Height() * 0.05;           // 顶部保留 5% 的高度
   int topMargin = int(rect.Height() * 0.05);      // 顶部保留 5% 的高度
   int bottomMargin = buttonHeight + topMargin;    // 底部保留按钮高度加间距
   int sideMargin = topMargin;                     // 左右间距与顶部间距相同
   int groupSpacing = 20;                          // 两组之间的间距
@@ -170,73 +176,48 @@
   int colWidthLarge = availableWidth * 4 / 14;      // 大宽度列比例
   int groupWidth = colWidthSmall * 2 + colWidthLarge; // 每组总宽度
   UINT id = LABEL_ID_BEGIN;
   for (int i = 0; i < m_nRowsPerPage; ++i) {
      // 每一行的起始 Y 坐标
      int y = topMargin + i * (rowHeight + verticalSpacing);
      // 创建第 1 组 (0, 1, 2)
      int x = sideMargin; // 从左边距开始
      CreateStaticControl(x, y, colWidthSmall, rowHeight, _T("OFF"), true, AlignCenter);
      CreateStaticControl(++id, x, y, colWidthSmall, rowHeight, _T("OFF"), true, AlignCenter);
      x += colWidthSmall;
      CreateStaticControl(x, y, colWidthSmall, rowHeight, _T("X1000"), false, AlignCenter);
      CreateStaticControl(++id, x, y, colWidthSmall, rowHeight, _T("X1000"), false, AlignCenter);
      x += colWidthSmall;
      CreateStaticControl(x, y, colWidthLarge, rowHeight, _T("描述文本"), false);
      CreateStaticControl(++id, x, y, colWidthLarge, rowHeight, _T("描述文本"), false);
      // 第 2 组起始位置,加上组间距
      x += colWidthLarge + groupSpacing;
      // 创建第 2 组 (3, 4, 5)
      CreateStaticControl(x, y, colWidthSmall, rowHeight, _T("OFF"), true, AlignCenter, [this, i]() {
      id++;
      CWnd* pBtn = CreateStaticControl(id, x, y, colWidthSmall, rowHeight, _T("OFF"), true, AlignCenter, [this, id, i, x, y]() {
         // 自定义点击事件的逻辑
         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);
               }
            });
         }
         PostMessage(ID_MSG_IO_CLICK, id, currentText == _T("OFF") ? 1 : 0);
      });
      x += colWidthSmall;
      CreateStaticControl(x, y, colWidthSmall, rowHeight, _T("Y1010"), false, AlignCenter);
      CWnd* pLabel = CreateStaticControl(++id, x, y, colWidthSmall, rowHeight, _T("Y1010"), false, AlignCenter);
      x += colWidthSmall;
      CreateStaticControl(x, y, colWidthLarge, rowHeight, _T("描述文本"), false);
      CreateStaticControl(++id, x, y, colWidthLarge, rowHeight, _T("描述文本"), false);
      ::SetProp(pBtn->GetSafeHwnd(), ADDR_WND, pLabel);
   }
}
void CIOMonitoringDlg::CreateStaticControl(int x, int y, int width, int height, const CString& text, bool hasBorder, TextAlign alignment, std::function<void()> clickCallback)
CWnd* CIOMonitoringDlg::CreateStaticControl(UINT id, int x, int y, int width, int height, const CString& text, bool hasBorder, TextAlign alignment, std::function<void()> clickCallback)
{
   // 创建动态控件
   CBLLabel* pStatic = new CBLLabel();
   DWORD style = WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE; // 确保垂直居中
   if (hasBorder) {
      style |= WS_BORDER; // 添加边框
   if (!hasBorder) {
      pStatic->DisableBorder();
   }
   pStatic->Create(text, style, CRect(x, y, x + width, y + height), this);
   pStatic->Create(text, style, CRect(x, y, x + width, y + height), this, id);
   // 设置文本对齐方式
   pStatic->SetAlignment(alignment);
@@ -249,12 +230,43 @@
   pStatic->SetDynamicFont(TRUE);
   // 设置回调
   if (clickCallback) {
   UserManager& userManager = UserManager::getInstance();
   UserRole enRole = userManager.getCurrentUserRole();
   if (clickCallback && (enRole == UserRole::SuperAdmin || enRole == UserRole::Operator)) {
      pStatic->SetClickCallback(clickCallback);
      pStatic->SetRoundedCorners(TRUE, 5);
      pStatic->DisableBorder();
   }
   // 存储控件指针
   m_staticControls.push_back(pStatic);
   return pStatic;
}
CWnd* CIOMonitoringDlg::GetStaticControl(UINT id)
{
   for (auto item : m_staticControls) {
      TRACE(">>id:%d\n", item->GetDlgCtrlID());
      if (item->GetDlgCtrlID() == id) {
         return item;
      }
   }
   return nullptr;
}
CString& CIOMonitoringDlg::GetStaticControlAddrText(UINT id, CString& strAddr)
{
   CWnd* pBtn = GetStaticControl(id);
   if (pBtn != nullptr) {
      CWnd* pLabel = (CWnd*)::GetProp(pBtn->GetSafeHwnd(), ADDR_WND);
      if (pLabel != nullptr) {
         pLabel->GetWindowText(strAddr);
      }
   }
   return strAddr;
}
void CIOMonitoringDlg::DisplayCurrentPage()
@@ -262,6 +274,8 @@
   int startIndex = (m_nCurrentPage - 1) * m_nRowsPerPage;
   int endIndex = min(startIndex + m_nRowsPerPage, static_cast<int>(m_displayData.size()));
   m_inputStates.clear();
   m_outputStates.clear();
   m_inputPLCAddresses.clear();
   m_outputPLCAddresses.clear();
@@ -270,6 +284,10 @@
      if (startIndex + i < endIndex) {
         const auto& data = m_displayData[startIndex + i];
         // 添加状态到容器中
         m_inputStates.push_back(FALSE);      // 0 列
         m_outputStates.push_back(FALSE);   // 3 列
         // 添加 PLC 地址到容器中
         m_inputPLCAddresses.push_back(CString(data.inputAddress.c_str()));      // 1 列
@@ -326,109 +344,210 @@
   // 提取组件类型(第一个字符)
   TCHAR componentChar = address[0];
   if (address.Left(2) == _T("ZR")) {
      component = MC::SOFT_COMPONENT::ZR;
      // 提取数字部分(去除ZR前缀)
      CString numericAddress = address.Mid(2);
      addr = _tcstoul(numericAddress, nullptr, 16);
      return addr != 0 || numericAddress.CompareNoCase(_T("0")) == 0;  // 如果是 "0",也认为有效
   }
   // 对于其他组件,按照常规规则处理
   CString hexAddress = address.Mid(1);
   switch (componentChar) {
   case 'D':
      component = MC::SOFT_COMPONENT::D;
      addr = _ttoi(hexAddress);
      break;
   case 'M':
      component = MC::SOFT_COMPONENT::M;
      addr = _tcstoul(hexAddress, nullptr, 16);
      break;
   case 'X':
      component = MC::SOFT_COMPONENT::X;
      addr = _tcstoul(hexAddress, nullptr, 16);
      break;
   case 'Y':
      component = MC::SOFT_COMPONENT::Y;
      addr = _tcstoul(hexAddress, nullptr, 16);
      break;
   case 'W':
      component = MC::SOFT_COMPONENT::W;
      addr = _tcstoul(hexAddress, nullptr, 16);
      break;
   case 'L':
      component = MC::SOFT_COMPONENT::L;
      addr = _tcstoul(hexAddress, nullptr, 16);
      break;
   case 'S':
      component = MC::SOFT_COMPONENT::S;
      addr = _tcstoul(hexAddress, nullptr, 16);
      break;
   case 'B':
      component = MC::SOFT_COMPONENT::B;
      addr = _tcstoul(hexAddress, nullptr, 16);
      break;
   case 'F':
      component = MC::SOFT_COMPONENT::F;
      addr = _tcstoul(hexAddress, nullptr, 16);
      break;
   default:
      return false;
   }
   CString hexAddress = address.Mid(1);
   addr = _tcstoul(hexAddress, nullptr, 16);
   // 检查地址是否有效
   if (addr == 0 && hexAddress.CompareNoCase(_T("0")) != 0) {
      return false;
   }
   return true;
}
void CIOMonitoringDlg::UpdatePLCStates()
bool CIOMonitoringDlg::GeneratePLCAddress(MC::SOFT_COMPONENT component, int addr, CString& address, bool bHexFormat)
{
   // 示例:从 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);
      }
   // 根据组件类型生成前缀
   CString prefix;
   switch (component) {
   case MC::SOFT_COMPONENT::D:
      prefix = _T("D");
      break;
   case MC::SOFT_COMPONENT::M:
      prefix = _T("M");
      break;
   case MC::SOFT_COMPONENT::X:
      prefix = _T("X");
      break;
   case MC::SOFT_COMPONENT::Y:
      prefix = _T("Y");
      break;
   case MC::SOFT_COMPONENT::W:
      prefix = _T("W");
      break;
   case MC::SOFT_COMPONENT::L:
      prefix = _T("L");
      break;
   case MC::SOFT_COMPONENT::S:
      prefix = _T("S");
      break;
   case MC::SOFT_COMPONENT::B:
      prefix = _T("B");
      break;
   case MC::SOFT_COMPONENT::F:
      prefix = _T("F");
      break;
   case MC::SOFT_COMPONENT::ZR:
      prefix = _T("ZR");
      break;
   default:
      return false;  // 如果是未知组件类型,返回失败
   }
   // 输出地址的读取
   if (!m_outputPLCAddresses.empty()) {
      // 获取起始地址和长度
      CString startAddressStr = m_outputPLCAddresses.front();
      CString endAddressStr = m_outputPLCAddresses.back();
      MC::SOFT_COMPONENT component;
      int startAddress, endAddress;
   // 根据 bHexFormat 判断输出格式
   CString strAddr;
   if (bHexFormat) {
      strAddr.Format(_T("%X"), addr);  // 十六进制格式
   }
   else {
      strAddr.Format(_T("%d"), addr);  // 十进制格式
   }
      // 解析起始和结束地址
      if (ParsePLCAddress(startAddressStr, component, startAddress) &&
         ParsePLCAddress(endAddressStr, component, endAddress)) {
         int outputSize = endAddress - startAddress + 1;
   // 生成最终的地址字符串
   address = prefix + strAddr;
   return true;
}
         // 回调处理输出数据
         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]);
// 处理PLC数据读取的通用方法
void CIOMonitoringDlg::ReadPLCData(MC::SOFT_COMPONENT softComponent, int startAddr, int endAddr, std::function<void(IMcChannel*, int, char*, unsigned int, int)> callback)
{
   int nSize;
   // 检查地址是否有效,以及组件是否匹配
   nSize = endAddr - startAddr + 1;
   if (nSize < 1) {
      return;
   }
                  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(softComponent, startAddr, nSize, callback);
}
void CIOMonitoringDlg::ReadPLCStates()
{
   if (m_displayData.empty()) {
      return;
   }
   auto startData = m_displayData.front();
   auto endData = m_displayData.back();
   MC::SOFT_COMPONENT startSoftComponent, endSoftComponent;
   int inputStartAddr, inputEndAddr;
   ParsePLCAddress(CString(startData.inputAddress.c_str()), startSoftComponent, inputStartAddr);
   ParsePLCAddress(CString(endData.inputAddress.c_str()), endSoftComponent, inputEndAddr);
   ASSERT(startSoftComponent == endSoftComponent);
   // 读取输入数据
   ReadPLCData(startSoftComponent, inputStartAddr, inputEndAddr, [this, inputStartAddr](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) {
      if (!::IsWindow(m_hWnd)) return;
      for (auto& data : m_displayData) {
         int nAddress;
         MC::SOFT_COMPONENT enComponent;
         if (ParsePLCAddress(CString(data.inputAddress.c_str()), enComponent, nAddress)) {
            int nOffset = nAddress - inputStartAddr;
            if (nOffset >= 0 && nOffset < (int)nDataSize) {
               int byteIndex = nOffset / 8;
               int bitIndex = nOffset % 8;
               data.bInputStates = CToolUnits::getBit(pData[byteIndex], bitIndex);
            }
         };
         }
      }
   });
         // 读取输出数据
         m_pPLC->readData(component, startAddress, outputSize, funOnReadOutput);
   // 读取输出数据
   int outputStartAddr, outputEndAddr;
   ParsePLCAddress(CString(startData.outputAddress.c_str()), startSoftComponent, outputStartAddr);
   ParsePLCAddress(CString(endData.outputAddress.c_str()), endSoftComponent, outputEndAddr);
   ASSERT(startSoftComponent == endSoftComponent);
   ReadPLCData(startSoftComponent, outputStartAddr, outputEndAddr, [this, outputStartAddr](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) {
      if (!::IsWindow(m_hWnd)) return;
      for (auto& data : m_displayData) {
         int nAddress;
         MC::SOFT_COMPONENT enComponent;
         if (ParsePLCAddress(CString(data.outputAddress.c_str()), enComponent, nAddress)) {
            int nOffset = nAddress - outputStartAddr;
            if (nOffset >= 0 && nOffset < (int)nDataSize) {
               int byteIndex = nOffset / 8;
               int bitIndex = nOffset % 8;
               data.bOutputStates = CToolUnits::getBit(pData[byteIndex], bitIndex);
               TRACE(">>>> %d %d %d |||| %d\n", nOffset, byteIndex, bitIndex, data.bOutputStates);
            }
         }
      }
   });
}
void CIOMonitoringDlg::UpdatePLCStatesToUI()
{
   int startIndex = (m_nCurrentPage - 1) * m_nRowsPerPage;
   int endIndex = min(startIndex + m_nRowsPerPage, static_cast<int>(m_displayData.size()));
   for (int i = 0; i < m_nRowsPerPage; ++i) {
      int row = i;
      if (startIndex + i < endIndex) {
         const auto& data = m_displayData[startIndex + i];
         // 设置内容和背景颜色
         if (m_inputStates[i] != data.bInputStates)
         {
            m_staticControls[row * m_nCols + 0]->SetText(data.bInputStates ? _T("ON") : _T("OFF"));
            m_staticControls[row * m_nCols + 0]->SetBkColor(data.bInputStates ? RGB(0, 255, 0) : RGB(255, 0, 0));
            m_inputStates[i] = data.bInputStates;
         }
         if (m_outputStates[i] != data.bOutputStates)
         {
            m_staticControls[row * m_nCols + 3]->SetText(data.bOutputStates ? _T("ON") : _T("OFF"));
            m_staticControls[row * m_nCols + 3]->SetBkColor(data.bOutputStates ? RGB(0, 255, 0) : RGB(255, 0, 0));
            m_outputStates[i] = data.bOutputStates;
         }
      }
   }
}
@@ -436,6 +555,7 @@
BEGIN_MESSAGE_MAP(CIOMonitoringDlg, CDialogEx)
   ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CIOMonitoringDlg::OnBnClickedButtonPrevPage)
   ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CIOMonitoringDlg::OnBnClickedButtonNextPage)
   ON_MESSAGE(ID_MSG_IO_CLICK, &CIOMonitoringDlg::OnIoClicked)
   ON_WM_SIZE()
   ON_WM_TIMER()
   ON_WM_CLOSE()
@@ -486,8 +606,8 @@
   }
   GetWindowRect(&dlgRect);
   int dlgWidth = dlgRect.Width() * 2;
   int dlgHeight = dlgRect.Height() * 2;
   int dlgWidth = dlgRect.Width() * 3;
   int dlgHeight = dlgRect.Height() * 3;
   if (dlgWidth > screenRect.Width()) {
      dlgWidth = screenRect.Width();
@@ -503,7 +623,11 @@
   CreateDynamicControls();
   DisplayCurrentPage();
   GetDlgItem(IDC_BUTTON_PREV_PAGE)->EnableWindow(m_nCurrentPage > 1);
   GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurrentPage < m_nTotalPages);
   SetTimer(TIMER_READ_PLC_DATA, 500, nullptr);
   SetTimer(TIMER_READ_UPDATE, 200, nullptr);
   return TRUE;  // return TRUE unless you set the focus to a control
   // 异常: OCX 属性页应返回 FALSE
@@ -535,6 +659,9 @@
   else {
      AfxMessageBox(_T("已经是第一页!"));
   }
   GetDlgItem(IDC_BUTTON_PREV_PAGE)->EnableWindow(m_nCurrentPage > 1);
   GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurrentPage < m_nTotalPages);
}
void CIOMonitoringDlg::OnBnClickedButtonNextPage()
@@ -547,6 +674,33 @@
   else {
      AfxMessageBox(_T("已经是最后一页!"));
   }
   GetDlgItem(IDC_BUTTON_PREV_PAGE)->EnableWindow(m_nCurrentPage > 1);
   GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurrentPage < m_nTotalPages);
}
LRESULT CIOMonitoringDlg::OnIoClicked(WPARAM wParam, LPARAM lParam)
{
   CString strAddr;
   GetStaticControlAddrText((UINT)wParam, strAddr);
   BOOL bOn = (BOOL)lParam;
   int nAddress;
   MC::SOFT_COMPONENT component;
   if (ParsePLCAddress(strAddr, component, nAddress) && m_pPLC) {
      TRACE("地址解析成功: %s %d\n", strAddr, GetCurrentThreadId());
      int n = 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);
         }
         });
      TRACE("地址解析成功2: %d\n", n);
   }
   return 0;
}
void CIOMonitoringDlg::OnTimer(UINT_PTR nIDEvent)
@@ -554,9 +708,13 @@
   // TODO: 在此添加消息处理程序代码和/或调用默认值
   if (TIMER_READ_PLC_DATA == nIDEvent) {
      ASSERT(m_pPLC);
      UpdatePLCStates();
      Sleep(100);
      ReadPLCStates();
   }
   else if (TIMER_READ_UPDATE == nIDEvent) {
      ASSERT(m_pPLC);
      UpdatePLCStatesToUI();
   }
   CDialogEx::OnTimer(nIDEvent);
}
@@ -564,5 +722,6 @@
{
   // TODO: 在此添加消息处理程序代码和/或调用默认值
   KillTimer(TIMER_READ_PLC_DATA);
   KillTimer(TIMER_READ_UPDATE);
   CDialogEx::OnClose();
}