From 43419b86d6a4a2d879454938fb7db7cc84d8c011 Mon Sep 17 00:00:00 2001
From: LAPTOP-T815PCOQ\25526 <mr.liuyang@126.com>
Date: 星期三, 11 十二月 2024 14:51:38 +0800
Subject: [PATCH] 1. 添加自定义限制编辑框 2. 在axis设定界面实现输入限制功能

---
 SourceCode/Bond/BondEq/Resource.h               |    0 
 SourceCode/Bond/BondEq/View/AxisSettingsDlg.h   |   20 +++
 SourceCode/Bond/BondEq/BondEq.rc                |    0 
 SourceCode/Bond/BondEq/RegexEdit.cpp            |  115 +++++++++++++++++++++++
 SourceCode/Bond/BondEq/RegexEdit.h              |   68 +++++++++++++
 SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp |   82 ++++++++++++---
 SourceCode/Bond/BondEq/BondEq.vcxproj           |    2 
 7 files changed, 267 insertions(+), 20 deletions(-)

diff --git a/SourceCode/Bond/BondEq/BondEq.rc b/SourceCode/Bond/BondEq/BondEq.rc
index fd6b3aa..673b991 100644
--- a/SourceCode/Bond/BondEq/BondEq.rc
+++ b/SourceCode/Bond/BondEq/BondEq.rc
Binary files differ
diff --git a/SourceCode/Bond/BondEq/BondEq.vcxproj b/SourceCode/Bond/BondEq/BondEq.vcxproj
index b18164e..48478d3 100644
--- a/SourceCode/Bond/BondEq/BondEq.vcxproj
+++ b/SourceCode/Bond/BondEq/BondEq.vcxproj
@@ -244,6 +244,7 @@
     <ClInclude Include="Model.h" />
     <ClInclude Include="CPageAlarm.h" />
     <ClInclude Include="Recipe.h" />
+    <ClInclude Include="RegexEdit.h" />
     <ClInclude Include="Resource.h" />
     <ClInclude Include="SetPage1.h" />
     <ClInclude Include="SetPage2.h" />
@@ -317,6 +318,7 @@
     <ClCompile Include="Model.cpp" />
     <ClCompile Include="CPageAlarm.cpp" />
     <ClCompile Include="Recipe.cpp" />
+    <ClCompile Include="RegexEdit.cpp" />
     <ClCompile Include="SetPage1.cpp" />
     <ClCompile Include="SetPage2.cpp" />
     <ClCompile Include="SettingsDlg.cpp" />
