LAPTOP-SNT8I5JK\Boounion
2025-06-21 0de0a72329a77fbf20bc299c542e435a6d47256b
Merge branch 'liuyang' into clh
已修改15个文件
381 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CLoadPort.cpp 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Model.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PortConfigurationDlg.cpp 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/PortConfigurationDlg.h 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeDeviceBindDlg.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeManager.cpp 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/RecipeManager.h 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoCommo.h 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/ServoDlg.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TopToolbar.cpp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/TopToolbar.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CLoadPort.cpp
@@ -1140,4 +1140,44 @@
        return 0;
    }
    int CLoadPort::testGenerateGlassListFromConfig(const SERVO::PortConfig& config)
    {
        char szBuffer[64];
        for (const auto& slot : config.vecSlot) {
            if (!slot.isEnabled) continue;
            int nSlotIndex = slot.nSlotID - 1;
            if (nSlotIndex < 0 || nSlotIndex >= SLOT_MAX) {
                continue;
            }
            m_slot[nSlotIndex].enable();
            if (!m_slot[nSlotIndex].isEnable()) continue;
            CJobDataS js;
            js.setCassetteSequenceNo(getNextCassetteSequenceNo());
            js.setJobSequenceNo(m_slot[nSlotIndex].getNo());
            sprintf_s(szBuffer, 64, "%05d%05d", js.getCassetteSequenceNo(), js.getJobSequenceNo());
            js.setJobType(1);
            js.setMaterialsType(config.nMaterialType);
            js.setLotId(config.strLotID.c_str());
            js.setProductId(config.strProductID.c_str());
            js.setOperationId(config.strOperationID.c_str());
            js.setGlass1Id(szBuffer);
            CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass();
            pGlass->addPath(m_nID, 0);
            pGlass->processEnd(m_nID, 0);
            pGlass->setID(szBuffer);
            pGlass->setType(static_cast<SERVO::MaterialsType>(config.nMaterialType));
            pGlass->setJobDataS(&js);
            m_slot[nSlotIndex].setContext(pGlass);
        }
        return 0;
    }
}
SourceCode/Bond/Servo/CLoadPort.h
@@ -56,6 +56,7 @@
        int getCassetteMappingState();
        int getCassetteStatus();
        int testGenerateGlassList(MaterialsType type);
        int testGenerateGlassListFromConfig(const SERVO::PortConfig& config);
    public:
        static std::string& getPortTypeDescription(PortType portType, std::string& strDescription);
