LAPTOP-SNT8I5JK\Boounion
2025-07-28 bfe14e41fa5b07771d78af4511ba18d706bc23cc
SourceCode/Bond/BoounionPLC/AxisSettingsDlg.cpp
@@ -8,6 +8,7 @@
#include "AxisDetailSettingsDlg.h"
#include "ToolUnits.h"
#include <cctype>
#include <regex>
#define COLOR_GREEN_ON    RGB(0, 255, 0)  // 正常状态绿色
@@ -16,6 +17,7 @@
#define TIMER_INIT               1
#define TIMER_READ_PLC_DATA         2
#define TIMER_HIDE_TIP            3
#define ID_MSG_UPDATA_DATA_TO_UI   WM_USER + 101
@@ -52,26 +54,22 @@
      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++) {
      m_pBlLabels[i] = new CBLLabel();
   }
   
   m_nBtnsFlashState6 = 0;
   m_nBtnsFlashState8 = 0;
   m_crTipBack = RGB(255, 127, 39);
   m_crTipText = RGB(228, 228, 228);
   m_hbrTip = CreateSolidBrush(m_crTipBack);
   m_hTipFont = nullptr;
}
CAxisSettingsDlg::~CAxisSettingsDlg()
{
   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++) {
@@ -82,6 +80,18 @@
      delete m_pAxisManager;
      m_pAxisManager = nullptr;
   }
   ::DeleteObject(m_hbrTip);
   if (m_hTipFont != nullptr) {
      ::DeleteObject(m_hTipFont);
   }
}
BOOL CAxisSettingsDlg::PreAdjustControl(CWnd* pWnd)
{
   int nCtrlID = pWnd->GetDlgCtrlID();
   if (nCtrlID == IDC_LABEL_TIP) return FALSE;
   return TRUE;
}
void CAxisSettingsDlg::DoDataExchange(CDataExchange* pDX)
@@ -162,27 +172,10 @@
   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) {
      m_pBlBtns[i]->SetFrameColor(BTN_PAGE_FRAME_COLOR);
      BOOL bSelect = (i + 1 == m_currentPage);
      m_pBlBtns[i]->SetFaceColor(bSelect ?
         BTN_PAGE_FACE_SELECT_COLOR: BTN_PAGE_FACE_NORMAL_COLOR);
@@ -253,11 +246,11 @@
   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("减速时间"));
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED)->SetWindowText(formatDouble(axisDetails.manualSpeed.currentValue));
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED)->SetWindowText(formatDouble(axisDetails.autoSpeed.currentValue));
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME)->SetWindowText(formatDouble(axisDetails.accelerationTime.currentValue));
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME)->SetWindowText(formatDouble(axisDetails.decelerationTime.currentValue));
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM)->SetWindowText(formatDouble(axisDetails.jogDistance.currentValue));
}
void CAxisSettingsDlg::RefreshPositionDetails(int nAxisId, int pageNumber)
@@ -291,13 +284,16 @@
         CString value;
         value.Format(_T("%.3f"), position.range.currentValue);
         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);
               if (!IsFloatInRange((LPTSTR)(LPCTSTR)value, position.range.minValue, position.range.maxValue)) {
                  CString strError;
                  strError.Format(_T("定位点%d值必须在 %.3f 和 %.3f 之间!"), i + 1, position.range.minValue, position.range.maxValue);
                  ShowTipText(strError, 5);
               }
               else {
                  pPositionCtrl->SetWindowText(value);
               }
            }
         }
      }
@@ -346,8 +342,8 @@
   // 判断输入的值是否在合法范围内
   if (enteredValue < minValue || enteredValue > maxValue) {
      CString strError;
      strError.Format(_T("定位点的值必须在 %f 和 %f 之间!"), minValue, maxValue);
      pDescriptionCtrl->SetWindowText(strError);
      strError.Format(_T("定位点%d的值必须在 %f 和 %f 之间!"), currentIndex + 1, minValue, maxValue);
      ShowTipText(strError, 5);
   }
   else {
      position.range.currentValue = enteredValue;
@@ -385,19 +381,19 @@
   // 获取界面上的修改参数
   CString text;
   m_pRegexEdit[EDIT_MANUAL_SPEED]->GetWindowText(text);
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED)->GetWindowText(text);
   axisData.manualSpeed.currentValue = _ttof(text);
   m_pRegexEdit[EDIT_AUTO_SPEED]->GetWindowText(text);
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED)->GetWindowText(text);
   axisData.autoSpeed.currentValue = _ttof(text);
   m_pRegexEdit[EDIT_ACCE_TIME]->GetWindowText(text);
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_ACCE_TIME)->GetWindowText(text);
   axisData.accelerationTime.currentValue = _ttof(text);
   m_pRegexEdit[EDIT_DECE_TIME]->GetWindowText(text);
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_DECE_TIME)->GetWindowText(text);
   axisData.decelerationTime.currentValue = _ttof(text);
   m_pRegexEdit[EDIT_MICROMENTUM]->GetWindowText(text);
   GetDlgItem(IDC_EDIT_AXIS_MODITFY_MICROMENTUM)->GetWindowText(text);
   axisData.jogDistance.currentValue = _ttof(text);
   // 更新定位点数据