diff --git a/SourceCode/Bond/BondEq/RegexEdit.cpp b/SourceCode/Bond/BondEq/RegexEdit.cpp
new file mode 100644
index 0000000..f3943e1
--- /dev/null
+++ b/SourceCode/Bond/BondEq/RegexEdit.cpp
@@ -0,0 +1,115 @@
+#include "stdafx.h"
+#include "RegexEdit.h"
+#include <stdexcept>
+
+IMPLEMENT_DYNAMIC(CRegexEdit, CEdit)
+
+CRegexEdit::CRegexEdit()
+{
+    m_enRegexType = RegexType::Alphanumeric;
+	m_dMinValue = LDBL_MIN;
+	m_dMaxValue = LDBL_MAX;
+}
+
+CRegexEdit::~CRegexEdit()
+{
+}
+
+void CRegexEdit::SetRegexType(RegexType enType)
+{
+    m_enRegexType = enType;
+}
+
+void CRegexEdit::SetCustomRegex(const std::string& strCustomRegex)
+{
+    m_strCustomRegex = strCustomRegex;
+}
+
+void CRegexEdit::SetValueRange(long double dMinValue, long double dMaxValue)
+{
+    m_dMinValue = dMinValue;
+    m_dMaxValue = dMaxValue;
+}
+
+void CRegexEdit::SetCustomComparator(std::function<bool(const std::string&)> comparator)
+{
+	m_customComparator = comparator;
+}
+
+void CRegexEdit::SetInvalidInputCallback(std::function<void()> callback)
+{
+    m_invalidInputCallback = callback;
+}
+
+std::regex CRegexEdit::GetCurrentRegex() const
+{
+    switch (m_enRegexType)
+    {
+    case RegexType::Alphanumeric:
+        return std::regex("^[a-zA-Z0-9]*$");        // 字母和数字
+    case RegexType::Letters:
+        return std::regex("^[a-zA-Z]*$");           // 只允许字母
+    case RegexType::Digits:
+        return std::regex("^\\d*$");                // 只允许数字
+    case RegexType::Decimal:
+        return std::regex("^[-+]?\\d+(\\.\\d+)?$"); // 允许小数和整数
+    case RegexType::Custom:
+        return std::regex(m_strCustomRegex);        // 自定义正则
+    default:
+        return std::regex(".*");                    // 默认允许输入任何内容
+    }
+}
+
+bool CRegexEdit::IsValueInRange(const std::string& strText)
+{
+    try {
+        if (m_enRegexType == RegexType::Digits || m_enRegexType == RegexType::Decimal) {
+            if (strText.find('.') == std::string::npos) {
+                int nValue = std::stoi(strText);
+                return nValue >= static_cast<int>(m_dMinValue) && nValue <= static_cast<int>(m_dMaxValue);
+            }
+            else {
+                double dValue = std::stod(strText);
+                return dValue >= m_dMinValue && dValue <= m_dMaxValue;
+            }
+        }
+    }
+    catch (const std::invalid_argument&) {
+        return false;
+    }
+
+    return true;
+}
+
+BEGIN_MESSAGE_MAP(CRegexEdit, CEdit)
+    ON_WM_CHAR()
+END_MESSAGE_MAP()
+
+void CRegexEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+    // 处理删除键和退格键
+    if (nChar == VK_BACK || nChar == VK_DELETE) {
+        CEdit::OnChar(nChar, nRepCnt, nFlags);
+        return;
+    }
+
+    CString strCurrent;
+    GetWindowText(strCurrent);
+
+    // 获取光标当前位置
+    int nStartChar, nEndChar;
+    GetSel(nStartChar, nEndChar); // 获取当前选区的起始和结束位置
+
+    std::string strText(CT2A(strCurrent.GetBuffer()));
+    strText.insert(strText.begin() + nStartChar, (char)nChar);
+
+    bool bValid = m_customComparator ? m_customComparator(strText) : IsValueInRange(strText);
+    if (std::regex_match(strText, GetCurrentRegex()) && bValid) {
+        CEdit::OnChar(nChar, nRepCnt, nFlags);
+    }
+    else {
+        if (m_invalidInputCallback) {
+            m_invalidInputCallback();
+        }
+    }
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/RegexEdit.h b/SourceCode/Bond/BondEq/RegexEdit.h
new file mode 100644
index 0000000..07df2cd
--- /dev/null
+++ b/SourceCode/Bond/BondEq/RegexEdit.h
@@ -0,0 +1,68 @@
+#if !defined(AFX_REGEXEDIT_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_)
+#define AFX_REGEXEDIT_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include <afxwin.h>
+#include <regex>
+#include <functional>
+#include <limits>
+
+// 枚举类型:正则表达式类型
+enum class RegexType
+{
+    Alphanumeric,   // 允许字母和数字
+    Letters,        // 只允许字母
+    Digits,         // 只允许数字
+    Decimal,        // 允许小数和整数
+    Custom          // 自定义正则
+};
+
+class CRegexEdit : public CEdit
+{
+    DECLARE_DYNAMIC(CRegexEdit)
+
+public:
+    // 构造与析构
+    CRegexEdit();
+    virtual ~CRegexEdit();
+
+    // 设置正则类型
+    void SetRegexType(RegexType enType);
+
+    // 设置自定义正则表达式
+    void SetCustomRegex(const std::string& strCustomRegex);
+
+    // 设置数值范围(整数或浮点)
+    void SetValueRange(long double dMinValue, long double dMaxValue);
+
+    // 设置自定义比较函数
+    void SetCustomComparator(std::function<bool(const std::string&)> comparator);
+
+	// 设置输入不合法函数
+    void SetInvalidInputCallback(std::function<void()> callback);
+
+protected:
+    // 根据枚举值返回对应的正则表达式
+    std::regex GetCurrentRegex() const;
+
+    // 校验输入是否在指定范围内
+    bool IsValueInRange(const std::string& strText);
+
+protected:
+    RegexType m_enRegexType;        // 当前选中的正则类型
+    std::string m_strCustomRegex;   // 自定义正则表达式
+	long double m_dMinValue;        // 最小值
+	long double m_dMaxValue;		// 最大值
+
+	std::function<bool(const std::string&)> m_customComparator; // 自定义比较函数
+    std::function<void()> m_invalidInputCallback;               // 不合法输入的回调函数
+
+protected:
+    void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
+    DECLARE_MESSAGE_MAP()
+};
+
+#endif // !defined(AFX_REGEXEDIT_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_)
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/Resource.h b/SourceCode/Bond/BondEq/Resource.h
index 19fb630..24879de 100644
--- a/SourceCode/Bond/BondEq/Resource.h
+++ b/SourceCode/Bond/BondEq/Resource.h
Binary files differ
diff --git a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
index 28d37c1..b5aae05 100644
--- a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
+++ b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
@@ -44,8 +44,13 @@
 	m_bReady = FALSE;
 	m_bBusy = FALSE;
 	m_bErr = FALSE;