SourceCode/Bond/Servo/Model.cpp
@@ -217,7 +217,7 @@
        // 安全格式化时间
        auto format_time = [](time_t t) -> std::string {
            if (t < 0 || t == _I64_MIN || t == _I64_MAX) {
            if (t <= 0 || t == _I64_MIN || t == _I64_MAX) {
                return "";
            }
SourceCode/Bond/Servo/PortConfigurationDlg.cpp
@@ -8,6 +8,8 @@
#include "NewCellTypes/GridCellCheck.h"
#include "NewCellTypes/GridCellCombo.h"
#include "NewCellTypes/GridCellNumeric.h"
#include "RecipeManager.h"
#include "ServoCommo.h"
// CPortConfigurationDlg 对话框
@@ -17,11 +19,70 @@
CPortConfigurationDlg::CPortConfigurationDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_PORT_CONFIGURATION, pParent)
{
    // 初始化成员变量
    m_pPort[0] = dynamic_cast<SERVO::CLoadPort*>(theApp.m_model.m_master.getEquipment(EQ_ID_LOADPORT1));
    m_pPort[1] = dynamic_cast<SERVO::CLoadPort*>(theApp.m_model.m_master.getEquipment(EQ_ID_LOADPORT2));
    m_pPort[2] = dynamic_cast<SERVO::CLoadPort*>(theApp.m_model.m_master.getEquipment(EQ_ID_LOADPORT3));
    m_pPort[3] = dynamic_cast<SERVO::CLoadPort*>(theApp.m_model.m_master.getEquipment(EQ_ID_LOADPORT4));
}
CPortConfigurationDlg::~CPortConfigurationDlg()
{
}
int CPortConfigurationDlg::GetLoadPortEqID(const std::string& strPortName)
{
    if (strPortName == "Port 1") return EQ_ID_LOADPORT1;
    if (strPortName == "Port 2") return EQ_ID_LOADPORT2;
    if (strPortName == "Port 3") return EQ_ID_LOADPORT3;
    if (strPortName == "Port 4") return EQ_ID_LOADPORT4;
    return -1; // 未知端口
}
void CPortConfigurationDlg::LoadPortConfigToUI(SERVO::CLoadPort* pPort)
{
    if (!pPort) {
        return;
    }
    SetDlgItemText(IDC_EDIT_LOTID, "");
    SetDlgItemText(IDC_EDIT_PRODUCTID, "");
    SetDlgItemText(IDC_EDIT_OPERATIONID, "");
    m_comboMaterialsType.SetCurSel(0);
    bool bJobInfoSet = false;
    for (int i = 0; i < SLOT_MAX; ++i) {
        SERVO::CSlot* pSlot = pPort->getSlot(i);
        if (!pSlot) {
            continue;
        }
        SERVO::CGlass* pGlass = dynamic_cast<SERVO::CGlass*>(pSlot->getContext());
        int nRow = i + 1;
        // 设置 Panel ID 和勾选框
        CGridCellCheck* pCheck = static_cast<CGridCellCheck*>(m_wndGrid.GetCell(nRow, 1));
        if (pCheck && pGlass) {
            pCheck->SetCheck(pSlot->isEnable() ? TRUE : FALSE);
            pCheck->SetText(pGlass ? pGlass->getID().c_str() : _T(""));
        }
        else {
            pCheck->SetCheck(FALSE);
            pCheck->SetText(_T(""));
        }
        // 回填 Job 信息(只取第一个有效 Glass)
        if (!bJobInfoSet && pGlass) {
            SERVO::CJobDataS* pJS = pGlass->getJobDataS();
            if (pJS) {
                SetDlgItemText(IDC_EDIT_LOTID, CString(pJS->getLotId().c_str()));
                SetDlgItemText(IDC_EDIT_PRODUCTID, CString(pJS->getProductId().c_str()));
                SetDlgItemText(IDC_EDIT_OPERATIONID, CString(pJS->getOperationId().c_str()));
                m_comboMaterialsType.SetCurSel(pJS->getMaterialsType() - 1);
                bJobInfoSet = true;
            }
        }
    }
}
void CPortConfigurationDlg::InitGrid()
@@ -30,9 +91,9 @@
        return;
    }
    const int nCols = 3;
    const int nCols = 2;
    const int nFixRows = 1;
    const int nRows = 9;
    const int nRows = SLOT_MAX + 1; // 存在表头,所以 +1
    int nColIdx = 0;
    m_wndGrid.DeleteAllItems();
@@ -53,10 +114,6 @@
    // 设置列宽
    m_wndGrid.SetColumnWidth(nColIdx, 50);
    m_wndGrid.SetItemText(0, nColIdx++, _T("Slot ID"));
    m_wndGrid.SetColumnWidth(nColIdx, 150);
    m_wndGrid.SetItemText(0, nColIdx++, _T("EQ Recipe"));
    m_wndGrid.SetColumnWidth(nColIdx, 150);
    m_wndGrid.SetItemText(0, nColIdx++, _T("Panel ID"));
    m_wndGrid.SetColumnWidth(nColIdx, 60);
    m_wndGrid.SetItemText(0, nColIdx++, _T("启用"));
