1.修改配方管理模块,定位点等参数有最大值最小值 2.同步修改合并轴管理界面3.IO界面显示16个,16个为一组
已修改7个文件
469 ■■■■ 文件已修改
SourceCode/Bond/BondEq/BondEq.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp 132 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/FileManager/RecipeManager.h 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp 280 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/AxisSettingsDlg.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/IOMonitoringDlg.cpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/View/UserManagerDlg.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/BondEq/BondEq.rc
Binary files differ
SourceCode/Bond/BondEq/FileManager/RecipeManager.cpp
@@ -37,16 +37,44 @@
        axisInfo.number = axisNode.attribute("number").value();
        axisInfo.description = axisNode.attribute("description").value();
        axisInfo.startAddress = axisNode.attribute("start_address").value();
        axisInfo.jogDistance = axisNode.attribute("jog_distance").as_double();
        axisInfo.manualSpeed = axisNode.attribute("manual_speed").as_double();
        axisInfo.autoSpeed = axisNode.attribute("auto_speed").as_double();
        axisInfo.accelerationTime = axisNode.attribute("acceleration_time").as_double();
        axisInfo.decelerationTime = axisNode.attribute("deceleration_time").as_double();
        // 加载 ValueRange 值
        axisInfo.jogDistance = ValueRange(
            axisNode.child("jog_distance").attribute("min").as_double(),
            axisNode.child("jog_distance").attribute("max").as_double(),
            axisNode.child("jog_distance").attribute("current").as_double()
        );
        axisInfo.manualSpeed = ValueRange(
            axisNode.child("manual_speed").attribute("min").as_double(),
            axisNode.child("manual_speed").attribute("max").as_double(),
            axisNode.child("manual_speed").attribute("current").as_double()
        );
        axisInfo.autoSpeed = ValueRange(
            axisNode.child("auto_speed").attribute("min").as_double(),
            axisNode.child("auto_speed").attribute("max").as_double(),
            axisNode.child("auto_speed").attribute("current").as_double()
        );
        axisInfo.accelerationTime = ValueRange(
            axisNode.child("acceleration_time").attribute("min").as_double(),
            axisNode.child("acceleration_time").attribute("max").as_double(),
            axisNode.child("acceleration_time").attribute("current").as_double()
        );
        axisInfo.decelerationTime = ValueRange(
            axisNode.child("deceleration_time").attribute("min").as_double(),
            axisNode.child("deceleration_time").attribute("max").as_double(),
            axisNode.child("deceleration_time").attribute("current").as_double()
        );
        // 加载 PositionRange 值
        for (auto positionNode : axisNode.child("Positions").children("Position")) {
            std::string description = positionNode.attribute("description").value();
            double positionValue = positionNode.attribute("value").as_double();
            axisInfo.positions.emplace_back(description, positionValue);
            ValueRange positionRange(
                positionNode.attribute("min").as_double(),
                positionNode.attribute("max").as_double(),
                positionNode.attribute("current").as_double()
            );
            axisInfo.positions.emplace_back(PositionRange(description, positionRange));
        }
        m_axes[axisInfo.id] = axisInfo;
