mrDarker
2025-05-22 5cf5e464a5891c8eb62aafadfce0d204fdc79b02
1. 添加机械臂快速测试界面
已添加2个文件
已修改6个文件
444 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CPageGraph2.cpp 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp 353 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CRobotCmdTestDlg.h 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.cpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.rc 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/Servo.vcxproj.filters 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/resource.h 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGraph2.cpp
@@ -13,6 +13,7 @@
#include "CPageCassetteCtrlCmd.h"
#include "CJobDataB.h"
#include "CRobotCmdContainerDlg.h"
#include "CRobotCmdTestDlg.h"
// CPageGraph2 å¯¹è¯æ¡†
@@ -271,13 +272,17 @@
                //cmds[1].subCmd = 10;
                //pEFEM->robotCmds(cmds, 2);
                CRobotCmdContainerDlg dlg;
                if (dlg.DoModal() == IDOK) {
                    std::vector<SERVO::ROBOT_CMD_PARAM>& cmds = dlg.GetResultCmds();
                    if (!cmds.empty()) {
                        pEFEM->robotCmds(cmds.data(), (int)cmds.size());
                    }
                }
                //CRobotCmdContainerDlg dlg;
                //if (dlg.DoModal() == IDOK) {
                //    std::vector<SERVO::ROBOT_CMD_PARAM>& cmds = dlg.GetResultCmds();
                //    if (!cmds.empty()) {
                //        pEFEM->robotCmds(cmds.data(), (int)cmds.size());
                //    }
                //}
                CRobotCmdTestDlg dlg;
                dlg.SetEFEM(pEFEM);
                dlg.DoModal();
            }
SourceCode/Bond/Servo/CRobotCmdTestDlg.cpp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,353 @@
// CRobotCmdTestDlg.cpp: å®žçŽ°æ–‡ä»¶
//
#include "stdafx.h"
#include "Servo.h"
#include "afxdialogex.h"
#include "CRobotCmdTestDlg.h"
// æ—¥å¿—颜色宏定义
#define LOG_COLOR_NORMAL   RGB(0, 0, 0)         // æ™®é€šï¼šé»‘色
#define LOG_COLOR_SUCCESS  RGB(0, 128, 0)       // æˆåŠŸï¼šç»¿è‰²
#define LOG_COLOR_ERROR    RGB(255, 0, 0)       // é”™è¯¯ï¼šçº¢è‰²
#define LOG_COLOR_WARNING  RGB(255, 165, 0)     // è­¦å‘Šï¼šæ©™è‰²
#define LOG_COLOR_TIME     RGB(0, 0, 255)       // æ—¶é—´æˆ³ï¼šè“è‰²
// å¿«æ·å‘½ä»¤æ˜ å°„表
std::map<CString, QuickCmdFieldMask> g_quickCmdMap = {
    {_T("SendHome"),             {false, false, false, false, false}},
    {_T("SendTransfer"),         {true,  true,  true,  true,  true }},
    {_T("SendMoveToGet"),        {true,  true,  true,  false, false}},
    {_T("SendMoveToPut"),        {true,  false, false, true,  true }},
    {_T("SendGet"),              {true,  true,  true,  false, false}},
    {_T("SendPut"),              {true,  false, false, true,  true }},
    {_T("SendExchange"),         {true,  true,  true,  true,  true }},
    {_T("SendCommandClear"),     {false, false, false, false, false}},
    {_T("SendBatchGet"),         {true,  true,  true,  false, false}},
    {_T("SendBatchPut"),         {true,  false, false, true,  true }},
    {_T("SendMoveToGetAndHome"), {true,  true,  true,  false, false}},
    {_T("SendMoveToPutAndHome"), {true,  false, false, true,  true }},
    {_T("SendTransferAndHome"),  {true,  true,  true,  true,  true }},
    {_T("SendGetAndPut"),        {true,  true,  true,  true,  true }},
    {_T("SendPutAndHome"),       {true,  false, false, true,  true }}
};
// CRobotCmdTestDlg å¯¹è¯æ¡†
IMPLEMENT_DYNAMIC(CRobotCmdTestDlg, CDialogEx)
CRobotCmdTestDlg::CRobotCmdTestDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_DIALOG_ROBOT_CMD_TEST, pParent)
{
    m_pEFEM = nullptr;
}
CRobotCmdTestDlg::~CRobotCmdTestDlg()
{
}
void CRobotCmdTestDlg::SetEFEM(SERVO::CEFEM* pEFEM)
{
    m_pEFEM = pEFEM;
}
void CRobotCmdTestDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_COMBO_CMD_TYPE, m_comboCmdType);
    DDX_Control(pDX, IDC_COMBO_ARM_NO, m_comboArmNo);
    DDX_Control(pDX, IDC_COMBO_GET_POS, m_comboGetPos);
    DDX_Control(pDX, IDC_COMBO_GET_SLOT, m_comboGetSlot);
    DDX_Control(pDX, IDC_COMBO_PUT_POS, m_comboPutPos);
    DDX_Control(pDX, IDC_COMBO_PUT_SLOT, m_comboPutSlot);
    DDX_Control(pDX, IDC_RICHEDIT_LOG, m_editLog);
}
BEGIN_MESSAGE_MAP(CRobotCmdTestDlg, CDialogEx)
    ON_CBN_SELCHANGE(IDC_COMBO_CMD_TYPE, &CRobotCmdTestDlg::OnCbnSelchangeComboCmdType)
    ON_BN_CLICKED(IDC_BUTTON_EXECUTE, &CRobotCmdTestDlg::OnBnClickedButtonExecute)
