| | |
| | | #include "BondEq.h" |
| | | #include "afxdialogex.h" |
| | | #include "IOMonitoringDlg.h" |
| | | #include "ToolUnits.h" |
| | | |
| | | #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 对话框 |
| | | |
| | |
| | | { |
| | | m_nCurrentPage = 1; |
| | | m_nTotalPages = 1; |
| | | m_nRowsPerPage = 10; |
| | | m_nRowsPerPage = 16; |
| | | m_nCols = 6; |
| | | } |
| | | |
| | |
| | | |
| | | // 计算页数 |
| | | 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) |
| | | { |
| | | ASSERT(pPLC); |
| | | m_pPLC = pPLC; |
| | | } |
| | | |
| | | CFont* CIOMonitoringDlg::GetOrCreateFont(int nFontSize) |
| | |
| | | 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; // 两组之间的间距 |
| | |
| | | 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); |
| | | |
| | | if (currentText == _T("OFF")) { |
| | | pControl->SetBkColor(RGB(0, 255, 0)); // 绿色背景 |
| | | pControl->SetText(_T("ON")); // 更新文本为 ON |
| | | } |
| | | else { |
| | | pControl->SetBkColor(RGB(255, 0, 0)); // 红色背景 |
| | | pControl->SetText(_T("OFF")); // 更新文本为 OFF |
| | | } |
| | | 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); |
| | |
| | | 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() |
| | |
| | | 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(); |
| | | |
| | |
| | | |
| | | 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 列 |
| | |
| | | m_staticControls.clear(); |
| | | } |
| | | |
| | | void CIOMonitoringDlg::UpdatePLCStates() |
| | | bool CIOMonitoringDlg::ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr) |
| | | { |
| | | // 随机值模拟 |
| | | 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")); |
| | | if (address.GetLength() < 2) { |
| | | return false; |
| | | } |
| | | |
| | | 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")); |
| | | // 提取组件类型(第一个字符) |
| | | 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; |
| | | } |
| | | |
| | | // 检查地址是否有效 |
| | | if (addr == 0 && hexAddress.CompareNoCase(_T("0")) != 0) { |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | bool CIOMonitoringDlg::GeneratePLCAddress(MC::SOFT_COMPONENT component, int addr, CString& address, bool bHexFormat) |
| | | { |
| | | // 根据组件类型生成前缀 |
| | | 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; // 如果是未知组件类型,返回失败 |
| | | } |
| | | |
| | | // 根据 bHexFormat 判断输出格式 |
| | | CString strAddr; |
| | | if (bHexFormat) { |
| | | strAddr.Format(_T("%X"), addr); // 十六进制格式 |
| | | } |
| | | else { |
| | | strAddr.Format(_T("%d"), addr); // 十进制格式 |
| | | } |
| | | |
| | | // 生成最终的地址字符串 |
| | | address = prefix + strAddr; |
| | | return true; |
| | | } |
| | | |
| | | // 处理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; |
| | | } |
| | | |
| | | // 读取数据 |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | |
| | | // 读取输出数据 |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | 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() |
| | |
| | | } |
| | | |
| | | 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(); |
| | |
| | | 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 |
| | |
| | | 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() |
| | |
| | | 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) |
| | | { |
| | | // TODO: 在此添加消息处理程序代码和/或调用默认值 |
| | | if (TIMER_READ_PLC_DATA == nIDEvent) { |
| | | //ASSERT(m_pPLC); |
| | | UpdatePLCStates(); |
| | | Sleep(100); |
| | | ASSERT(m_pPLC); |
| | | ReadPLCStates(); |
| | | } |
| | | else if (TIMER_READ_UPDATE == nIDEvent) { |
| | | ASSERT(m_pPLC); |
| | | UpdatePLCStatesToUI(); |
| | | } |
| | | |
| | | CDialogEx::OnTimer(nIDEvent); |
| | | } |
| | | |
| | |
| | | { |
| | | // TODO: 在此添加消息处理程序代码和/或调用默认值 |
| | | KillTimer(TIMER_READ_PLC_DATA); |
| | | KillTimer(TIMER_READ_UPDATE); |
| | | CDialogEx::OnClose(); |
| | | } |