+
 	for (int i = 0; i < BTN_MAX; i++) {
 		m_pBlBtns[i] = new CBlButton();
+	}
+
+	for (int i = 0; i < EDIT_MAX; i++) {
+		m_pRegexEdit[i] = new CRegexEdit();
 	}
 
 	for (int i = 0; i < LABEL_MAX; i++) {
@@ -68,6 +73,10 @@
 
 	for (int i = 0; i < BTN_MAX; i++) {
 		delete m_pBlBtns[i];
+	}
+
+	for (int i = 0; i < EDIT_MAX; i++) {
+		delete m_pRegexEdit[i];
 	}
 
 	for (int i = 0; i < LABEL_MAX; i++) {
@@ -93,11 +102,6 @@
 	DDX_Control(pDX, IDC_STATIC_AXIS_NUMBER, m_staticAxisNO);
 	DDX_Control(pDX, IDC_STATIC_AXIS_DESCRIP, m_staticAxisDescription);
 	DDX_Control(pDX, IDC_STATIC_START_ADDRESS, m_staticStartAddress);
-	DDX_Control(pDX, IDC_EDIT_AXIS_MODITFY_POS, m_editManualSpeed);
-	DDX_Control(pDX, IDC_EDIT_AXIS_MODITFY_AUTO_SPEED, m_editAutoSpeed);
-	DDX_Control(pDX, IDC_EDIT_AXIS_MODITFY_ACCE_TIME, m_editAccelerationTime);
-	DDX_Control(pDX, IDC_EDIT_AXIS_MODITFY_DECE_TIME, m_editDecelerationTime);
-	DDX_Control(pDX, IDC_EDIT_AXIS_MODITFY_MICROMENTUM, m_editJogDistance);
 }
 
 UINT CAxisSettingsDlg::FindIDByName(const CString& strControlID)
@@ -238,6 +242,24 @@
 	SetLabelColorBasedOnState(*m_pBlLabels[LABEL_ERR], m_bErr, COLOR_RED, COLOR_GREEN_OFF);
 }
 