@@ -83,18 +111,36 @@
        axisNode.append_attribute("number") = axisInfo.number.c_str();
        axisNode.append_attribute("description") = axisInfo.description.c_str();
        axisNode.append_attribute("start_address") = axisInfo.startAddress.c_str();
        axisNode.append_attribute("jog_distance") = axisInfo.jogDistance;
        axisNode.append_attribute("manual_speed") = axisInfo.manualSpeed;
        axisNode.append_attribute("auto_speed") = axisInfo.autoSpeed;
        axisNode.append_attribute("acceleration_time") = axisInfo.accelerationTime;
        axisNode.append_attribute("deceleration_time") = axisInfo.decelerationTime;
        // 添加定位点列表
        // 保存 ValueRange 值
        axisNode.append_child("jog_distance").append_attribute("min") = axisInfo.jogDistance.minValue;
        axisNode.append_child("jog_distance").append_attribute("max") = axisInfo.jogDistance.maxValue;
        axisNode.append_child("jog_distance").append_attribute("current") = axisInfo.jogDistance.currentValue;
        axisNode.append_child("manual_speed").append_attribute("min") = axisInfo.manualSpeed.minValue;
        axisNode.append_child("manual_speed").append_attribute("max") = axisInfo.manualSpeed.maxValue;
        axisNode.append_child("manual_speed").append_attribute("current") = axisInfo.manualSpeed.currentValue;
        axisNode.append_child("auto_speed").append_attribute("min") = axisInfo.autoSpeed.minValue;
        axisNode.append_child("auto_speed").append_attribute("max") = axisInfo.autoSpeed.maxValue;
        axisNode.append_child("auto_speed").append_attribute("current") = axisInfo.autoSpeed.currentValue;
        axisNode.append_child("acceleration_time").append_attribute("min") = axisInfo.accelerationTime.minValue;
        axisNode.append_child("acceleration_time").append_attribute("max") = axisInfo.accelerationTime.maxValue;
        axisNode.append_child("acceleration_time").append_attribute("current") = axisInfo.accelerationTime.currentValue;
        axisNode.append_child("deceleration_time").append_attribute("min") = axisInfo.decelerationTime.minValue;
        axisNode.append_child("deceleration_time").append_attribute("max") = axisInfo.decelerationTime.maxValue;
        axisNode.append_child("deceleration_time").append_attribute("current") = axisInfo.decelerationTime.currentValue;
        // 保存 PositionRange 值
        auto positionsNode = axisNode.append_child("Positions");
        for (const auto& position : axisInfo.positions) {
            auto positionNode = positionsNode.append_child("Position");
            positionNode.append_attribute("description") = position.first.c_str();
            positionNode.append_attribute("value") = position.second;
            positionNode.append_attribute("description") = position.description.c_str();
            positionNode.append_attribute("min") = position.range.minValue;
            positionNode.append_attribute("max") = position.range.maxValue;
            positionNode.append_attribute("current") = position.range.currentValue;
        }
    }
@@ -112,14 +158,19 @@
        axisInfo.number = "M100-M" + std::to_string(axisId);
        axisInfo.description = "Default_Axis" + std::to_string(axisId);
        axisInfo.startAddress = "ZR" + std::to_string(10000 + (axisId - 1) * 300);
        axisInfo.jogDistance = 0.5;
        axisInfo.manualSpeed = 10.0;
        axisInfo.autoSpeed = 15.0;
        axisInfo.accelerationTime = 0.2;
        axisInfo.decelerationTime = 0.3;
        // 设置默认的 ValueRange
        axisInfo.jogDistance = ValueRange(1.0, 10.0, 1.0);
        axisInfo.manualSpeed = ValueRange(1.0, 100.0, 10.0);
        axisInfo.autoSpeed = ValueRange(5.0, 200.0, 50.0);
        axisInfo.accelerationTime = ValueRange(1.0, 10.0, 1.0);
        axisInfo.decelerationTime = ValueRange(1.0, 10.0, 1.0);
        // 添加定位点并设置默认的最小值和最大值
        for (int posId = 1; posId <= 25; ++posId) {
            axisInfo.positions.emplace_back("Position " + std::to_string(posId), posId * 10.0);
            double minPos = posId * 5.0;
            double maxPos = posId * 20.0;
            axisInfo.positions.emplace_back(PositionRange("Position " + std::to_string(posId), ValueRange(minPos, maxPos, posId * 10.0)));
        }
        m_axes[axisId] = axisInfo;
