// CProcessDataListDlg.cpp: 实现文件
|
//
|
|
#include "stdafx.h"
|
#include "Servo.h"
|
#include "CProcessDataListDlg.h"
|
#include "afxdialogex.h"
|
|
namespace {
|
static const UINT IDC_CHECK_SHOW_ARM_STEPS = 0x5001;
|
static const UINT IDC_TAB_UNIFIED = 0x5002;
|
}
|
|
// CProcessDataListDlg 对话框
|
|
IMPLEMENT_DYNAMIC(CProcessDataListDlg, CDialogEx)
|
|
CProcessDataListDlg::CProcessDataListDlg(CWnd* pParent /*=nullptr*/)
|
: CDialogEx(IDD_DIALOG_PROCESS_DATA_LIST, pParent)
|
{
|
|
}
|
|
CProcessDataListDlg::~CProcessDataListDlg()
|
{
|
}
|
|
void CProcessDataListDlg::DoDataExchange(CDataExchange* pDX)
|
{
|
CDialogEx::DoDataExchange(pDX);
|
DDX_Control(pDX, IDC_LIST_RECIPE_PARAM, m_listCtrl);
|
}
|
|
|
BEGIN_MESSAGE_MAP(CProcessDataListDlg, CDialogEx)
|
ON_BN_CLICKED(IDC_BUTTON1, &CProcessDataListDlg::OnBnClickedButton1)
|
ON_BN_CLICKED(IDC_CHECK_SHOW_ARM_STEPS, &CProcessDataListDlg::OnBnClickedCheckShowArm)
|
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB_UNIFIED, &CProcessDataListDlg::OnTcnSelchangeTabUnified)
|
END_MESSAGE_MAP()
|
|
|
// CProcessDataListDlg 消息处理程序
|
|
|
BOOL CProcessDataListDlg::OnInitDialog()
|
{
|
CDialogEx::OnInitDialog();
|
|
SetupListCtrlStyle();
|
SetWindowText(_T("Glass数据详情"));
|
LoadArmStepOption();
|
InitUnifiedLayout();
|
RenderUnifiedTab();
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
// 异常: OCX 属性页应返回 FALSE
|
}
|
|
void CProcessDataListDlg::SetupListCtrlStyle()
|
{
|
DWORD dwStyle = m_listCtrl.GetExtendedStyle();
|
dwStyle |= LVS_EX_FULLROWSELECT;
|
dwStyle |= LVS_EX_GRIDLINES;
|
dwStyle |= LVS_EX_DOUBLEBUFFER;
|
m_listCtrl.SetExtendedStyle(dwStyle);
|
|
HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1);
|
ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL);
|
}
|
|
void CProcessDataListDlg::setRawText(CString& strRawText)
|
{
|
m_strRawText = strRawText;
|
m_initialTab = 2;
|
}
|
|
void CProcessDataListDlg::setPathRows(const std::vector<PathRow>& rows)
|
{
|
m_pathRows = rows;
|
m_initialTab = 1;
|
}
|
|
void CProcessDataListDlg::setUnifiedData(const std::vector<std::pair<CString, CString>>& basicRows,
|
const std::vector<PathRow>& pathRows,
|
const std::vector<std::pair<CString, CString>>& processRows)
|
{
|
m_basicRows = basicRows;
|
m_pathRows = pathRows;
|
m_processRows = processRows;
|
}
|
|
void CProcessDataListDlg::setInitialTab(int tabIndex)
|
{
|
if (tabIndex < 0) tabIndex = 0;
|
if (tabIndex > 2) tabIndex = 2;
|
m_initialTab = tabIndex;
|
}
|
|
void CProcessDataListDlg::LoadArmStepOption()
|
{
|
CString iniPath;
|
iniPath.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
|
m_showArmSteps = (GetPrivateProfileInt(_T("GlassPathDlg"), _T("ShowArmSteps"), 0, iniPath) != 0);
|
}
|
|
void CProcessDataListDlg::SaveArmStepOption() const
|
{
|
CString iniPath, val;
|
iniPath.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir);
|
val.Format(_T("%d"), m_showArmSteps ? 1 : 0);
|
WritePrivateProfileString(_T("GlassPathDlg"), _T("ShowArmSteps"), val, iniPath);
|
}
|
|
void CProcessDataListDlg::BuildPathList()
|
{
|
m_listCtrl.DeleteAllItems();
|
int stepNo = 1;
|
for (const auto& r : m_pathRows)
|
{
|
if (!m_showArmSteps && r.isArmStep) continue;
|
|
CString step;
|
step.Format(_T("%d"), stepNo++);
|
int nItem = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), step);
|
m_listCtrl.SetItemText(nItem, 1, r.chamber);
|
m_listCtrl.SetItemText(nItem, 2, r.enterTime);
|
m_listCtrl.SetItemText(nItem, 3, r.leaveTime);
|
}
|
}
|
|
void CProcessDataListDlg::BuildNameValueList(const std::vector<std::pair<CString, CString>>& rows)
|
{
|
m_listCtrl.DeleteAllItems();
|
for (int i = 0; i < (int)rows.size(); ++i) {
|
int nItem = m_listCtrl.InsertItem(i, rows[i].first);
|
m_listCtrl.SetItemText(nItem, 1, rows[i].second);
|
}
|
}
|
|
void CProcessDataListDlg::InitUnifiedLayout()
|
{
|
CRect rcList;
|
m_listCtrl.GetWindowRect(&rcList);
|
ScreenToClient(&rcList);
|
|
CRect rcTab(rcList.left, rcList.top, rcList.right, rcList.top + 24);
|
m_tabCtrl.Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP, rcTab, this, IDC_TAB_UNIFIED);
|
m_tabCtrl.SetFont(GetFont());
|
m_tabCtrl.InsertItem(0, _T("基础信息"));
|
m_tabCtrl.InsertItem(1, _T("工艺Step"));
|
m_tabCtrl.InsertItem(2, _T("ProcessData"));
|
m_tabCtrl.SetCurSel(m_initialTab);
|
|
CRect rcNewList(rcList.left, rcTab.bottom + 2, rcList.right, rcList.bottom);
|
m_listCtrl.MoveWindow(&rcNewList);
|
|
CRect rcChk(rcNewList.left, rcNewList.bottom + 6, rcNewList.left + 200, rcNewList.bottom + 24);
|
m_chkShowArm.Create(_T("显示机械手相关Step"),
|
WS_CHILD | BS_AUTOCHECKBOX,
|
rcChk, this, IDC_CHECK_SHOW_ARM_STEPS);
|
m_chkShowArm.SetFont(GetFont());
|
m_chkShowArm.SetCheck(m_showArmSteps ? BST_CHECKED : BST_UNCHECKED);
|
}
|
|
void CProcessDataListDlg::RenderUnifiedTab()
|
{
|
const int tab = m_tabCtrl.GetCurSel();
|
while (m_listCtrl.GetHeaderCtrl() && m_listCtrl.GetHeaderCtrl()->GetItemCount() > 0) {
|
m_listCtrl.DeleteColumn(0);
|
}
|
|
if (tab == 0) {
|
m_chkShowArm.ShowWindow(SW_HIDE);
|
m_listCtrl.InsertColumn(0, _T("名称"), LVCFMT_RIGHT, 200);
|
m_listCtrl.InsertColumn(1, _T("值"), LVCFMT_LEFT, 320);
|
BuildNameValueList(m_basicRows);
|
}
|
else if (tab == 1) {
|
m_chkShowArm.ShowWindow(SW_SHOW);
|
m_listCtrl.InsertColumn(0, _T("Step"), LVCFMT_RIGHT, 56);
|
m_listCtrl.InsertColumn(1, _T("腔体名称"), LVCFMT_LEFT, 180);
|
m_listCtrl.InsertColumn(2, _T("进入时间"), LVCFMT_LEFT, 156);
|
m_listCtrl.InsertColumn(3, _T("离开时间"), LVCFMT_LEFT, 156);
|
|
m_listCtrl.DeleteAllItems();
|
int stepNo = 1;
|
for (const auto& r : m_pathRows)
|
{
|
if (!m_showArmSteps && r.isArmStep) continue;
|
CString step;
|
step.Format(_T("%d"), stepNo++);
|
int nItem = m_listCtrl.InsertItem(m_listCtrl.GetItemCount(), step);
|
m_listCtrl.SetItemText(nItem, 1, r.chamber);
|
m_listCtrl.SetItemText(nItem, 2, r.enterTime);
|
m_listCtrl.SetItemText(nItem, 3, r.leaveTime);
|
}
|
}
|
else {
|
m_chkShowArm.ShowWindow(SW_HIDE);
|
m_listCtrl.InsertColumn(0, _T("名称"), LVCFMT_RIGHT, 200);
|
m_listCtrl.InsertColumn(1, _T("值"), LVCFMT_LEFT, 320);
|
if (!m_processRows.empty()) {
|
BuildNameValueList(m_processRows);
|
}
|
else {
|
InsertParamsToListCtrl(m_listCtrl, m_strRawText);
|
}
|
}
|
}
|
|
void CProcessDataListDlg::InsertParamsToListCtrl(CListCtrl& listCtrl, const CString& data)
|
{
|
// 清空现有内容
|
listCtrl.DeleteAllItems();
|
|
int row = 0;
|
int start = 0;
|
CString item;
|
|
// 按逗号分割
|
while (AfxExtractSubString(item, data, row, ',')) // row 从 0 开始,逐个取子串
|
{
|
int pos = item.Find(_T(':'));
|
if (pos == -1) {
|
row++;
|
continue;
|
}
|
|
CString name = item.Left(pos);
|
CString value = item.Mid(pos + 1);
|
|
name.Trim(); // 去掉前后空格
|
value.Trim();
|
|
int nItem = listCtrl.InsertItem(row, name); // 第一列:参数名
|
listCtrl.SetItemText(nItem, 1, value); // 第二列:参数值
|
|
row++;
|
}
|
}
|
|
bool CProcessDataListDlg::CopyListCtrlToClipboard(CListCtrl& listCtrl, bool includeHeader/* = false*/)
|
{
|
CString strCSV;
|
int nCount = listCtrl.GetItemCount();
|
int nColCount = listCtrl.GetHeaderCtrl()->GetItemCount();
|
|
if (nCount == 0 || nColCount == 0)
|
return false;
|
|
// 如果需要导出表头
|
if (includeHeader)
|
{
|
CString headerLine;
|
for (int j = 0; j < nColCount; j++)
|
{
|
CString text;
|
LVCOLUMN col;
|
TCHAR buf[256] = { 0 };
|
col.mask = LVCF_TEXT;
|
col.pszText = buf;
|
col.cchTextMax = 255;
|
if (listCtrl.GetColumn(j, &col))
|
text = col.pszText;
|
|
if (text.Find(_T(',')) != -1 || text.Find(_T('"')) != -1)
|
{
|
text.Replace(_T("\""), _T("\"\""));
|
text = _T("\"") + text + _T("\"");
|
}
|
|
headerLine += text;
|
if (j < nColCount - 1)
|
headerLine += _T(",");
|
}
|
strCSV += headerLine + _T("\n");
|
}
|
|
// 遍历行
|
for (int i = 0; i < nCount; i++)
|
{
|
CString line;
|
for (int j = 0; j < nColCount; j++)
|
{
|
CString text = listCtrl.GetItemText(i, j);
|
|
// 如果包含逗号或双引号,加上引号并转义
|
if (text.Find(_T(',')) != -1 || text.Find(_T('"')) != -1)
|
{
|
text.Replace(_T("\""), _T("\"\""));
|
text = _T("\"") + text + _T("\"");
|
}
|
|
line += text;
|
if (j < nColCount - 1)
|
line += _T(",");
|
}
|
strCSV += line + _T("\n");
|
}
|
|
if (!OpenClipboard())
|
return false;
|
|
EmptyClipboard();
|
|
// 转为全局内存
|
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (strCSV.GetLength() + 1) * sizeof(TCHAR));
|
if (!hMem)
|
{
|
CloseClipboard();
|
return false;
|
}
|
|
LPTSTR pMem = (LPTSTR)GlobalLock(hMem);
|
if (!pMem)
|
{
|
GlobalFree(hMem);
|
CloseClipboard();
|
return false;
|
}
|
|
_tcscpy_s(pMem, strCSV.GetLength() + 1, strCSV);
|
GlobalUnlock(hMem);
|
|
#ifdef UNICODE
|
SetClipboardData(CF_UNICODETEXT, hMem);
|
#else
|
SetClipboardData(CF_TEXT, hMem);
|
#endif
|
|
CloseClipboard();
|
return true;
|
}
|
|
void CProcessDataListDlg::OnBnClickedButton1()
|
{
|
if (CopyListCtrlToClipboard(m_listCtrl, true))
|
{
|
AfxMessageBox(_T("复制成功!"));
|
}
|
else
|
{
|
AfxMessageBox(_T("复制失败!"));
|
}
|
}
|
|
void CProcessDataListDlg::OnBnClickedCheckShowArm()
|
{
|
m_showArmSteps = (m_chkShowArm.GetCheck() == BST_CHECKED);
|
SaveArmStepOption();
|
RenderUnifiedTab();
|
}
|
|
void CProcessDataListDlg::OnTcnSelchangeTabUnified(NMHDR* pNMHDR, LRESULT* pResult)
|
{
|
RenderUnifiedTab();
|
*pResult = 0;
|
}
|