@@ -756,9 +752,15 @@
   ON_BN_CLICKED(IDC_BUTTON_AXIS_UPDATE_UI, &CAxisSettingsDlg::OnBnClickedButtonAxisUpdateUi)
   ON_BN_CLICKED(IDC_BUTTON_AXIS_DETAIL_SETTINGS, &CAxisSettingsDlg::OnBnClickedButtonAxisDetailSettings)
   ON_MESSAGE(ID_MSG_UPDATA_DATA_TO_UI, &CAxisSettingsDlg::OnUpdateDataToUI)
   ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED, &CAxisSettingsDlg::OnKillfocusEditAxisModitfyManualSpeed)
   ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED, &CAxisSettingsDlg::OnKillfocusEditAxisModitfyAutoSpeed)
   ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_DECE_TIME, &CAxisSettingsDlg::OnKillfocusEditAxisModitfyDeceTime)
   ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_ACCE_TIME, &CAxisSettingsDlg::OnKillfocusEditAxisModitfyAcceTime)
   ON_EN_KILLFOCUS(IDC_EDIT_AXIS_MODITFY_MICROMENTUM, &CAxisSettingsDlg::OnEnKillfocusEditAxisModitfyMicromentum)
   ON_WM_SIZE()
   ON_WM_TIMER()
   ON_WM_CLOSE()
   ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
@@ -806,18 +808,6 @@
      AdjustLabelFont(*pLabel);
   }
   // 初始化编辑框
   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);