@@ -135,11 +186,11 @@
AxisInfo RecipeManager::getAxis(int axisId) const {
    auto it = m_axes.find(axisId);
    if (it != m_axes.end()) {
        return it->second;
        return it->second;  // 如果找到了轴,返回其详细信息
    }
    // 返回一个无效的 AxisInfo
    return AxisInfo{ -1, "", "", "", 0.0, 0.0, 0.0, 0.0, 0.0, {}};
    // 如果没有找到该轴,返回一个默认的无效 AxisInfo
    return AxisInfo{ -1, "", "", "", ValueRange(), ValueRange(), ValueRange(), ValueRange(), ValueRange(), {} };
}
// 更新轴信息
@@ -177,8 +228,8 @@
}
// 获取指定页的定位点
std::vector<std::pair<std::string, double>> RecipeManager::getPositions(int axisId, int pageNumber, int pageSize) const {
    std::vector<std::pair<std::string, double>> result;
std::vector<PositionRange> RecipeManager::getPositions(int axisId, int pageNumber, int pageSize) const {
    std::vector<PositionRange> result;
    // 检查轴是否存在
    auto it = m_axes.find(axisId);
@@ -196,11 +247,10 @@
    // 遍历定位点,按分页提取数据
    int index = 0;
    for (const auto& pos : positions) {
        const std::string& description = pos.first; // 键:描述
        double value = pos.second;                  // 值:位置值
        const PositionRange& position = pos;  // 定位点包含描述、位置、最小值、最大值和当前值
        if (index >= startIndex && index < endIndex) {
            result.emplace_back(description, value);
            result.push_back(position);  // 添加完整的 PositionRange 对象
        }
        ++index;
@@ -211,3 +261,27 @@
    return result;
}
// 获取指定轴的定位点
PositionRange RecipeManager::getPositionByIndex(int axisId, int pageNumber, int pageSize, int currentIndex) const {
    // 检查轴是否存在
    auto it = m_axes.find(axisId);
    if (it == m_axes.end()) {
        return PositionRange();  // 轴不存在,返回默认构造的 PositionRange(无效的定位点)
    }
    // 获取指定轴的所有定位点
    const auto& positions = it->second.positions;
    // 确定分页范围
    int startIndex = (pageNumber - 1) * pageSize;
    int endIndex = startIndex + pageSize;
    // 如果 currentIndex 超过了当前页的范围,返回无效的 PositionRange
    if (currentIndex < 0 || currentIndex >= pageSize || currentIndex + startIndex >= positions.size()) {
        return PositionRange();  // 返回无效的定位点
    }
    // 返回指定定位点(考虑分页)
    return positions[startIndex + currentIndex];
}
SourceCode/Bond/BondEq/FileManager/RecipeManager.h
@@ -6,18 +6,37 @@
#include <map>
#include "pugixml.hpp"
struct ValueRange {
    double minValue;        // 最小值
    double maxValue;        // 最大值
    double currentValue;    // 当前值
    // 构造函数初始化
    ValueRange(double minVal = 0.0, double maxVal = 0.0, double curVal = 0.0)
        : minValue(minVal), maxValue(maxVal), currentValue(curVal) {}
};
struct PositionRange {
    std::string description;  // 定位点描述
    ValueRange range;         // 位置的最小值、最大值和当前值
    // 构造函数初始化
    PositionRange(const std::string& desc = "", const ValueRange& r = ValueRange())
        : description(desc), range(r) {}
};
// 轴信息结构体
struct AxisInfo {
    int id;                                    // 轴ID
    std::string number;                        // 轴编号
    std::string description;                   // 轴描述
    std::string startAddress;                  // 起始地址
    double jogDistance;                        // 微动量
    double manualSpeed;                        // 手动速度
    double autoSpeed;                          // 自动速度
    double accelerationTime;                   // 加速时间
    double decelerationTime;                   // 减速时间
    std::vector<std::pair<std::string, double>> positions; // 定位点:描述和位置
    ValueRange jogDistance;                    // 微动量(最小值、最大值、当前值)
    ValueRange manualSpeed;                    // 手动速度(最小值、最大值、当前值)
    ValueRange autoSpeed;                      // 自动速度(最小值、最大值、当前值)
    ValueRange accelerationTime;               // 加速时间(最小值、最大值、当前值)
    ValueRange decelerationTime;               // 减速时间(最小值、最大值、当前值)
    std::vector<PositionRange> positions;      // 定位点:描述、位置及最小最大值
};
// 配方管理类
@@ -57,7 +76,10 @@
    std::vector<int> getAllAxisID() const;
    // 获取指定页的定位点
    std::vector<std::pair<std::string, double>> getPositions(int axisId, int pageNumber, int pageSize) const;
    std::vector<PositionRange> getPositions(int axisId, int pageNumber, int pageSize) const;
    // 获取指定页的定位点
    PositionRange getPositionByIndex(int axisId, int pageNumber, int pageSize, int currentIndex) const;
private:
    RecipeManager();
SourceCode/Bond/BondEq/View/AxisSettingsDlg.cpp
@@ -12,7 +12,6 @@
#define TIMER_INIT                1
#define TIMER_READ_PLC_DATA        2
#define ID_MSG_UPDATA_DATA_TO_UI    WM_USER + 101
// CAxisSettingsDlg 对话框
@@ -40,8 +39,13 @@
    m_bReady = FALSE;
    m_bBusy = FALSE;
    m_bErr = FALSE;
    for (int i = 0; i < 9; i++) {
        m_pBlBtns[i] = new CBlButton();
    }
    for (int i = 0; i < 6; i++) {
        m_pBlLabels[i] = new CBLLabel();
    }
}
@@ -57,6 +61,10 @@
    for (int i = 0; i < 9; i++) {
        delete m_pBlBtns[i];
    }
    for (int i = 0; i < 6; i++) {
        delete m_pBlLabels[i];
    }
}
@@ -74,12 +82,6 @@
void CAxisSettingsDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_STATIC_AXIS_TEST_FLS, m_staticFLS);
    DDX_Control(pDX, IDC_STATIC_AXIS_TEST_DOG, m_staticDOG);
    DDX_Control(pDX, IDC_STATIC_AXIS_TEST_RLS, m_staticRLS);
    DDX_Control(pDX, IDC_STATIC_AXIS_TEST_READY, m_staticReady);
    DDX_Control(pDX, IDC_STATIC_AXIS_TEST_BUSY, m_staticBusy);
    DDX_Control(pDX, IDC_STATIC_AXIS_TEST_ERR, m_staticErr);
    DDX_Control(pDX, IDC_COMBO_AXIS_NAME, m_comboAxisNO);
    DDX_Control(pDX, IDC_STATIC_AXIS_NUMBER, m_staticAxisNO);
    DDX_Control(pDX, IDC_STATIC_AXIS_DESCRIP, m_staticAxisDescription);
