From 8da35975404dd92801b1006f76f2ea6c200016d2 Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期四, 05 十二月 2024 09:03:22 +0800
Subject: [PATCH] 1.IO测试页面;

---
 SourceCode/Bond/BondEq/CPLC.cpp                      |    6 
 SourceCode/Bond/BondEq/CPLC.h                        |    1 
 SourceCode/Bond/BondEq/ToolUnits.h                   |    1 
 SourceCode/Bond/BondEq/View/AxisSettingsDlg.h        |    3 
 SourceCode/Bond/BondEq/FileManager/IOManager.h       |    2 
 SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp      |  157 +++++++++++++--
 SourceCode/Bond/BondEq/View/IOMonitoringDlg.cpp      |  362 ++++++++++++++++++++++++------------
 SourceCode/Bond/BondEq/View/IOMonitoringDlg.h        |   18 +
 SourceCode/Bond/BondEq/ToolUnits.cpp                 |   35 +++
 SourceCode/Bond/BondEq/FileManager/IOManager.cpp     |    7 
 SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp |    2 
 11 files changed, 441 insertions(+), 153 deletions(-)

diff --git a/SourceCode/Bond/BondEq/CPLC.cpp b/SourceCode/Bond/BondEq/CPLC.cpp
index ba307d3..3c4d175 100644
--- a/SourceCode/Bond/BondEq/CPLC.cpp
+++ b/SourceCode/Bond/BondEq/CPLC.cpp
@@ -269,6 +269,12 @@
 	return m_pChannel->writeWord(softComponent, addr, value, funOnWrite);
 }
 
+int CPLC::writeDWord(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+	int value, ONWRITE funOnWrite)
+{
+	return m_pChannel->writeDWord(softComponent, addr, value, funOnWrite);
+}
+
 int CPLC::writeData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
 	const char* pszData, unsigned int length, ONWRITE funOnWrite)
 {
diff --git a/SourceCode/Bond/BondEq/CPLC.h b/SourceCode/Bond/BondEq/CPLC.h
index 89fded1..f65d324 100644
--- a/SourceCode/Bond/BondEq/CPLC.h
+++ b/SourceCode/Bond/BondEq/CPLC.h
@@ -58,6 +58,7 @@
 	int readWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, ONREAD funOnRead);
 	int readData(MC::SOFT_COMPONENT softComponent, unsigned int addr, unsigned int nReadLen, ONREADDATA funOnReadData);
 	int writeWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, int value, ONWRITE funOnWrite);
+	int writeDWord(MC::SOFT_COMPONENT softComponent, unsigned int addr, int value, ONWRITE funOnWrite);
 	int writeBit(MC::SOFT_COMPONENT softComponent, unsigned int addr, BOOL bValue, ONWRITE funOnWrite);
 	int writeData(MC::SOFT_COMPONENT softComponent, unsigned int addr, const char* pszData, unsigned int length, ONWRITE funOnWrite);
 
diff --git a/SourceCode/Bond/BondEq/FileManager/IOManager.cpp b/SourceCode/Bond/BondEq/FileManager/IOManager.cpp
index b02088d..1884bda 100644
--- a/SourceCode/Bond/BondEq/FileManager/IOManager.cpp
+++ b/SourceCode/Bond/BondEq/FileManager/IOManager.cpp
@@ -15,7 +15,9 @@
 	m_machines[machineName] = data;
 }
 