@@ -98,20 +155,9 @@
        m_wndGrid.SetItemText(i, 0, strIndex);
        m_wndGrid.SetItemState(i, 0, GVIS_READONLY);
        // EQ Recipe - ComboBox
        //if (m_wndGrid.SetCellType(i, 1, RUNTIME_CLASS(CGridCellCombo))) {
        //    CGridCellCombo* pCell = static_cast<CGridCellCombo*>(m_wndGrid.GetCell(i, 1));
        //    pCell->SetOptions(recipeOptions);
        //    pCell->SetStyle(CBS_DROPDOWNLIST);
        //}
        //m_wndGrid.SetItemText(i, 1, recipeOptions[0]);
        // Panel ID - 可编辑
        m_wndGrid.SetItemText(i, 1, _T(""));
        // Checkbox
        m_wndGrid.SetCellType(i, 2, RUNTIME_CLASS(CGridCellCheck));
        CGridCellCheck* pCheck = static_cast<CGridCellCheck*>(m_wndGrid.GetCell(i, 2));
        m_wndGrid.SetCellType(i, 1, RUNTIME_CLASS(CGridCellCheck));
        CGridCellCheck* pCheck = static_cast<CGridCellCheck*>(m_wndGrid.GetCell(i, 1));
        if (pCheck) {
            pCheck->SetCheck(FALSE);
        }
@@ -123,12 +169,17 @@
void CPortConfigurationDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_GRID_PANEL_RECIPE, m_wndGrid);
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_COMBO_PORT, m_comboPort);
    DDX_Control(pDX, IDC_COMBO_RECIPE, m_comboRecipe);
    DDX_Control(pDX, IDC_COMBO_MATERIALS_TYPE, m_comboMaterialsType);
}
BEGIN_MESSAGE_MAP(CPortConfigurationDlg, CDialogEx)
    ON_CBN_SELCHANGE(IDC_COMBO_PORT, &CPortConfigurationDlg::OnSelchangeComboPort)
    ON_BN_CLICKED(IDC_BUTTON_APPLY, &CPortConfigurationDlg::OnBnClickedButtonApply)