@@ -227,6 +229,16 @@
    }
}
void CAxisSettingsDlg::HideEditCursor(int nCtrlID)
{
    CEdit* pEdit = (CEdit*)GetDlgItem(nCtrlID);
    if (pEdit && pEdit->GetSafeHwnd()) {
        pEdit->EnableWindow(FALSE); // 禁用控件
        pEdit->SetReadOnly(TRUE);   // 设置为只读
        pEdit->HideCaret();         // 隐藏光标
    }
}
int CAxisSettingsDlg::getCurrentSelectedAxisID()
{
    int currentIndex = m_comboAxisNO.GetCurSel();
@@ -283,11 +295,11 @@
    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));                // 微动量
    m_editManualSpeed.SetWindowText(formatDouble(axisDetails.manualSpeed));                // 手动速度
    m_editAutoSpeed.SetWindowText(formatDouble(axisDetails.autoSpeed));                    // 自动速度
    m_editAccelerationTime.SetWindowText(formatDouble(axisDetails.accelerationTime));    // 加速时间
    m_editDecelerationTime.SetWindowText(formatDouble(axisDetails.decelerationTime));    // 减速时间
    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));    // 减速时间
}
void CAxisSettingsDlg::refreshPositionDetails(int nAxisId, int pageNumber)
@@ -312,17 +324,62 @@
        CWnd* pPositionCtrl = GetDlgItem(positionCtrlId);
        if (i < positions.size()) {
            CString description = CString(positions[i].first.c_str());
            CString value;
            value.Format(_T("%.3f"), positions[i].second);
            const PositionRange& position = positions[i];
            // 显示定位点的描述
            CString description = CString(position.description.c_str());
            if (pDescriptionCtrl) pDescriptionCtrl->SetWindowText(description);
            // 显示定位点的当前位置
            CString value;
            value.Format(_T("%.3f"), position.range.currentValue);
            if (pPositionCtrl) pPositionCtrl->SetWindowText(value);
        }
        else {
            // 清空控件内容
            if (pDescriptionCtrl) pDescriptionCtrl->SetWindowText(_T(""));
            if (pPositionCtrl) pPositionCtrl->SetWindowText(_T(""));
        }
    }
}
void CAxisSettingsDlg::UpdatePositionRange(PositionRange& position, int pageNumber, int pageSize, int currentIndex)
{
    // 获取当前输入框中的文本
    CString strText;
    GetDlgItem(IDC_EDIT_AXIS_CURR_POS)->GetWindowText(strText);
    if (strText.IsEmpty()) {
        return;
    }
    CString descriptionCtrlName, positionCtrlName;
    descriptionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP%d"), currentIndex + 1);
    positionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT%d"), currentIndex + 1);
    UINT descriptionCtrlId = FindIDByName(descriptionCtrlName);
    UINT positionCtrlId = FindIDByName(positionCtrlName);
    CWnd* pDescriptionCtrl = GetDlgItem(descriptionCtrlId);
    CWnd* pPositionCtrl = GetDlgItem(positionCtrlId);
    if (pDescriptionCtrl == nullptr || pPositionCtrl == nullptr) {
        return;
    }
    double enteredValue = _ttof(strText);
    double minValue = position.range.minValue;
    double maxValue = position.range.maxValue;
    // 判断输入的值是否在合法范围内
    if (enteredValue < minValue || enteredValue > maxValue) {
        CString strError;
        strError.Format(_T("定位点的值必须在 %f 和 %f 之间!"), minValue, maxValue);
        pDescriptionCtrl->SetWindowText(strError);
    }
    else {
        position.range.currentValue = enteredValue;
        pDescriptionCtrl->SetWindowText(CString(position.description.c_str()));
        pPositionCtrl->SetWindowText(strText);
    }
}
@@ -358,45 +415,49 @@
    // 获取界面上的修改参数
    CString text;
    m_editManualSpeed.GetWindowText(text);
    axisData.manualSpeed = _ttof(text);
    axisData.manualSpeed.currentValue = _ttof(text);
    m_editAutoSpeed.GetWindowText(text);
    axisData.autoSpeed = _ttof(text);
    axisData.autoSpeed.currentValue = _ttof(text);
    m_editAccelerationTime.GetWindowText(text);
    axisData.accelerationTime = _ttof(text);
    axisData.accelerationTime.currentValue = _ttof(text);
    m_editDecelerationTime.GetWindowText(text);
    axisData.decelerationTime = _ttof(text);
    axisData.decelerationTime.currentValue = _ttof(text);
    m_editJogDistance.GetWindowText(text);
    axisData.jogDistance = _ttof(text);
    axisData.jogDistance.currentValue = _ttof(text);
    // 更新定位点数据
    for (int i = 0; i < pageSize; ++i) {
        int index = (m_currentPage - 1) * pageSize + i;
        if (index < axisData.positions.size()) {
            CString descriptionName, positionName;
            // 构建控件名称
            CString descriptionName, positionName, minValueName, maxValueName;
            descriptionName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP%d"), i + 1);
            positionName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT%d"), i + 1);
            // 获取控件
            CEdit* pDescriptionEdit = (CEdit*)GetDlgItem(FindIDByName(descriptionName));
            CEdit* pPositionEdit = (CEdit*)GetDlgItem(FindIDByName(positionName));
            if (pDescriptionEdit && pPositionEdit) {
                CString description, positionValue;
                CString description, positionValue, minValue, maxValue;
                // 获取控件中的文本
                pDescriptionEdit->GetWindowText(description);
                pPositionEdit->GetWindowText(positionValue);
                // 更新 RecipeManager 中的数据
                axisData.positions[index].first = CT2A(description);
                axisData.positions[index].second = _ttof(positionValue);
                axisData.positions[index].description = CT2A(description);
                axisData.positions[index].range.currentValue = _ttof(positionValue);
            }
        }
    }
    // 保存回 RecipeManager
    // 保存 RecipeManager
    recipeManager.updateAxis(axisData);
}
@@ -510,7 +571,7 @@
    }
    // 写入手动速度
    m_pPLC->writeDWord(component, startAddress + 82, (int)axisData.manualSpeed * 1000, [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
    m_pPLC->writeDWord(component, startAddress + 82, (int)axisData.manualSpeed.currentValue * 1000, [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: 手动速度, 地址: %d, 值: %lu\n", addr, value);
        }
@@ -520,7 +581,7 @@
    });
    // 写入自动速度
    m_pPLC->writeDWord(component, startAddress + 84, (int)(axisData.autoSpeed * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
    m_pPLC->writeDWord(component, startAddress + 84, (int)(axisData.autoSpeed.currentValue * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: 自动速度, 地址: %d, 值: %lu\n", addr, value);
        }
@@ -530,7 +591,7 @@
    });
    // 写入加速时间, 转换为毫秒
    m_pPLC->writeDWord(component, startAddress + 62, (int)(axisData.accelerationTime * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
    m_pPLC->writeDWord(component, startAddress + 62, (int)(axisData.accelerationTime.currentValue * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: 加速时间, 地址: %d, 值: %lu\n", addr, value);
        }
@@ -540,7 +601,7 @@
    });
    // 写入减速时间, 转换为毫秒
    m_pPLC->writeDWord(component, startAddress + 64, (int)(axisData.decelerationTime * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
    m_pPLC->writeDWord(component, startAddress + 64, (int)(axisData.decelerationTime.currentValue * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: 减速时间, 地址: %d, 值: %lu\n", addr, value);
        }
@@ -550,7 +611,7 @@
    });
    // 写入微动量
    m_pPLC->writeWord(component, startAddress + 81, (int)(axisData.jogDistance * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
    m_pPLC->writeWord(component, startAddress + 81, (int)(axisData.jogDistance.currentValue * 1000.0), [](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        if (flag == 0) {
            TRACE("\n写入成功: 微动量, 地址: %d, 值: %lu\n", addr, value);
        }
@@ -565,7 +626,8 @@
        const auto& position = axisData.positions[i];
        unsigned int positionAddress = positionStartAddress + (i * 2);
        m_pPLC->writeDWord(component, positionAddress, (int)(position.second * 1000), [i, positionAddress](IMcChannel* pChannel, int addr, DWORD value, int flag) {
        double valueToWrite = position.range.currentValue;
        m_pPLC->writeDWord(component, positionAddress, (int)(valueToWrite * 1000), [i, positionAddress](IMcChannel* pChannel, int addr, DWORD value, int flag) {
            if (flag == 0) {
                    TRACE("\n写入成功: 定位点 %d, 地址: %d, 值: %lu\n", i + 1, positionAddress, value);
            }
@@ -574,7 +636,6 @@
            }
        });
    }
}
void CAxisSettingsDlg::handleAxisOperation(AxisOperationType eOpType, bool bPressed)
@@ -722,9 +783,31 @@
    strTitle.Format(_T("Axis设定(配方: %s)"), m_strRecipeName);
    SetWindowText(strTitle);
    // 隐藏光标
    //HideEditCursor(IDC_EDIT_AXIS_CURR_POS);
    HideEditCursor(IDC_EDIT_AXIS_CURR_MANUAL_SPEED);
    HideEditCursor(IDC_EDIT_AXIS_CURR_AUTO_SPEED);
    HideEditCursor(IDC_EDIT_AXIS_CURR_ROTA_SPEED);
    HideEditCursor(IDC_EDIT_AXIS_CURR_LOAD);
    HideEditCursor(IDC_EDIT_AXIS_CURR_ERROR_NUMBER);
    HideEditCursor(IDC_EDIT_AXIS_CURR_ALARM_NUMBER);
    // 测试
    {
        CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_AXIS_CURR_POS);
        pEdit->EnableWindow(TRUE);
        pEdit->SetReadOnly(FALSE);
    }
    // 设置测试状态
    CBLLabel* pLabels[] = { &m_staticFLS, &m_staticDOG, &m_staticRLS, &m_staticReady, &m_staticBusy, &m_staticErr };
    for (auto pLabel : pLabels) {
    m_pBlLabels[0]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_FLS, this);
    m_pBlLabels[1]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_DOG, this);
    m_pBlLabels[2]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_RLS, this);
    m_pBlLabels[3]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_READY, this);
    m_pBlLabels[4]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_BUSY, this);
    m_pBlLabels[5]->SubclassDlgItem(IDC_STATIC_AXIS_TEST_ERR, this);
    for (auto pLabel : m_pBlLabels) {
        pLabel->SetBkColor(RGB(0, 180, 0));
        pLabel->ModifyStyle(0, SS_NOTIFY);
        pLabel->SetTextColor(RGB(255, 255, 255));
@@ -766,7 +849,6 @@
    m_pBlBtns[8]->SetBkgndColor(BS_NORMAL, BTN_STOP_BKGND_NORMAL);
    m_pBlBtns[8]->SetBkgndColor(BS_HOVER, BTN_STOP_BKGND_HOVER);
    m_pBlBtns[8]->SetBkgndColor(BS_PRESS, BTN_STOP_BKGND_PRESS);
    // 初始化当前页面为第一页
    m_currentPage = 1;
@@ -826,6 +908,94 @@
BOOL CAxisSettingsDlg::PreTranslateMessage(MSG* pMsg)
{
    // TODO: 在此添加专用代码和/或调用基类
    CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
    if (pWnd) {
        // 判断鼠标是否进入指定控件区域
        if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP1)->m_hWnd ||
            pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP2)->m_hWnd ||
            pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP3)->m_hWnd ||
            pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP4)->m_hWnd ||
            pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP5)->m_hWnd) {
            RecipeManager& recipeManager = RecipeManager::getInstance();
            int currentIndex = -1;
            // 根据控件ID确定 currentIndex
            if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP1)->m_hWnd) {
                currentIndex = 0;
            }
            else if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP2)->m_hWnd) {
                currentIndex = 1;
            }
            else if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP3)->m_hWnd) {
                currentIndex = 2;
            }
            else if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP4)->m_hWnd) {
                currentIndex = 3;
            }
            else if (pWnd->GetSafeHwnd() == GetDlgItem(IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP5)->m_hWnd) {
                currentIndex = 4;
            }
            if (currentIndex == -1) {
                return CDialogEx::PreTranslateMessage(pMsg);
            }
            CString descriptionCtrlName, positionCtrlName;
            descriptionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT_DESCRIP%d"), currentIndex + 1);
            positionCtrlName.Format(_T("IDC_EDIT_AXIS_ANCHOR_POINT%d"), currentIndex + 1);
            UINT descriptionCtrlId = FindIDByName(descriptionCtrlName);
            UINT positionCtrlId = FindIDByName(positionCtrlName);
            CWnd* pDescriptionCtrl = GetDlgItem(descriptionCtrlId);
            CWnd* pPositionCtrl = GetDlgItem(positionCtrlId);
            if (pDescriptionCtrl == nullptr || pPositionCtrl == nullptr) {
                return CDialogEx::PreTranslateMessage(pMsg);
            }
            PositionRange& position = recipeManager.getPositionByIndex(getCurrentSelectedAxisID(), m_currentPage, 5, currentIndex);
            if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK) {
                // 处理鼠标点击事件
                // 设置鼠标为箭头光标
                ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
                CString strText;
                GetDlgItem(IDC_EDIT_AXIS_CURR_POS)->GetWindowText(strText);
                if (strText.IsEmpty()) {
                    return CDialogEx::PreTranslateMessage(pMsg);;
                }
                double enteredValue = _ttof(strText);
                double minValue = position.range.minValue;
                double maxValue = position.range.maxValue;
                // 判断输入的值是否在合法范围内
                if (enteredValue < minValue || enteredValue > maxValue) {
                    CString strError;
                    strError.Format(_T("定位点的值必须在 %f 和 %f 之间!"), minValue, maxValue);
                    pDescriptionCtrl->SetWindowText(strError);
                }
                else {
                    position.range.currentValue = enteredValue;
                    pPositionCtrl->SetWindowText(strText);
                }
            }
            else if (pMsg->message == WM_LBUTTONUP) {
                // 处理鼠标抬起事件
                // 设置鼠标为手形光标
                ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HAND));
                CString strText;
                strText.Format(_T("%s"), position.description.c_str());
                pDescriptionCtrl->SetWindowText(strText);
            }
            else if (pMsg->message == WM_MOUSEMOVE) {
                // 处理鼠标移动事件
                ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HAND));
            }
        }
    if (pMsg->message == WM_LBUTTONDOWN) {
        if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_AXIS_TEST_JOG_ADD)->m_hWnd) {
@@ -848,6 +1018,7 @@
            handleAxisOperation(AxisOperationType::JOG_SUB, false);
        }
    }
    }
    return CDialogEx::PreTranslateMessage(pMsg);
}
@@ -868,8 +1039,7 @@
    AdjustControls(dScaleX, dScaleY);
    // 动态调整各个 CBLLabel 的字体大小
    CBLLabel* pLabels[] = { &m_staticFLS, &m_staticDOG, &m_staticRLS, &m_staticReady, &m_staticBusy, &m_staticErr };
    for (auto pLabel : pLabels) {
    for (auto pLabel : m_pBlLabels) {
        AdjustLabelFont(*pLabel);
    }
@@ -1018,6 +1188,12 @@
    handleAxisOperation(AxisOperationType::STOP, false);
}
void CAxisSettingsDlg::OnBnClickedButtonAxisSev()
{
    // TODO: 在此添加控件通知处理程序代码
    handleAxisOperation(AxisOperationType::SEV_ON, !m_bSEV);
}
void CAxisSettingsDlg::OnSelchangeComboAxisName()
{
    // TODO: 在此添加控件通知处理程序代码
@@ -1074,45 +1250,45 @@
    //OPR 信号
    if (m_bFLS) {
        SetLabelColor(m_staticFLS, RGB(0, 255, 0));
        SetLabelColor(*m_pBlLabels[0], RGB(0, 255, 0));
    }
    else {
        SetLabelColor(m_staticFLS, RGB(0, 180, 0));
        SetLabelColor(*m_pBlLabels[0], RGB(0, 180, 0));
    }
    if (m_bDOG) {
        SetLabelColor(m_staticDOG, RGB(0, 255, 0));
        SetLabelColor(*m_pBlLabels[1], RGB(0, 255, 0));
    }
    else {
        SetLabelColor(m_staticDOG, RGB(0, 180, 0));
        SetLabelColor(*m_pBlLabels[1], RGB(0, 180, 0));
    }
    if (m_bRLS) {
        SetLabelColor(m_staticRLS, RGB(0, 255, 0));
        SetLabelColor(*m_pBlLabels[2], RGB(0, 255, 0));
    }
    else {
        SetLabelColor(m_staticRLS, RGB(0, 180, 0));
        SetLabelColor(*m_pBlLabels[2], RGB(0, 180, 0));
    }
    if (m_bReady) {
        SetLabelColor(m_staticReady, RGB(0, 255, 0));
        SetLabelColor(*m_pBlLabels[3], RGB(0, 255, 0));
    }
    else {
        SetLabelColor(m_staticReady, RGB(0, 180, 0));
        SetLabelColor(*m_pBlLabels[3], RGB(0, 180, 0));
    }
    if (m_bBusy) {
        SetLabelColor(m_staticBusy, RGB(0, 255, 0));
        SetLabelColor(*m_pBlLabels[4], RGB(0, 255, 0));
    }
    else {
        SetLabelColor(m_staticBusy, RGB(0, 180, 0));
        SetLabelColor(*m_pBlLabels[4], RGB(0, 180, 0));
    }
    if (m_bErr) {
        SetLabelColor(m_staticErr, RGB(255, 0, 0));
        SetLabelColor(*m_pBlLabels[5], RGB(255, 0, 0));
    }
    else {
        SetLabelColor(m_staticErr, RGB(0, 180, 0));
        SetLabelColor(*m_pBlLabels[5], RGB(0, 180, 0));
    }
    return 0;
@@ -1140,10 +1316,4 @@
    KillTimer(TIMER_READ_PLC_DATA);
    CDialogEx::OnClose();
}
void CAxisSettingsDlg::OnBnClickedButtonAxisSev()
{
    // TODO: 在此添加控件通知处理程序代码
    handleAxisOperation(AxisOperationType::SEV_ON, !m_bSEV);
}
SourceCode/Bond/BondEq/View/AxisSettingsDlg.h
@@ -45,10 +45,12 @@
    void AdjustLabelFont(CBLLabel& label);
    void SetLabelColor(CBLLabel& label, COLORREF color);
    void updatePageButtonStates();
    void HideEditCursor(int nCtrlID);
    int getCurrentSelectedAxisID();
    void initializeAxisIDCombo();
    void refreshAxisDetails(int nAxisId);
    void refreshPositionDetails(int nAxisId, int pageNumber);
    void UpdatePositionRange(PositionRange& position, int pageNumber, int pageSize, int currentIndex);
    void updateAxisSelection(int offset);
    void updateDataFromUI(int nAxisId);
    void switchToPage(int targetPage);