+void CAxisSettingsDlg::UpdateRegexEdit(CRegexEdit* pRegexEdit, const ValueRange& range, const CString& title)
+{
+	auto formatDouble = [](double value) -> CString {
+		CString str;
+		str.Format(_T("%.3f"), value);
+		return str;
+	};
+
+	pRegexEdit->SetWindowText(formatDouble(range.currentValue));
+	pRegexEdit->SetRegexType(RegexType::Decimal);
+	pRegexEdit->SetValueRange(range.minValue, range.maxValue);
+	pRegexEdit->SetInvalidInputCallback([title, range]() {
+		CString strError;
+		strError.Format(_T("%s鐨勫�煎繀椤诲湪 %.3f 鍜� %.3f 涔嬮棿锛�"), title, range.minValue, range.maxValue);
+		AfxMessageBox(strError);
+	});
+}
+
 void CAxisSettingsDlg::updatePageButtonStates()
 {
 	for (int i = 0; i < AXIS_PAGE_SIZE; ++i) {
@@ -313,14 +335,15 @@
 	};
 
 	// 鏇存柊鎺т欢鏄剧ず
-	m_staticAxisNO.SetWindowText(CString(axisDetails.number.c_str()));								// 杞寸紪鍙�
-	m_staticAxisDescription.SetWindowText(CString(axisDetails.description.c_str()));				// 杞存弿杩�
-	m_staticStartAddress.SetWindowText(CString(axisDetails.startAddress.c_str()));					// 璧峰鍦板潃
-	m_editJogDistance.SetWindowText(formatDouble(axisDetails.jogDistance.currentValue));			// 寰姩閲�
-	m_editManualSpeed.SetWindowText(formatDouble(axisDetails.manualSpeed.currentValue));			// 鎵嬪姩閫熷害
-	m_editAutoSpeed.SetWindowText(formatDouble(axisDetails.autoSpeed.currentValue));				// 鑷姩閫熷害
-	m_editAccelerationTime.SetWindowText(formatDouble(axisDetails.accelerationTime.currentValue));	// 鍔犻�熸椂闂�
-	m_editDecelerationTime.SetWindowText(formatDouble(axisDetails.decelerationTime.currentValue));	// 鍑忛�熸椂闂�
+	m_staticAxisNO.SetWindowText(CString(axisDetails.number.c_str()));					// 杞寸紪鍙�
+	m_staticAxisDescription.SetWindowText(CString(axisDetails.description.c_str()));	// 杞存弿杩�
+	m_staticStartAddress.SetWindowText(CString(axisDetails.startAddress.c_str()));		// 璧峰鍦板潃
+
+	UpdateRegexEdit(m_pRegexEdit[EDIT_MICROMENTUM], axisDetails.jogDistance, _T("寰姩閲�"));
+	UpdateRegexEdit(m_pRegexEdit[EDIT_MANUAL_SPEED], axisDetails.manualSpeed, _T("鎵嬪姩閫熷害"));
+	UpdateRegexEdit(m_pRegexEdit[EDIT_AUTO_SPEED], axisDetails.autoSpeed, _T("鑷姩閫熷害"));
+	UpdateRegexEdit(m_pRegexEdit[EDIT_ACCE_TIME], axisDetails.accelerationTime, _T("鍔犻�熸椂闂�"));
+	UpdateRegexEdit(m_pRegexEdit[EDIT_DECE_TIME], axisDetails.decelerationTime, _T("鍑忛�熸椂闂�"));
 }
 
 void CAxisSettingsDlg::refreshPositionDetails(int nAxisId, int pageNumber)
@@ -357,6 +380,12 @@
 			if (pPositionCtrl) {
 				pPositionCtrl->SetWindowText(value);
 				pPositionCtrl->EnableWindow(position.isEnable);
+
+				if (position.isEnable) {
+					CString strError;
+					strError.Format(_T("瀹氫綅鐐�%d"), i + 1);
+					UpdateRegexEdit((CRegexEdit*)pPositionCtrl, position.range, strError);
+				}
 			}
 		}
 		else {
@@ -445,19 +474,19 @@
 
 	// 鑾峰彇鐣岄潰涓婄殑淇敼鍙傛暟
 	CString text;
-	m_editManualSpeed.GetWindowText(text);
+	m_pRegexEdit[EDIT_MANUAL_SPEED]->GetWindowText(text);
 	axisData.manualSpeed.currentValue = _ttof(text);
 
-	m_editAutoSpeed.GetWindowText(text);
+	m_pRegexEdit[EDIT_AUTO_SPEED]->GetWindowText(text);
 	axisData.autoSpeed.currentValue = _ttof(text);
 
-	m_editAccelerationTime.GetWindowText(text);
+	m_pRegexEdit[EDIT_ACCE_TIME]->GetWindowText(text);
 	axisData.accelerationTime.currentValue = _ttof(text);
 
-	m_editDecelerationTime.GetWindowText(text);
+	m_pRegexEdit[EDIT_DECE_TIME]->GetWindowText(text);
 	axisData.decelerationTime.currentValue = _ttof(text);
 
-	m_editJogDistance.GetWindowText(text);
+	m_pRegexEdit[EDIT_MICROMENTUM]->GetWindowText(text);
 	axisData.jogDistance.currentValue = _ttof(text);
 
 	// 鏇存柊瀹氫綅鐐规暟鎹�
@@ -866,6 +895,18 @@
 		pLabel->SetDynamicFont(TRUE);
 	}
 	