END_MESSAGE_MAP()
@@ -139,8 +190,134 @@
    CDialogEx::OnInitDialog();
    // TODO:  在此添加额外的初始化
    // 初始化端口下拉框内容
    CString ports[] = { _T("Port 1"), _T("Port 2"), _T("Port 3"), _T("Port 4") };
    for (const auto& item : ports) {
        m_comboPort.AddString(item);
    }
    m_comboPort.SetCurSel(0); // 默认选择第一个端口
    // 初始化配方下拉框内容
    std::vector<std::string> vecRecipe = RecipeManager::getInstance().getAllPPID();
    for (const auto& recipe : vecRecipe) {
        m_comboRecipe.AddString(CString(recipe.c_str()));
    }
    m_comboRecipe.SetCurSel(0); // 默认选择第一个配方
    // 初始化物料类型下拉框内容
    CString materialTypes[] = { _T("G1"), _T("G2"), _T("G1+G2") };
    for (const auto& item : materialTypes) {
        m_comboMaterialsType.AddString(item);
    }
    m_comboMaterialsType.SetCurSel(0);  // 默认选择第一个物料类型
    InitGrid();
    LoadPortConfigToUI(m_pPort[0]);     // 默认加载第一个端口的配置
    // 设置对话框标题
    SetWindowText(_T("Port Configuration"));
    return TRUE;  // return TRUE unless you set the focus to a control
    // 异常: OCX 属性页应返回 FALSE
}
void CPortConfigurationDlg::OnSelchangeComboPort()
{
    // TODO: 在此添加控件通知处理程序代码
    int selPort = m_comboPort.GetCurSel();
    if (selPort < 0 || selPort >= 4) {
        return; // 无效选择
    }
    // 加载选中端口的配置到 UI
    LoadPortConfigToUI(m_pPort[selPort]);
}
void CPortConfigurationDlg::OnBnClickedButtonApply()
{
    // TODO: 在此添加控件通知处理程序代码
    SERVO::PortConfig config;
    // 获取 Port 名称
    int selPort = m_comboPort.GetCurSel();
    if (selPort != CB_ERR) {
        CString str;
        m_comboPort.GetLBText(selPort, str);
        config.strPortName = CT2A(str.GetString());
    }
    // 获取 Recipe 名称
    int selRecipe = m_comboRecipe.GetCurSel();
    if (selRecipe != CB_ERR) {
        CString str;
        m_comboRecipe.GetLBText(selRecipe, str);
        config.strRecipe = CT2A(str.GetString());
    }
    // 获取 Material Type 索引(索引从 0 开始,对应枚举从 1 开始)
    int selMaterial = m_comboMaterialsType.GetCurSel();
    if (selMaterial != CB_ERR) {
        config.nMaterialType = selMaterial + 1;
    }
    else {
        AfxMessageBox(_T("Please select a material type!"));
        return;
    }
    // 获取 Lot ID / Product ID / Operation ID
    CString strText;
    GetDlgItemText(IDC_EDIT_LOTID, strText);
    config.strLotID = CT2A(strText.GetString());
    if (config.strLotID.empty()) {
        AfxMessageBox(_T("Lot ID cannot be empty!"));
        return;
    }
    GetDlgItemText(IDC_EDIT_PRODUCTID, strText);
    config.strProductID = CT2A(strText.GetString());
    if (config.strProductID.empty()) {
        AfxMessageBox(_T("Product ID cannot be empty!"));
        return;
    }
    GetDlgItemText(IDC_EDIT_OPERATIONID, strText);
    config.strOperationID = CT2A(strText.GetString());
    if (config.strOperationID.empty()) {
        AfxMessageBox(_T("Operation ID cannot be empty!"));
        return;
    }
    // 获取 Grid 表格中 Slot 状态(第1~8行)
    for (int i = 1; i <= 8; ++i) {
        SERVO::SlotConfig slot;
        slot.nSlotID = i;
        CGridCellCheck* pCheck = static_cast<CGridCellCheck*>(m_wndGrid.GetCell(i, 1));
        if (pCheck) {
            slot.isEnabled = pCheck->GetCheck();
        }
        config.vecSlot.push_back(slot);
    }
    int nEqID = GetLoadPortEqID(config.strPortName);
    if (nEqID < 0) {
        AfxMessageBox(_T("未知的端口名称!"));
        return;
    }
    SERVO::CLoadPort* pPort = dynamic_cast<SERVO::CLoadPort*>(theApp.m_model.m_master.getEquipment(nEqID));
    if (!pPort) {
        AfxMessageBox(_T("找不到对应的 LoadPort 设备!"));
        return;
    }
    // 应用配置(例如测试生成玻璃)
    if (pPort->testGenerateGlassListFromConfig(config) < 0) {
        AfxMessageBox(_T("Failed to generate glass list from configuration!"));
        return;
    }
    OnOK();
}
SourceCode/Bond/Servo/PortConfigurationDlg.h
@@ -1,6 +1,7 @@
#pragma once
#include "afxdialogex.h"
#include "GridCtrl.h"
#include "CLoadPort.h"
// CPortConfigurationDlg 对话框
@@ -20,11 +21,20 @@
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
    virtual BOOL OnInitDialog();
    afx_msg void OnSelchangeComboPort();
    afx_msg void OnBnClickedButtonApply();
    DECLARE_MESSAGE_MAP()