@@ -68,13 +70,17 @@
    // 配方名称
    CString m_strRecipeName;
    // 按下标识
    BOOL m_bJogAddPressed;
    BOOL m_bJogSubPressed;
    // 控件
    CBLLabel m_staticFLS, m_staticDOG, m_staticRLS, m_staticReady, m_staticBusy, m_staticErr;
    CBlButton* m_pBlBtns[9];
    CBLLabel* m_pBlLabels[6];
    CComboBox m_comboAxisNO;
    CStatic m_staticAxisNO, m_staticAxisDescription, m_staticStartAddress;
    CEdit m_editManualSpeed, m_editAutoSpeed, m_editAccelerationTime, m_editDecelerationTime, m_editJogDistance;
    
    CBlButton* m_pBlBtns[9];
    std::map<int, CRect> m_mapCtrlLayouts;
    std::map<int, CFont*> m_mapFonts;
@@ -115,12 +121,11 @@
    afx_msg void OnBnClickedButtonAxisAnchorPoint5();
    afx_msg void OnBnClickedButtonAxisTestOpr();
    afx_msg void OnBnClickedButtonAxisTestStop();
    afx_msg void OnBnClickedButtonAxisSev();
    afx_msg void OnSelchangeComboAxisName();
    afx_msg void OnBnClickedButtonAxisSave();
    afx_msg LRESULT OnUpdateDataToUI(WPARAM wParam, LPARAM lParam);
    afx_msg void OnTimer(UINT_PTR nIDEvent);
    afx_msg void OnClose();
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnBnClickedButtonAxisSev();
};
SourceCode/Bond/BondEq/View/IOMonitoringDlg.cpp
@@ -25,7 +25,7 @@
{
    m_nCurrentPage = 1;
    m_nTotalPages = 1;
    m_nRowsPerPage = 10;
    m_nRowsPerPage = 16;
    m_nCols = 6;
}
@@ -604,8 +604,8 @@
    }
    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();
SourceCode/Bond/BondEq/View/UserManagerDlg.cpp
@@ -119,7 +119,7 @@
    int nCurrNameRow = -1;
    std::vector<std::vector<std::string>> usersData = userManager.getUsers();
    if (!usersData.empty()) {
        m_gridUserManager.SetRowCount(usersData.size() + 1);
        m_gridUserManager.SetRowCount((int)usersData.size() + 1);
        for (int i = 0; i < usersData.size(); i++) {
            int nRowIdx = i + 1;