+
 void IOManager::addDefaultMachineData(const std::string& machineName) {
+	/*
 	if (machineName == "Cavity") {
 		std::vector<IOData> defaultData = {
 			{"X1000", "Unit1_急停 EMO", "Y1010", "Unit1_四色灯-红"},
@@ -324,6 +326,7 @@
 		};
 		m_machines[machineName] = defaultData;
 	}
+	*/
 }
 
 void IOManager::saveToFile(const std::string& machineName) {
@@ -356,6 +359,10 @@
 		IOData entry;
 		size_t pos = 0;
 		pos = line.find(",");
+
+		entry.bInputStates = FALSE;
+		entry.bOutputStates = FALSE;
+
 		entry.inputAddress = line.substr(0, pos);
 		line.erase(0, pos + 1);
 
diff --git a/SourceCode/Bond/BondEq/FileManager/IOManager.h b/SourceCode/Bond/BondEq/FileManager/IOManager.h
index 9d81cd3..8751052 100644
--- a/SourceCode/Bond/BondEq/FileManager/IOManager.h
+++ b/SourceCode/Bond/BondEq/FileManager/IOManager.h
@@ -6,8 +6,10 @@
 #include <map>
 
 struct IOData {
+	BOOL bInputStates;
     std::string inputAddress;
     std::string inputDescription;
+    BOOL bOutputStates;
     std::string outputAddress;
     std::string outputDescription;
 };
diff --git a/SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp b/SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp
index 406156a..5265326 100644
--- a/SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp
+++ b/SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp
@@ -111,7 +111,7 @@
         axisInfo.id = axisId;
 		axisInfo.number = "M100-M" + std::to_string(axisId);
         axisInfo.description = "Default_Axis" + std::to_string(axisId);
-        axisInfo.startAddress = "D" + std::to_string(5000 + axisId * 10);
+        axisInfo.startAddress = "ZR" + std::to_string(10000 + (axisId - 1) * 300);
         axisInfo.jogDistance = 0.5;
         axisInfo.manualSpeed = 10.0;
         axisInfo.autoSpeed = 15.0;
diff --git a/SourceCode/Bond/BondEq/ToolUnits.cpp b/SourceCode/Bond/BondEq/ToolUnits.cpp
index 944503a..69be431 100644
--- a/SourceCode/Bond/BondEq/ToolUnits.cpp
+++ b/SourceCode/Bond/BondEq/ToolUnits.cpp
@@ -160,6 +160,41 @@
 	return (pBuffer[0] & 0xff) | (pBuffer[1] & 0xff) << 8;
 }
 
+BOOL CToolUnits::getBit(const char c, int index)
+{
+	switch (index)
+	{
+	case 0:
+		return c & 0x01;
+		break;
+	case 1:
+		return c & 0x02;
+		break;
+	case 2:
+		return c & 0x04;
+		break;
+	case 3:
+		return c & 0x08;
+		break;
+	case 4:
+		return c & 0x10;
+		break;
+	case 5:
+		return c & 0x20;
+		break;
+	case 6:
+		return c & 0x40;
+		break;
+	case 7:
+		return c & 0x80;
+		break;
+	default:
+		break;
+	}
+
+	return FALSE;
+}
+
 void CToolUnits::setDlgItemDouble(CWnd* pWnd, int nCtrlId, double value)
 {
 	CString strText;
diff --git a/SourceCode/Bond/BondEq/ToolUnits.h b/SourceCode/Bond/BondEq/ToolUnits.h
index 167cf0e..ad88f75 100644
--- a/SourceCode/Bond/BondEq/ToolUnits.h
+++ b/SourceCode/Bond/BondEq/ToolUnits.h
@@ -22,6 +22,7 @@
 	static bool isDirectory(const std::string& path);
 	static double toInt32(const char* pBuffer);
 	static double toInt16(const char* pBuffer);
+	static BOOL getBit(const char c, int index);
 	static void setDlgItemDouble(CWnd* pWnd, int nCtrlId, double value);
 };
 
diff --git a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
index dcdc219..77bc579 100644
--- a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
+++ b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
@@ -421,24 +421,87 @@
 	}
 }
 