+	// 鍒濆鍖栫紪杈戞
+	m_pRegexEdit[EDIT_MANUAL_SPEED]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED, this);
+	m_pRegexEdit[EDIT_AUTO_SPEED]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED, this);
+	m_pRegexEdit[EDIT_ACCE_TIME]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME, this);
+	m_pRegexEdit[EDIT_DECE_TIME]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME, this);
+	m_pRegexEdit[EDIT_MICROMENTUM]->SubclassDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM, this);
+	m_pRegexEdit[EDIT_ANCHOR_POINT1]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT1, this);
+	m_pRegexEdit[EDIT_ANCHOR_POINT2]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT2, this);
+	m_pRegexEdit[EDIT_ANCHOR_POINT3]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT3, this);
+	m_pRegexEdit[EDIT_ANCHOR_POINT4]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT4, this);
+	m_pRegexEdit[EDIT_ANCHOR_POINT5]->SubclassDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT5, this);
+
 	// 鎸夐挳鍒濆鍖�
 	m_pBlBtns[BTN_PAGE1]->SubclassDlgItem(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP1, this);
 	m_pBlBtns[BTN_PAGE2]->SubclassDlgItem(IDC_BUTTON_AXIS_ANCHOR_POINT_GROUP2, this);
@@ -980,6 +1021,11 @@
 	CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
 
 	if (pWnd) {
+		if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
+			// 闃绘鍥炶溅閿粯璁ゅ鐞嗭紝闃叉瀵硅瘽妗嗗叧闂�
+			return TRUE;
+		}
+
 		// 鍒ゆ柇榧犳爣鏄惁杩涘叆鎸囧畾鎺т欢鍖哄煙
 		if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP1)->m_hWnd ||
 			pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP2)->m_hWnd ||
diff --git a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.h b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.h
index 1aa0a27..ed1e674 100644
--- a/SourceCode/Bond/BondEq/View/AxisSettingsDlg.h
+++ b/SourceCode/Bond/BondEq/View/AxisSettingsDlg.h
@@ -2,12 +2,13 @@
 #include "afxdialogex.h"
 #include "BlButton.h"
 #include "BLLabel.h"
+#include "RegexEdit.h"
 #include "CPLC.h"
 
 // 姣忛〉瀹氫綅鐐规樉绀轰釜鏁�
 #define AXIS_PAGE_SIZE	5
 
-// LABEL鎺т欢
+// Label鎺т欢
 #define LABEL_MAX		6
 #define LABEL_FLS		0
 #define LABEL_DOG		1
@@ -15,6 +16,19 @@
 #define LABEL_READY		3
 #define LABEL_BUSY		4
 #define LABEL_ERR		5
+
+// RegexEdit鎺т欢
+#define EDIT_MAX			10
+#define EDIT_MANUAL_SPEED	0
+#define EDIT_AUTO_SPEED		1
+#define EDIT_ACCE_TIME		2
+#define EDIT_DECE_TIME		3
+#define EDIT_MICROMENTUM	4
+#define EDIT_ANCHOR_POINT1	5
+#define EDIT_ANCHOR_POINT2	6
+#define EDIT_ANCHOR_POINT3	7
+#define EDIT_ANCHOR_POINT4	8
+#define EDIT_ANCHOR_POINT5	9
 
 // BUTTON鎺т欢
 #define BTN_MAX			15
@@ -76,6 +90,7 @@
 	void SetLabelColor(CBLLabel& label, COLORREF color);
 	void SetLabelColorBasedOnState(CBLLabel& label, BOOL bState, COLORREF colorTrue, COLORREF colorFalse);
 	void UpdateLabels();
+	void UpdateRegexEdit(CRegexEdit* pRegexEdit, const ValueRange& range, const CString& title);
 	void updatePageButtonStates();
 	void HideEditCursor(int nCtrlID);
 	int getCurrentSelectedAxisID();
@@ -105,9 +120,10 @@
 	// 鎺т欢
 	CBlButton* m_pBlBtns[BTN_MAX];
 	CBLLabel* m_pBlLabels[LABEL_MAX];
+	CRegexEdit* m_pRegexEdit[EDIT_MAX];
 	CComboBox m_comboAxisNO;
 	CStatic m_staticAxisNO, m_staticAxisDescription, m_staticStartAddress;
-	CEdit m_editManualSpeed, m_editAutoSpeed, m_editAccelerationTime, m_editDecelerationTime, m_editJogDistance;
+	//CEdit m_editManualSpeed, m_editAutoSpeed, m_editAccelerationTime, m_editDecelerationTime, m_editJogDistance;
 	
 	std::map<int, CRect> m_mapCtrlLayouts;
 	std::map<int, CFont*> m_mapFonts;

--
Gitblit v1.9.3