private:
    CGridCtrl m_wndGrid;
    int GetLoadPortEqID(const std::string& strPortName);
    void LoadPortConfigToUI(SERVO::CLoadPort* pPort);
    void InitGrid();
    void FillGrid();
    SERVO::CLoadPort* m_pPort[4];
    CGridCtrl m_wndGrid;
    CComboBox m_comboPort;
    CComboBox m_comboRecipe;
    CComboBox m_comboMaterialsType;
};
SourceCode/Bond/Servo/RecipeDeviceBindDlg.cpp
@@ -6,6 +6,9 @@
#include "afxdialogex.h"
#include "RecipeDeviceBindDlg.h"
#define IDC_EDIT_DEVICEID_BASE     3000
#define IDC_EDIT_DEVICENAME_BASE   3050
#define IDC_COMBO_RECIPEID_BASE    3100
// CRecipeDeviceBindDlg 对话框
@@ -32,3 +35,39 @@
// CRecipeDeviceBindDlg 消息处理程序
BOOL CRecipeDeviceBindDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // TODO:  在此添加额外的初始化
    // 设置固定大小(例如 600x400)
    SetWindowPos(nullptr, 0, 0, 600, 400, SWP_NOMOVE | SWP_NOZORDER);
    // 创建控件
    const int totalControlWidth = 340;
    CRect clientRect;
    GetClientRect(&clientRect);
    int xStart = (clientRect.Width() - totalControlWidth) / 2;
    const int nRowCount = 8;
    const int nRowHeight = 30;
    const int yStart = 30; // 顶部起始高度
    for (int i = 0; i < nRowCount; ++i)
    {
        int y = yStart + i * nRowHeight;
        CEdit* pEditID = new CEdit();
        pEditID->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(xStart, y, xStart + 100, y + 25), this, IDC_EDIT_DEVICEID_BASE + i);
        CEdit* pEditName = new CEdit();
        pEditName->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(xStart + 110, y, xStart + 210, y + 25), this, IDC_EDIT_DEVICENAME_BASE + i);
        CComboBox* pCombo = new CComboBox();
        pCombo->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(xStart + 220, y, xStart + 340, y + 300), this, IDC_COMBO_RECIPEID_BASE + i);
    }
    return TRUE;  // return TRUE unless you set the focus to a control
    // 异常: OCX 属性页应返回 FALSE
}
SourceCode/Bond/Servo/RecipeDeviceBindDlg.h
@@ -19,6 +19,15 @@
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
    virtual BOOL OnInitDialog();
    DECLARE_MESSAGE_MAP()
