// 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& rows) { m_pathRows = rows; m_initialTab = 1; } void CProcessDataListDlg::setUnifiedData(const std::vector>& basicRows, const std::vector& pathRows, const std::vector>& 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>& 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; }