LAPTOP-T815PCOQ\25526
2024-12-11 43419b86d6a4a2d879454938fb7db7cc84d8c011
1. 添加自定义限制编辑框 2. 在axis设定界面实现输入限制功能
已添加2个文件
已修改5个文件
287 ■■■■■ 文件已修改
SourceCode/Bond/BondEq/BondEq.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEq.vcxproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/RegexEdit.cpp 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/RegexEdit.h 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/Resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp 82 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/AxisSettingsDlg.h 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEq.rc
Binary files differ
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" />
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();
        }
    }
}
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_)
SourceCode/Bond/BondEq/Resource.h
Binary files differ
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 ||
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;