// 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);
|
}
|
}
|