+bool CAxisSettingsDlg::ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr)
+{
+	if (address.GetLength() < 2) {
+		return false;
+	}
+
+	// 鎻愬彇缁勪欢绫诲瀷锛堢涓�涓瓧绗︼級
+	TCHAR componentChar = address[0];
+	if (address.Left(2) == _T("ZR")) {
+		component = MC::SOFT_COMPONENT::ZR;
+		// 鎻愬彇鏁板瓧閮ㄥ垎锛堝幓闄R鍓嶇紑锛�
+		CString numericAddress = address.Mid(2);
+		addr = _ttoi(numericAddress);
+		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;
+}
+
 void CAxisSettingsDlg::writeAxisDataToPLC(int nAxisId)
 {
 	// 浠� RecipeManager 鑾峰彇杞存暟鎹�
 	RecipeManager& recipeManager = RecipeManager::getInstance();
 	auto axisData = recipeManager.getAxis(nAxisId);
 
-	// 鍘婚櫎闈炴暟瀛楀瓧绗﹀苟杞崲璧峰鍦板潃
-	std::string cleanAddress = axisData.startAddress;
-	cleanAddress.erase(std::remove_if(cleanAddress.begin(), cleanAddress.end(),
-		[](char c) { return !std::isdigit(c); }), cleanAddress.end());
-	if (cleanAddress.empty()) {
+	int startAddress;
+	MC::SOFT_COMPONENT component;
+	if (!ParsePLCAddress(CString(axisData.startAddress.c_str()), component, startAddress)) {
 		AfxMessageBox(_T("鏃犳晥鐨勮捣濮嬪湴鍧�锛�"));
-		return;
 	}
-	int startAddress = std::stoi(cleanAddress);
 
 	// 鍐欏叆鎵嬪姩閫熷害
-	m_pPLC->writeWord(MC::SOFT_COMPONENT::D, 5120, (int)axisData.manualSpeed, [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
+	m_pPLC->writeDWord(component, startAddress + 82, (int)axisData.manualSpeed * 1000, [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
 		if (flag == 0) {
 			TRACE("\n鍐欏叆鎴愬姛: 鎵嬪姩閫熷害, 鍦板潃: %d, 鍊�: %lu\n", addr, value);
 		}
@@ -448,7 +511,7 @@
 	});
 
 	// 鍐欏叆鑷姩閫熷害
-	m_pPLC->writeWord(MC::SOFT_COMPONENT::D, startAddress + 2, (int)axisData.autoSpeed, [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
+	m_pPLC->writeDWord(component, startAddress + 84, (int)(axisData.autoSpeed * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
 		if (flag == 0) {
 			TRACE("\n鍐欏叆鎴愬姛: 鑷姩閫熷害, 鍦板潃: %d, 鍊�: %lu\n", addr, value);
 		}
@@ -458,7 +521,7 @@
 	});
 
 	// 鍐欏叆鍔犻�熸椂闂�, 杞崲涓烘绉�
-	m_pPLC->writeWord(MC::SOFT_COMPONENT::D, startAddress + 4, (int)(axisData.accelerationTime * 1000), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
+	m_pPLC->writeDWord(component, startAddress + 62, (int)(axisData.accelerationTime * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
 		if (flag == 0) {
 			TRACE("\n鍐欏叆鎴愬姛: 鍔犻�熸椂闂�, 鍦板潃: %d, 鍊�: %lu\n", addr, value);
 		}
@@ -468,7 +531,7 @@
 	});
 
 	// 鍐欏叆鍑忛�熸椂闂�, 杞崲涓烘绉�
-	m_pPLC->writeWord(MC::SOFT_COMPONENT::D, startAddress + 6, (int)(axisData.decelerationTime * 1000), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
+	m_pPLC->writeDWord(component, startAddress + 64, (int)(axisData.decelerationTime * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
 		if (flag == 0) {
 			TRACE("\n鍐欏叆鎴愬姛: 鍑忛�熸椂闂�, 鍦板潃: %d, 鍊�: %lu\n", addr, value);
 		}
@@ -478,7 +541,7 @@
 	});
 
 	// 鍐欏叆寰姩閲�
-	m_pPLC->writeWord(MC::SOFT_COMPONENT::D, startAddress + 8, (int)axisData.jogDistance, [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
+	m_pPLC->writeWord(component, startAddress + 81, (int)(axisData.jogDistance * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
 		if (flag == 0) {
 			TRACE("\n鍐欏叆鎴愬姛: 寰姩閲�, 鍦板潃: %d, 鍊�: %lu\n", addr, value);
 		}
@@ -488,12 +551,13 @@
 	});
 
 	// 鍐欏叆瀹氫綅鐐规暟鎹�
-	int positionStartAddress = startAddress + 10;
+	/*
+	int positionStartAddress = startAddress + 100;
 	for (size_t i = 0; i < axisData.positions.size(); ++i) {
 		const auto& position = axisData.positions[i];
-		int positionAddress = positionStartAddress + (i * 2);
+		unsigned int positionAddress = positionStartAddress + (i * 4);
 
-		m_pPLC->writeWord(MC::SOFT_COMPONENT::D, positionAddress, (int)position.second, [i](IMcChannel* pChannel, int addr, DWORD value, int flag) {
+		m_pPLC->writeWord(component, positionAddress, (int)position.second, [i](IMcChannel* pChannel, int addr, DWORD value, int flag) {
 			if (flag == 0) {
 				TRACE("\n鍐欏叆鎴愬姛: 瀹氫綅鐐� %d, 鍦板潃: %d, 鍊�: %lu\n", i + 1, addr, value);
 			}
@@ -502,6 +566,7 @@
 			}
 		});
 	}
+	*/
 }
 
 void CAxisSettingsDlg::handleAxisOperation(AxisOperationType eOpType, bool bPressed)
@@ -516,18 +581,14 @@
 	RecipeManager& recipeManager = RecipeManager::getInstance();
 	auto axisData = recipeManager.getAxis(nAxisId);
 
-	std::string strCleanAddress = axisData.startAddress;
-	strCleanAddress.erase(std::remove_if(strCleanAddress.begin(), strCleanAddress.end(),
-		[](unsigned char c) { return !std::isdigit(c); }), strCleanAddress.end());
-	if (strCleanAddress.empty()) {
+	int startAddress;
+	MC::SOFT_COMPONENT component;
+	if (!ParsePLCAddress(CString(axisData.startAddress.c_str()), component, startAddress)) {
 		AfxMessageBox(_T("鏃犳晥鐨勮捣濮嬪湴鍧�锛�"));
-		return;
 	}
 
-	int nStartAddress = std::stoi(strCleanAddress);
-
 	// 鏍规嵁鎿嶄綔绫诲瀷璁$畻鐩爣鍦板潃
-	int nTargetAddress = nStartAddress;
+	int nTargetAddress = startAddress + 10;
 	switch (eOpType) {
 	case AxisOperationType::OPR:
 		nTargetAddress += 10; // OPR 淇″彿鍦板潃
@@ -562,7 +623,7 @@
 	}
 
 	// 鍚� PLC 鍐欏叆淇″彿
-	m_pPLC->writeBit(MC::SOFT_COMPONENT::D, nTargetAddress, bPressed, [eOpType, nTargetAddress, bPressed](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
+	m_pPLC->writeBit(component, nTargetAddress, bPressed, [eOpType, nTargetAddress, bPressed](IMcChannel* pChannel, int nAddr, DWORD nValue, int nFlag) {
 		if (nFlag == 0) {
 			TRACE("鎿嶄綔鎴愬姛锛氱被鍨�=%d锛屽湴鍧�=%d锛屽��=%d\n", static_cast<int>(eOpType), nAddr, bPressed);
 		}
@@ -570,6 +631,45 @@
 			TRACE("鎿嶄綔澶辫触锛氱被鍨�=%d锛屽湴鍧�=%d锛岄敊璇爜=%d\n", static_cast<int>(eOpType), nAddr, nFlag);
 		}
 	});
+}
+
+void CAxisSettingsDlg::readPLCDataToUI(int nAxisId)
+{	
+	CBLLabel* pLabels[] = { &m_staticFLS, &m_staticDOG, &m_staticRLS, &m_staticReady, &m_staticBusy, &m_staticErr };
+
+	// 浠� RecipeManager 鑾峰彇杞存暟鎹�
+	RecipeManager& recipeManager = RecipeManager::getInstance();
+	auto axisData = recipeManager.getAxis(nAxisId);
+
+	MC::SOFT_COMPONENT component;
+	int startAddress, endAddress, readSize;
+	if (!ParsePLCAddress(CString(axisData.startAddress.c_str()), component, startAddress)) {
+		AfxMessageBox(_T("鏃犳晥鐨勮捣濮嬪湴鍧�锛�"));
+	}
+
+	// 浠� OPR 淇″彿鍦板潃寮�濮嬭鍙�
+	startAddress += 10;
+	endAddress = startAddress + 24;
+	readSize = endAddress - startAddress + 1;
+
+	// 鍥炶皟澶勭悊杈撳叆鏁版嵁
+	auto funOnReadData = [this, startAddress, &pLabels](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) {
+		if (flag == 0) {
+			int nOffset = 0;
+			for (auto pLabel : pLabels) {
+				int value = CToolUnits::toInt16(&pData[(startAddress + nOffset) * 2]);
+				if (value == 0) {
+					SetStatusColor(*pLabel, FALSE);
+				} else {
+					SetStatusColor(*pLabel, TRUE);
+				}
+
+				nOffset++;
+			}
+		}
+	};
+
+	m_pPLC->readData(component, startAddress, readSize, funOnReadData);
 }
 
 
@@ -925,6 +1025,11 @@
 	if (TIMER_READ_PLC_DATA == nIDEvent) {
 		ASSERT(m_pPLC);
 
+		int nAxisId = getCurrentSelectedAxisID();
+		if (nAxisId == -1) {
+			return;
+		}
+
 		int addr1, addr2, readSize;
 		addr1 = 5120;
 		addr2 = 5425;
@@ -947,7 +1052,9 @@
 				SetDlgItemInt(IDC_EDIT_AXIS_CURR_ALARM_NUMBER, nAlarmCode);
 			}
 		};
-		m_pPLC->readData(MC::SOFT_COMPONENT::D, addr1, readSize, funOnReadData);
+		//m_pPLC->readData(MC::SOFT_COMPONENT::D, addr1, readSize, funOnReadData);
+
+		//readPLCDataToUI(nAxisId);
 	}	
 	else if (nIDEvent == TIMER_JOG_ADD && m_bJogAddPressed) {
 		TRACE("鎸佺画鍙戦�� JOG+\n");
diff --git a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.h b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.h
index bd1f4d6..d94c18b 100644
--- a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.h
+++ b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.h
@@ -51,9 +51,10 @@
 	void updateAxisSelection(int offset);
 	void updateDataFromUI(int nAxisId);
 	void switchToPage(int targetPage);
+	bool ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr);
 	void writeAxisDataToPLC(int nAxisId);
 	void handleAxisOperation(AxisOperationType eOpType, bool bPressed);
-
+	void readPLCDataToUI(int nAxisId);
 
 private:
 	CPLC* m_pPLC;
diff --git a/SourceCode/Bond/BondEq/View/IOMonitoringDlg.cpp b/SourceCode/Bond/BondEq/View/IOMonitoringDlg.cpp
index dfc430a..ad1e83d 100644
--- a/SourceCode/Bond/BondEq/View/IOMonitoringDlg.cpp
+++ b/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 瀵硅瘽妗�
 
@@ -170,65 +176,40 @@
 	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("鍦板潃瑙f瀽鎴愬姛: %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();
@@ -236,7 +217,7 @@
 	if (hasBorder) {
 		style |= WS_BORDER; // 娣诲姞杈规
 	}
-	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);
@@ -255,6 +236,33 @@
 
 	// 瀛樺偍鎺т欢鎸囬拡
 	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()
@@ -326,109 +334,200 @@
 
 	// 鎻愬彇缁勪欢绫诲瀷锛堢涓�涓瓧绗︼級
 	TCHAR componentChar = address[0];
+	if (address.Left(2) == _T("ZR")) {
+		component = MC::SOFT_COMPONENT::ZR;
+		// 鎻愬彇鏁板瓧閮ㄥ垎锛堝幓闄R鍓嶇紑锛�
+		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;
-
-		// 瑙f瀽璧峰鍜岀粨鏉熷湴鍧�
-		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);  // 鍗佽繘鍒舵牸寮�
+	}
 
-		// 瑙f瀽璧峰鍜岀粨鏉熷湴鍧�
-		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 startAddr, endAddr;
+	ParsePLCAddress(CString(startData.inputAddress.c_str()), startSoftComponent, startAddr);
+	ParsePLCAddress(CString(endData.inputAddress.c_str()), endSoftComponent, endAddr);
+	ASSERT(startSoftComponent == endSoftComponent);
+
+	// 璇诲彇杈撳叆鏁版嵁
+	ReadPLCData(startSoftComponent, startAddr, endAddr, [this, startAddr](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) {
+		for (auto& data : m_displayData) {
+			int nAddress;
+			MC::SOFT_COMPONENT enComponent;
+			if (ParsePLCAddress(CString(data.inputAddress.c_str()), enComponent, nAddress)) {
+				int nOffset = nAddress - startAddr;
+				if (nOffset >= 0 && nOffset < nDataSize) {
+					int byteIndex = nOffset / 8;
+					int bitIndex = nOffset % 8;
+					data.bInputStates = CToolUnits::getBit(pData[byteIndex], bitIndex);
 				}
-			};
+			}
+		}
+	});
 
-			// 璇诲彇杈撳嚭鏁版嵁
-			m_pPLC->readData(component, startAddress, outputSize, funOnReadOutput);
+	// 璇诲彇杈撳嚭鏁版嵁
+	int startAddr2, endAddr2;
+	ParsePLCAddress(CString(startData.outputAddress.c_str()), startSoftComponent, startAddr2);
+	ParsePLCAddress(CString(endData.outputAddress.c_str()), endSoftComponent, endAddr2);
+	ASSERT(startSoftComponent == endSoftComponent);
+	ReadPLCData(startSoftComponent, startAddr2, endAddr2, [this, startAddr2](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) {
+		for (auto& data : m_displayData) {
+			int nAddress;
+			MC::SOFT_COMPONENT enComponent;
+			if (ParsePLCAddress(CString(data.outputAddress.c_str()), enComponent, nAddress)) {
+				int nOffset = nAddress - startAddr2;
+				if (nOffset >= 0 && nOffset < 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];
+			// 璁剧疆鍐呭鍜岃儗鏅鑹�
+			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_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));
 		}
 	}
 }
@@ -436,6 +535,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()
@@ -502,10 +602,9 @@
 
 	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
@@ -537,9 +636,6 @@
 	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()
@@ -552,9 +648,30 @@
 	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("鍦板潃瑙f瀽鎴愬姛: %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("鍦板潃瑙f瀽鎴愬姛2: %d\n", n);
+	}
+
+	return 0;
 }
 
 void CIOMonitoringDlg::OnTimer(UINT_PTR nIDEvent)
@@ -562,9 +679,13 @@
 	// TODO: 鍦ㄦ娣诲姞娑堟伅澶勭悊绋嬪簭浠g爜鍜�/鎴栬皟鐢ㄩ粯璁ゅ��
 	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);
 }
 
@@ -572,5 +693,6 @@
 {
 	// TODO: 鍦ㄦ娣诲姞娑堟伅澶勭悊绋嬪簭浠g爜鍜�/鎴栬皟鐢ㄩ粯璁ゅ��
 	KillTimer(TIMER_READ_PLC_DATA);
+	KillTimer(TIMER_READ_UPDATE);
 	CDialogEx::OnClose();
 }
diff --git a/SourceCode/Bond/BondEq/View/IOMonitoringDlg.h b/SourceCode/Bond/BondEq/View/IOMonitoringDlg.h
index 6f173fe..6c75c0d 100644
--- a/SourceCode/Bond/BondEq/View/IOMonitoringDlg.h
+++ b/SourceCode/Bond/BondEq/View/IOMonitoringDlg.h
@@ -28,13 +28,18 @@
 	void AdjustControls(float dScaleX, float dScaleY);				// 璋冩暣鎺т欢澶у皬
 	void AdjustControlFont(CWnd* pWnd, int nWidth, int nHeight);	// 璋冩暣鎺т欢瀛椾綋澶у皬
 
-	void UpdatePageInfo();			// 鏇存柊鍒嗛〉淇℃伅
-	void CreateDynamicControls();	// 鍔ㄦ�佸垱寤烘帶浠�
-	void CreateStaticControl(int x, int y, int width, int height, const CString& text, bool hasBorder = false, TextAlign alignment = AlignLeft, std::function<void()> clickCallback = nullptr); // 鍒涘缓闈欐�佹帶浠�
-	void DisplayCurrentPage();		// 鏄剧ず褰撳墠椤垫暟鎹�
-	void ClearDynamicControls();	// 娓呴櫎鍔ㄦ�佸垱寤虹殑鎺т欢
+	void UpdatePageInfo();			 // 鏇存柊鍒嗛〉淇℃伅
+	void CreateDynamicControls();	 // 鍔ㄦ�佸垱寤烘帶浠�
+	CWnd* CreateStaticControl(UINT id, int x, int y, int width, int height, const CString& text, bool hasBorder = false, TextAlign alignment = AlignLeft, std::function<void()> clickCallback = nullptr); // 鍒涘缓闈欐�佹帶浠�
+	CWnd* GetStaticControl(UINT id); // 鑾峰彇闈欐�佹帶浠�
+	CString& GetStaticControlAddrText(UINT id, CString& strAddr); // 鑾峰彇闈欐�佹帶浠跺湴鍧�鏂囨湰
+	void DisplayCurrentPage();		 // 鏄剧ず褰撳墠椤垫暟鎹�
+	void ClearDynamicControls();	 // 娓呴櫎鍔ㄦ�佸垱寤虹殑鎺т欢
 	bool ParsePLCAddress(const CString& address, MC::SOFT_COMPONENT& component, int& addr); // 瑙f瀽 PLC 鍦板潃
-	void UpdatePLCStates();			// 瀹氭椂鍣ㄦ洿鏂扮姸鎬佺殑鏂规硶
+	bool GeneratePLCAddress(MC::SOFT_COMPONENT component, int addr, CString& address, bool bHexFormat = false); // 鐢熸垚 PLC 鍦板潃
+	void ReadPLCData(MC::SOFT_COMPONENT softComponent, int startAddr, int endAddr, std::function<void(IMcChannel*, int, char*, unsigned int, int)> callback); // 璇诲彇 PLC 鏁版嵁
+	void ReadPLCStates();			 // 瀹氭椂鍣ㄨPLC
+	void UpdatePLCStatesToUI();		 // 瀹氭椂鍣ㄦ洿鏂扮姸鎬佺殑鏂规硶
 
 private:
 	CPLC* m_pPLC;
@@ -64,6 +69,7 @@
 	afx_msg void OnSize(UINT nType, int cx, int cy);
 	afx_msg void OnBnClickedButtonPrevPage();
 	afx_msg void OnBnClickedButtonNextPage();
+	afx_msg LRESULT OnIoClicked(WPARAM wParam, LPARAM lParam);
 	afx_msg void OnTimer(UINT_PTR nIDEvent);
 	afx_msg void OnClose();
 };

--
Gitblit v1.9.3