@@ -1011,8 +1001,17 @@
void CAxisSettingsDlg::OnSize(UINT nType, int cx, int cy)
{
   CBaseDlg::OnSize(nType, cx, cy);
   if (GetDlgItem(IDC_LABEL_TIP) == nullptr) return;
   // TODO: 在此处添加消息处理程序代码
   CWnd* pItem;
   CRect rcClient;
   GetClientRect(&rcClient);
   pItem = GetDlgItem(IDC_LABEL_TIP);
   pItem->MoveWindow(0, 0, rcClient.Width(), 36);
   // 动态调整各个 CBLLabel 的字体大小
   for (auto pLabel : m_pBlLabels) {
      AdjustLabelFont(*pLabel);
@@ -1061,13 +1060,11 @@
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup2()
{
   // TODO: 在此添加控件通知处理程序代码
   SwitchToPage(2);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisAnchorPointGroup3()
{
   // TODO: 在此添加控件通知处理程序代码
   SwitchToPage(3);
}
@@ -1358,6 +1355,110 @@
   return 0;
}
void CAxisSettingsDlg::OnKillfocusEditAxisModitfyManualSpeed()
{
   // TODO: 在此添加控件通知处理程序代码
   int nAxisId = GetCurrentSelectedAxisID();
   if (nAxisId == -1) {
      AfxMessageBox(_T("请选择一个有效的轴编号!"));
      return;
   }
   auto axisDetails = m_pAxisManager->GetAxis(nAxisId);
   auto dMinValue = axisDetails.manualSpeed.minValue;
   auto dMaxValue = axisDetails.manualSpeed.maxValue;
   CString strText;
   GetDlgItemText(IDC_EDIT_AXIS_MODITFY_MANUAL_SPEED, strText);
   if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) {
      CString strError;
      strError.Format(_T("手动速度值必须在 %.3f 和 %.3f 之间!"), dMinValue, dMaxValue);
      ShowTipText(strError, 5);
   }
}
void CAxisSettingsDlg::OnKillfocusEditAxisModitfyAutoSpeed()
{
   // TODO: 在此添加控件通知处理程序代码
   int nAxisId = GetCurrentSelectedAxisID();
   if (nAxisId == -1) {
      AfxMessageBox(_T("请选择一个有效的轴编号!"));
      return;
   }
   auto axisDetails = m_pAxisManager->GetAxis(nAxisId);
   auto dMinValue = axisDetails.autoSpeed.minValue;
   auto dMaxValue = axisDetails.autoSpeed.maxValue;
   CString strText;
   GetDlgItemText(IDC_EDIT_AXIS_MODITFY_AUTO_SPEED, strText);
   if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) {
      CString strError;
      strError.Format(_T("自动速度值必须在 %.3f 和 %.3f 之间!"), dMinValue, dMaxValue);
      ShowTipText(strError, 5);
   }
}
void CAxisSettingsDlg::OnKillfocusEditAxisModitfyAcceTime()
{
   // TODO: 在此添加控件通知处理程序代码
   int nAxisId = GetCurrentSelectedAxisID();
   if (nAxisId == -1) {
      AfxMessageBox(_T("请选择一个有效的轴编号!"));
      return;
   }
   auto axisDetails = m_pAxisManager->GetAxis(nAxisId);
   auto dMinValue = axisDetails.accelerationTime.minValue;
   auto dMaxValue = axisDetails.accelerationTime.maxValue;
   CString strText;
   GetDlgItemText(IDC_EDIT_AXIS_MODITFY_ACCE_TIME, strText);
   if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) {
      CString strError;
      strError.Format(_T("加速时间值必须在 %.3f 和 %.3f 之间!"), dMinValue, dMaxValue);
      ShowTipText(strError, 5);
   }
}
void CAxisSettingsDlg::OnKillfocusEditAxisModitfyDeceTime()
{
   // TODO: 在此添加控件通知处理程序代码
   int nAxisId = GetCurrentSelectedAxisID();
   if (nAxisId == -1) {
      AfxMessageBox(_T("请选择一个有效的轴编号!"));
      return;
   }
   auto axisDetails = m_pAxisManager->GetAxis(nAxisId);
   auto dMinValue = axisDetails.decelerationTime.minValue;
   auto dMaxValue = axisDetails.decelerationTime.maxValue;
   CString strText;
   GetDlgItemText(IDC_EDIT_AXIS_MODITFY_DECE_TIME, strText);
   if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) {
      CString strError;
      strError.Format(_T("减速时间值必须在 %.3f 和 %.3f 之间!"), dMinValue, dMaxValue);
      ShowTipText(strError, 5);
   }
}
void CAxisSettingsDlg::OnEnKillfocusEditAxisModitfyMicromentum()
{
   int nAxisId = GetCurrentSelectedAxisID();
   if (nAxisId == -1) {
      AfxMessageBox(_T("请选择一个有效的轴编号!"));
      return;
   }
   auto axisDetails = m_pAxisManager->GetAxis(nAxisId);
   auto dMinValue = axisDetails.jogDistance.minValue;
   auto dMaxValue = axisDetails.jogDistance.maxValue;
   CString strText;
   GetDlgItemText(IDC_EDIT_AXIS_MODITFY_MICROMENTUM, strText);
   if (!IsFloatInRange((LPTSTR)(LPCTSTR)strText, dMinValue, dMaxValue)) {
      CString strError;
      strError.Format(_T("微动量值必须在 %.3f 和 %.3f 之间!"), dMinValue, dMaxValue);
      ShowTipText(strError, 5);
   }
}
void CAxisSettingsDlg::OnTimer(UINT_PTR nIDEvent)
{
   if (TIMER_READ_PLC_DATA == nIDEvent) {
@@ -1370,6 +1471,10 @@
      ReadPLCDataToUI(nAxisId);
   }   
   else if (TIMER_HIDE_TIP == nIDEvent) {
      KillTimer(TIMER_HIDE_TIP);
      HideTip();
   }
   CBaseDlg::OnTimer(nIDEvent);
}
@@ -1381,3 +1486,62 @@
   CBaseDlg::OnClose();
}
HBRUSH CAxisSettingsDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
   HBRUSH hbr = CBaseDlg::OnCtlColor(pDC, pWnd, nCtlColor);
   int nCtrlID = pWnd->GetDlgCtrlID();
   if (nCtrlID == IDC_LABEL_TIP) {
      pDC->SetTextColor(m_crTipText);
      pDC->SetBkColor(m_crTipBack);
      if (m_hTipFont == nullptr) {
         HFONT hFontDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
         CFont* pFont = CFont::FromHandle(hFontDefault);
         LOGFONT lf;
         pFont->GetLogFont(&lf);
         lf.lfHeight -= 8;
         m_hTipFont = ::CreateFontIndirect(&lf);
         ::SelectObject(pDC->m_hDC, m_hTipFont);
      }
      return m_hbrTip;
   }
   return hbr;
}
void CAxisSettingsDlg::ShowTipText(const char* pszText, float sec)
{
   CString strText;
   strText.Format(_T(" * %s"), pszText);
   SetDlgItemText(IDC_LABEL_TIP, strText);
   GetDlgItem(IDC_LABEL_TIP)->ShowWindow(SW_SHOW);
   SetTimer(TIMER_HIDE_TIP, (int)(sec * 1000.0), nullptr);
}
void CAxisSettingsDlg::HideTip()
{
   GetDlgItem(IDC_LABEL_TIP)->ShowWindow(SW_HIDE);
}
bool CAxisSettingsDlg::IsFloatInRange(const std::string& strInput, double fLowerBound, double fUpperBound)
{
   // 是否为合法浮点数
   std::regex floatRegex(R"([-+]?\d*\.?\d+([eE][-+]?\d+)?)");
   if (!std::regex_match(strInput, floatRegex)) {
      return false;
   }
   try {
      double value = std::stod(strInput);
      return value >= fLowerBound && value <= fUpperBound;
   }
   catch (const std::exception&) {
      return false;
   }
}