private:
    struct DeviceWidget {
        CEdit editDeviceID;
        CEdit editDeviceName;
        CComboBox comboRecipeID;
    };
    std::vector<DeviceWidget> m_vecDevices;
};
SourceCode/Bond/Servo/RecipeManager.cpp
@@ -238,6 +238,25 @@
    return recipes;
}
std::vector<std::string> RecipeManager::getAllPPID() const {
    std::vector<std::string> vecPPID;
    if (!m_pDB) {
        return vecPPID;
    }
    const std::string query = "SELECT ppid FROM recipes ORDER BY ppid;";
    auto result = m_pDB->fetchResults(query);
    for (const auto& row : result) {
        if (!row.empty()) {
            vecPPID.push_back(row[0]);
        }
    }
    return vecPPID;
}
RecipeInfo RecipeManager::getRecipeByPPID(const std::string& ppid) {
    RecipeInfo info;
    auto rows = m_pDB->fetchResults("SELECT ppid, description, create_time FROM recipes WHERE ppid = '" + ppid + "';");
SourceCode/Bond/Servo/RecipeManager.h
@@ -58,6 +58,9 @@
    // 查询所有配方
    std::vector<RecipeInfo> getAllRecipes();
    // 获取所有 PPID
    std::vector<std::string> getAllPPID() const;
    // 按 PPID 查询配方
    RecipeInfo getRecipeByPPID(const std::string& ppid);
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/ServoCommo.h
@@ -1,5 +1,6 @@
#pragma once
#include <string>
#include <vector>
namespace SERVO {
#define BLOCK_BUFFER_MAX            1024
@@ -165,6 +166,22 @@
        Error
    };
    /* Port Status */
    struct SlotConfig {
        int nSlotID = 0;
        bool isEnabled = false;
    };
    struct PortConfig {
        int nMaterialType;               // 物料类型,1: G1, 2: G2, 3: G1+G2
        std::string strPortName;       // 例如 "Port 1"
        std::string strRecipe;         // 例如 "P1001"
        std::string strLotID;
        std::string strProductID;
        std::string strOperationID;
        std::vector<SlotConfig> vecSlot;
    };
    /* EQ Data changed code */
#define EDCC_FETCHOUT_JOB                1000    /* ȡƬ */
#define EDCC_STORED_JOB                    1001    /* 放片 */
SourceCode/Bond/Servo/ServoDlg.cpp
@@ -21,6 +21,7 @@
#include "SystemLogManagerDlg.h"
#include "UserManager.h"
#include "SystemLogManager.h"
#include "PortConfigurationDlg.h"
#ifdef _DEBUG
@@ -885,6 +886,10 @@
            m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE);
        }
    }
    else if (id == IDC_BUTTON_PORT_CONFIG) {
        CPortConfigurationDlg dlg;
        dlg.DoModal();
    }
    else if (id == IDC_BUTTON_ROBOT) {
        theApp.m_model.getMaster().clearError();
        SERVO::CEFEM* pEFEM = (SERVO::CEFEM*)theApp.m_model.getMaster().getEquipment(EQ_ID_EFEM);
SourceCode/Bond/Servo/TopToolbar.cpp
@@ -30,6 +30,7 @@
    DDX_Control(pDX, IDC_BUTTON_STOP, m_btnStop);
    DDX_Control(pDX, IDC_BUTTON_ALARM, m_btnAlarm);
    DDX_Control(pDX, IDC_BUTTON_SETTINGS, m_btnSettings);
    DDX_Control(pDX, IDC_BUTTON_PORT_CONFIG, m_btnPortConfig);
    DDX_Control(pDX, IDC_BUTTON_ROBOT, m_btnRobot);
    DDX_Control(pDX, IDC_BUTTON_OPERATOR, m_btnOperator);
}
@@ -55,6 +56,7 @@
    InitBtn(m_btnAlarm, "Alarm_o_32.ico", "Alarm_gray_32.ico");
    InitBtn(m_btnSettings, "Settings_High_32.ico", "Settings_Gray_32.ico");
    InitBtn(m_btnRobot, "Robot_High_32.ico", "Robot_Gray_32.ico");
    InitBtn(m_btnPortConfig, "PortConfig_High_32.ico", "PortConfig_Gray_32.ico");
    InitBtn(m_btnOperator, "Operator_High_32.ico", "Operator_Gray_32.ico");
    HMENU hMenu = LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCEA(IDR_MENU_OPEATOR));
    m_btnOperator.SetMenu(hMenu);
@@ -133,6 +135,11 @@
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_BUTTON_PORT_CONFIG);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
    x += 2;
    pItem = GetDlgItem(IDC_BUTTON_ROBOT);
    pItem->MoveWindow(x, y, BTN_WIDTH, nBthHeight);
    x += BTN_WIDTH;
@@ -186,6 +193,7 @@
    case IDC_BUTTON_STOP:
    case IDC_BUTTON_ALARM:
    case IDC_BUTTON_SETTINGS:
    case IDC_BUTTON_PORT_CONFIG:
    case IDC_BUTTON_ROBOT:
        GetParent()->SendMessage(ID_MSG_TOOLBAR_BTN_CLICKED, 0, LOWORD(wParam));
        break;
SourceCode/Bond/Servo/TopToolbar.h
@@ -34,6 +34,7 @@
    CBlButton m_btnStop;
    CBlButton m_btnAlarm;
    CBlButton m_btnSettings;
    CBlButton m_btnPortConfig;
    CBlButton m_btnRobot;
    CBlButton m_btnOperator;
SourceCode/Bond/Servo/resource.h
Binary files differ