END_MESSAGE_MAP()
// CRobotCmdTestDlg æ¶ˆæ¯å¤„理程序
BOOL CRobotCmdTestDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // TODO:  åœ¨æ­¤æ·»åŠ é¢å¤–çš„åˆå§‹åŒ–
    // åˆå§‹åŒ–命令组合列表
    for (const auto& pair : g_quickCmdMap) {
        m_comboCmdType.AddString(pair.first);
    }
    m_comboCmdType.SetCurSel(0);
    // åˆå§‹åŒ–命令输入控件
    if (!g_quickCmdMap.empty()) {
        UpdateCommandInputUI(g_quickCmdMap.begin()->first);
    }
    // åˆå§‹åŒ– Arm No(1:Arm#1,2:Arm#2)
    m_comboArmNo.AddString(_T("1"));
    m_comboArmNo.AddString(_T("2"));
    m_comboArmNo.SetCurSel(0);
    // ç¤ºä¾‹è®¾å¤‡åç§°åˆ—表
    CStringList eqNameList;
    eqNameList.AddTail(_T("PORT 1"));                // 1 1 UNIT
    eqNameList.AddTail(_T("PORT 2"));                // 2 1 UNIT
    eqNameList.AddTail(_T("PORT 3"));                // 3 1 UNIT
    eqNameList.AddTail(_T("PORT 4"));                // 4 1 UNIT
    eqNameList.AddTail(_T("RB1"));                    // 5 1 UNIT
    eqNameList.AddTail(_T("RB2"));                    // 6 1 UNIT
    eqNameList.AddTail(_T("ALIGN"));                // 7 1 UNIT
    eqNameList.AddTail(_T("FLIP"));                    // 8 1 UNIT
    eqNameList.AddTail(_T("VAC BAKE"));                // 9 2 UNIT
    eqNameList.AddTail(_T("BONDER1"));                // 10 2 UNIT
    eqNameList.AddTail(_T("BONDER2"));                // 11 2 UNIT
    eqNameList.AddTail(_T("POST BAKE(COOLING)"));    // 12 4 UNIT
    eqNameList.AddTail(_T("MEASUREMENT"));            // 13 1 UNIT
    for (POSITION pos = eqNameList.GetHeadPosition(); pos != NULL;) {
        CString item = eqNameList.GetNext(pos);
        m_comboGetPos.AddString(item);
        m_comboPutPos.AddString(item);
    }
    m_comboGetPos.SetCurSel(0);
    m_comboPutPos.SetCurSel(0);
    // åˆå§‹åŒ– Slot(默认从 1 åˆ° 25)
    for (int i = 1; i < 26; ++i) {
        CString str;
        str.Format(_T("%d"), i);
        m_comboGetSlot.AddString(str);
        m_comboPutSlot.AddString(str);
    }
    m_comboGetSlot.SetCurSel(0);
    m_comboPutSlot.SetCurSel(0);
    // å¿«æ·å‘½ä»¤æ‰§è¡Œæ˜ å°„表
    m_mapCmdExec = {
        {_T("SendHome"), [this](int seq, int, int, int, int, int) {
            return m_pEFEM->SendHome(seq);
        }},
        {_T("SendTransfer"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
            return m_pEFEM->SendTransfer(seq, armNo, getPos, putPos, getSlot, putSlot);
        }},
        {_T("SendMoveToGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
            return m_pEFEM->SendMoveToGet(seq, armNo, pos, slot);
        }},
        {_T("SendMoveToPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendMoveToPut(seq, armNo, pos, slot);
        }},
        {_T("SendGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
            return m_pEFEM->SendGet(seq, armNo, pos, slot);
        }},
        {_T("SendPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendPut(seq, armNo, pos, slot);
        }},
        {_T("SendExchange"), [this](int seq, int armNo, int pos, int, int getSlot, int putSlot) {
            return m_pEFEM->SendExchange(seq, armNo, pos, getSlot, putSlot);
        }},
        {_T("SendCommandClear"), [this](int seq, int, int, int, int, int) {
            return m_pEFEM->SendCommandClear(seq);
        }},
        {_T("SendBatchGet"), [this](int seq, int armNo, int pos, int, int slot, int) {
            return m_pEFEM->SendBatchGet(seq, pos, slot);
        }},
        {_T("SendBatchPut"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendBatchPut(seq, pos, slot);
        }},
        {_T("SendMoveToGetAndHome"), [this](int seq, int armNo, int pos, int, int slot, int) {
            return m_pEFEM->SendMoveToGetAndHome(seq, armNo, pos, slot);
        }},
        {_T("SendMoveToPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendMoveToPutAndHome(seq, armNo, pos, slot);
        }},
        {_T("SendTransferAndHome"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
            return m_pEFEM->SendTransferAndHome(seq, armNo, getPos, putPos, getSlot, putSlot);
        }},
        {_T("SendGetAndPut"), [this](int seq, int armNo, int getPos, int putPos, int getSlot, int putSlot) {
            return m_pEFEM->SendGetAndPut(seq, armNo, getPos, putPos, getSlot, putSlot);
        }},
        {_T("SendPutAndHome"), [this](int seq, int armNo, int, int pos, int, int slot) {
            return m_pEFEM->SendPutAndHome(seq, armNo, pos, slot);
        }}
    };
    // åˆå§‹åŒ–日志框
    AppendLogLineRichStyled(_T("准备就绪..."), LOG_COLOR_SUCCESS);
    return TRUE;  // return TRUE unless you set the focus to a control
    // å¼‚常: OCX å±žæ€§é¡µåº”返回 FALSE
}
void CRobotCmdTestDlg::UpdateCommandInputUI(const CString& cmdName)
{
    auto it = g_quickCmdMap.find(cmdName);
    if (it == g_quickCmdMap.end()) {
        return;
    }
    const QuickCmdFieldMask& mask = it->second;
    GetDlgItem(IDC_COMBO_ARM_NO)->EnableWindow(mask.useArm);
    GetDlgItem(IDC_COMBO_GET_POS)->EnableWindow(mask.useGetPos);
    GetDlgItem(IDC_COMBO_GET_SLOT)->EnableWindow(mask.useGetSlot);
    GetDlgItem(IDC_COMBO_PUT_POS)->EnableWindow(mask.usePutPos);
    GetDlgItem(IDC_COMBO_PUT_SLOT)->EnableWindow(mask.usePutSlot);
}
void CRobotCmdTestDlg::AppendLogLineBatchBegin()
{
    m_editLog.SetRedraw(FALSE);
    m_editLog.SetEventMask(0); // é˜²æ­¢è§¦å‘不必要的通知
}
void CRobotCmdTestDlg::AppendLogLineBatchEnd()
{
    m_editLog.SetRedraw(TRUE);
    m_editLog.Invalidate();  // å¼ºåˆ¶é‡ç»˜
    m_editLog.SetEventMask(ENM_CHANGE | ENM_SELCHANGE);
}
void CRobotCmdTestDlg::TrimRichEditLineLimit(int maxLines)
{
    int lineCount = m_editLog.GetLineCount();
    if (lineCount <= maxLines) {
        return;
    }
    // èŽ·å–å¤šä½™è¡Œçš„å­—ç¬¦æ•°èŒƒå›´
    int charIndex = m_editLog.LineIndex(maxLines);
    m_editLog.SetSel(0, charIndex); // é€‰ä¸­å¤šä½™å†…容
    m_editLog.ReplaceSel(_T(""));   // åˆ é™¤
}
void CRobotCmdTestDlg::AppendLogLineRichStyled(const CString& content, COLORREF color /*= RGB(0, 0, 0)*/)
{
    // æ—¶é—´æˆ³
    CString timestamp;
    CTime now = CTime::GetCurrentTime();
    timestamp.Format(_T("[%02d:%02d:%02d] "), now.GetHour(), now.GetMinute(), now.GetSecond());
    // æ’入点移到最后(也可以设为 0 è¡¨ç¤ºé¡¶éƒ¨ï¼‰
    m_editLog.SetSel(-1, -1);
    // æ’入时间(蓝色)
    CHARFORMAT2 cfTime = {};
    cfTime.cbSize = sizeof(cfTime);
    cfTime.dwMask = CFM_COLOR;
    cfTime.crTextColor = LOG_COLOR_TIME;
    m_editLog.SetSelectionCharFormat(cfTime);
    m_editLog.ReplaceSel(timestamp);
    // æ’入日志正文(传入颜色)
    CHARFORMAT2 cfMsg = {};
    cfMsg.cbSize = sizeof(cfMsg);
    cfMsg.dwMask = CFM_COLOR;
    cfMsg.crTextColor = color;
    m_editLog.SetSelectionCharFormat(cfMsg);
    m_editLog.ReplaceSel(content + _T("\r\n"));
    // é™åˆ¶æœ€å¤§è¡Œæ•°
    TrimRichEditLineLimit(100);
}
void CRobotCmdTestDlg::HighlightAllMatches(const CString& strSearch, COLORREF clrHighlight)
{
    if (strSearch.IsEmpty()) {
        return;
    }
    long nStart = 0;
    long nEnd = m_editLog.GetTextLength();
    CHARRANGE cr;
    FINDTEXTEX ft = { 0 };
    ft.chrg.cpMin = 0;
    ft.chrg.cpMax = nEnd;
    ft.lpstrText = strSearch.GetString();
    // é«˜äº®å‰ä¸æ¸…除全文颜色,避免历史多色混淆
    while (m_editLog.FindText(FR_DOWN, &ft) != -1) {
        m_editLog.SetSel(ft.chrgText.cpMin, ft.chrgText.cpMax);
        CHARFORMAT2 cf = {};
        cf.cbSize = sizeof(cf);
        cf.dwMask = CFM_COLOR;
        cf.crTextColor = clrHighlight;
        m_editLog.SetSelectionCharFormat(cf);
        // ä¸‹æ¬¡æœç´¢ä»ŽåŽé¢å¼€å§‹
        ft.chrg.cpMin = ft.chrgText.cpMax;
    }
    m_editLog.SetSel(-1, 0);
}
void CRobotCmdTestDlg::OnCbnSelchangeComboCmdType()
{
    int nSel = m_comboCmdType.GetCurSel();
    if (nSel < 0) {
        return;
    }
    CString str;
    m_comboCmdType.GetLBText(nSel, str);
    UpdateCommandInputUI(str);
    str.Format(_T("切换当前命令类型:%s"), str);
    AppendLogLineRichStyled(str, LOG_COLOR_NORMAL);
}
void CRobotCmdTestDlg::OnBnClickedButtonExecute()
{
    // TODO: åœ¨æ­¤æ·»åŠ æŽ§ä»¶é€šçŸ¥å¤„ç†ç¨‹åºä»£ç 
    int sel = m_comboCmdType.GetCurSel();
    if (sel == CB_ERR) {
        AppendLogLineRichStyled(_T("未选择命令类型"), LOG_COLOR_ERROR);
        return;
    }
    CString cmdName;
    m_comboCmdType.GetLBText(sel, cmdName);
    // å‚数收集
    int armNo = m_comboArmNo.GetCurSel() + 1;
    int getPos = m_comboGetPos.GetCurSel() + 1;
    int getSlot = m_comboGetSlot.GetCurSel() + 1;
    int putPos = m_comboPutPos.GetCurSel() + 1;
    int putSlot = m_comboPutSlot.GetCurSel() + 1;
    // æŸ¥æ‰¾å‡½æ•°å¹¶æ‰§è¡Œ
    auto it = m_mapCmdExec.find(cmdName);
    if (it != m_mapCmdExec.end() && nullptr != m_pEFEM) {
        int ret = it->second(1, armNo, getPos, getSlot, putPos, putSlot);
        CString log;
        if (ret == 0) {
            log.Format(_T("执行命令 %s æˆåŠŸ"), cmdName.GetString());
            AppendLogLineRichStyled(log, LOG_COLOR_SUCCESS);
        }
        else {
            log.Format(_T("执行命令 %s å‚数错误"), cmdName.GetString());
            AppendLogLineRichStyled(log, LOG_COLOR_ERROR);
        }
    }
    else {
        CString log;
        log.Format(_T("命令 %s ä¸å­˜åœ¨æˆ– EFEM æœªåˆå§‹åŒ–"), cmdName.GetString());
        AppendLogLineRichStyled(log, LOG_COLOR_ERROR);
    }
}
SourceCode/Bond/Servo/CRobotCmdTestDlg.h
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
#pragma once
#include "afxdialogex.h"
#include <afxrich.h>
// å®šä¹‰å‘½ä»¤å‡½æ•°æŒ‡é’ˆç±»åž‹ï¼ˆseq, armNo, getPos, getSlot, putPos, putSlot)
using CmdFunc = std::function<int(int, int, int, int, int, int)>;
// è¾“入控件状态
struct QuickCmdFieldMask {
    bool useArm = false;
    bool useGetPos = false;
    bool useGetSlot = false;
    bool usePutPos = false;
    bool usePutSlot = false;
};
// CRobotCmdTestDlg å¯¹è¯æ¡†
class CRobotCmdTestDlg : public CDialogEx
{
    DECLARE_DYNAMIC(CRobotCmdTestDlg)
public:
    CRobotCmdTestDlg(CWnd* pParent = nullptr);   // æ ‡å‡†æž„造函数
    virtual ~CRobotCmdTestDlg();
    // è®¾ç½® EFEM æŒ‡é’ˆ
    void SetEFEM(SERVO::CEFEM* pEFEM);
// å¯¹è¯æ¡†æ•°æ®
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_DIALOG_ROBOT_CMD_TEST };
#endif
protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV æ”¯æŒ
    virtual BOOL OnInitDialog();
    afx_msg void OnCbnSelchangeComboCmdType();
    afx_msg void OnBnClickedButtonExecute();
    DECLARE_MESSAGE_MAP()
private:
    void UpdateCommandInputUI(const CString& cmdName);
    void AppendLogLineBatchBegin();
    void AppendLogLineBatchEnd();
    void TrimRichEditLineLimit(int maxLines = 100);
    void AppendLogLineRichStyled(const CString& content, COLORREF color = RGB(0, 0, 0));
    void HighlightAllMatches(const CString& strSearch, COLORREF clrHighlight = RGB(255, 165, 0));
    // æŽ§ä»¶
    CComboBox m_comboCmdType;
    CComboBox m_comboArmNo;
    CComboBox m_comboGetPos;
    CComboBox m_comboGetSlot;
    CComboBox m_comboPutPos;
    CComboBox m_comboPutSlot;
    CRichEditCtrl m_editLog;
    // å¿«æ·å‘½ä»¤æ˜ å°„表
    SERVO::CEFEM* m_pEFEM;
    std::map<CString, CmdFunc> m_mapCmdExec;
};
SourceCode/Bond/Servo/Servo.cpp
@@ -52,7 +52,7 @@
BOOL CServoApp::InitInstance()
{
    // å¦‚果一个运行在 Windows XP ä¸Šçš„应用程序清单指定要
    // TODO: è°ƒç”¨ AfxInitRichEdit2() ä»¥åˆå§‹åŒ– richedit2 åº“。\n"    // å¦‚果一个运行在 Windows XP ä¸Šçš„应用程序清单指定要
    // ä½¿ç”¨ ComCtl32.dll ç‰ˆæœ¬ 6 æˆ–更高版本来启用可视化方式,
    //则需要 InitCommonControlsEx()。  å¦åˆ™ï¼Œå°†æ— æ³•创建窗口。
    INITCOMMONCONTROLSEX InitCtrls;
@@ -113,6 +113,10 @@
    InitGDIPlus();
    // åˆå§‹åŒ– MFC RichEdit æŽ§ä»¶
    AfxInitRichEdit2();
    // åˆå§‹åŒ–报警管理器
    try {
        if (!AlarmManager::getInstance().initAlarmTable()) {
SourceCode/Bond/Servo/Servo.rc
Binary files differ
SourceCode/Bond/Servo/Servo.vcxproj
@@ -201,6 +201,7 @@
    <ClInclude Include="CEquipmentPage3.h" />
    <ClInclude Include="CGlassPool.h" />
    <ClInclude Include="CRobotCmdContainerDlg.h" />
    <ClInclude Include="CRobotCmdTestDlg.h" />
    <ClInclude Include="PageRecipe.h" />
    <ClInclude Include="CDoubleGlass.h" />
    <ClInclude Include="CProcessData.h" />
@@ -302,6 +303,7 @@
    <ClCompile Include="CEquipmentPage3.cpp" />
    <ClCompile Include="CGlassPool.cpp" />
    <ClCompile Include="CRobotCmdContainerDlg.cpp" />
    <ClCompile Include="CRobotCmdTestDlg.cpp" />
    <ClCompile Include="PageRecipe.cpp" />
    <ClCompile Include="CDoubleGlass.cpp" />
    <ClCompile Include="CProcessData.cpp" />
SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -107,6 +107,7 @@
    <ClCompile Include="CEquipmentPage3.cpp" />
    <ClCompile Include="PageRobotCmd.cpp" />
    <ClCompile Include="CRobotCmdContainerDlg.cpp" />
    <ClCompile Include="CRobotCmdTestDlg.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="AlarmManager.h" />
@@ -212,6 +213,7 @@
    <ClInclude Include="CEquipmentPage3.h" />
    <ClInclude Include="PageRobotCmd.h" />
    <ClInclude Include="CRobotCmdContainerDlg.h" />
    <ClInclude Include="CRobotCmdTestDlg.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="Servo.rc" />
SourceCode/Bond/Servo/resource.h
Binary files differ