// CPageRecipe.cpp: 实现文件 // #include "stdafx.h" #include "Servo.h" #include "afxdialogex.h" #include "PageRecipe.h" // CPageRecipe 对话框 IMPLEMENT_DYNAMIC(CPageRecipe, CDialogEx) CPageRecipe::CPageRecipe(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_PAGE_RECIPE, pParent) { } CPageRecipe::~CPageRecipe() { } void CPageRecipe::FillDataToListCtrl(const std::vector& vecRecipe) { CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_PPID); if (pListCtrl == nullptr || pListCtrl->m_hWnd == nullptr) { return; } // 清空当前CListCtrl中的所有项 pListCtrl->DeleteAllItems(); // 遍历数据并插入到CListCtrl中 for (int i = 0; i < static_cast(vecRecipe.size()); ++i) { const RecipeInfo& recipe = vecRecipe[i]; m_listPPID.InsertItem(i, _T("")); // 第0列空白 CString strNo; strNo.Format(_T("%d"), i + 1); m_listPPID.SetItemText(i, 1, strNo); m_listPPID.SetItemText(i, 2, CA2T(recipe.strPPID.c_str())); m_listPPID.SetItemText(i, 3, CA2T(recipe.strDescription.c_str())); m_listPPID.SetItemText(i, 4, CA2T(recipe.strCreateTime.c_str())); } // 获取列数 int nColCount = m_listPPID.GetHeaderCtrl()->GetItemCount(); m_listPPID.SetColumnWidth(nColCount - 1, LVSCW_AUTOSIZE_USEHEADER); } void CPageRecipe::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST_PPID, m_listPPID); DDX_Control(pDX, IDC_EDIT_PPID, m_editPPID); DDX_Control(pDX, IDC_EDIT_DESC, m_editDesc); } BEGIN_MESSAGE_MAP(CPageRecipe, CDialogEx) ON_WM_SIZE() ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CPageRecipe::OnBnClickedButtonSearch) ON_BN_CLICKED(IDC_BUTTON_MODIFY, &CPageRecipe::OnBnClickedButtonModify) ON_BN_CLICKED(IDC_BUTTON_DELETE, &CPageRecipe::OnBnClickedButtonDelete) ON_BN_CLICKED(IDC_BUTTON_DELETE_ALL, &CPageRecipe::OnBnClickedButtonDeleteAll) ON_BN_CLICKED(IDC_BUTTON_REFRESH, &CPageRecipe::OnBnClickedButtonRefresh) ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_PPID, &CPageRecipe::OnLvnItemChangedListPPID) END_MESSAGE_MAP() // CPageRecipe 消息处理程序 BOOL CPageRecipe::OnInitDialog() { CDialogEx::OnInitDialog(); // TODO: 在此添加额外的初始化 CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_PPID); DWORD dwStyle = pListCtrl->GetExtendedStyle(); dwStyle |= LVS_EX_FULLROWSELECT; dwStyle |= LVS_EX_GRIDLINES; pListCtrl->SetExtendedStyle(dwStyle); HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1); ListView_SetImageList(pListCtrl->GetSafeHwnd(), imageList, LVSIL_SMALL); pListCtrl->InsertColumn(0, _T(""), LVCFMT_RIGHT, 0); // 隐藏列 pListCtrl->InsertColumn(1, _T("No."), LVCFMT_LEFT, 80); pListCtrl->InsertColumn(2, _T("PPID"), LVCFMT_LEFT, 120); pListCtrl->InsertColumn(3, _T("描述"), LVCFMT_LEFT, 180); pListCtrl->InsertColumn(4, _T("创建时间"), LVCFMT_LEFT, 160); pListCtrl->SetColumnWidth(4, LVSCW_AUTOSIZE_USEHEADER); // 获取所有数据 auto vecData = RecipeManager::getInstance().getAllRecipes(); FillDataToListCtrl(vecData); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CPageRecipe::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); if (m_listPPID.GetSafeHwnd()) { // 左侧列表宽高自适应 int margin = 10; int buttonWidth = 80; int buttonHeight = 30; int buttonSpacing = 10; CRect rect; GetClientRect(&rect); int listWidth = rect.Width() - buttonWidth - 3 * margin; int listHeight = rect.Height() - 2 * margin; m_listPPID.MoveWindow(margin, margin + 80, listWidth, listHeight - 80); // 编辑框调整位置:右边对齐列表,左边固定起始 int labelWidth = 60; int rightEdge = rect.right - buttonWidth - 2 * margin; if (m_editPPID.GetSafeHwnd()) { m_editPPID.MoveWindow(labelWidth, margin, rightEdge - labelWidth, 25); } if (m_editDesc.GetSafeHwnd()) { m_editDesc.MoveWindow(labelWidth, margin + 35, rightEdge - labelWidth, 25); } // 按钮竖直排列在右侧 CWnd* buttons[] = { GetDlgItem(IDC_BUTTON_SEARCH), GetDlgItem(IDC_BUTTON_MODIFY), GetDlgItem(IDC_BUTTON_DELETE), GetDlgItem(IDC_BUTTON_DELETE_ALL), GetDlgItem(IDC_BUTTON_REFRESH) }; int y = margin; for (auto pBtn : buttons) { if (pBtn && pBtn->GetSafeHwnd()) { pBtn->MoveWindow(rect.right - buttonWidth - margin, y, buttonWidth, buttonHeight); y += buttonHeight + buttonSpacing; } } // 列宽重设 int col0 = 50; // No. int col1 = 120; // PPID int col3 = 160; // 创建时间自动填充 int col2 = listWidth - col0 - col1 - col3 - 2; // 描述自动填充 if (col2 < 80) { col2 = 80; } m_listPPID.SetColumnWidth(1, col0); m_listPPID.SetColumnWidth(2, col1); m_listPPID.SetColumnWidth(3, col2); m_listPPID.SetColumnWidth(4, col3); } } void CPageRecipe::OnBnClickedButtonSearch() { // TODO: 在此添加控件通知处理程序代码 CString strInput; m_editPPID.GetWindowText(strInput); int nCount = m_listPPID.GetItemCount(); for (int i = 0; i < nCount; ++i) { CString strItemText = m_listPPID.GetItemText(i, 2); // 第2列为PPID if (strItemText == strInput) { m_listPPID.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); m_listPPID.EnsureVisible(i, FALSE); break; } } } void CPageRecipe::OnBnClickedButtonModify() { // TODO: 在此添加控件通知处理程序代码 POSITION pos = m_listPPID.GetFirstSelectedItemPosition(); if (!pos) { AfxMessageBox(_T("请选择要修改的配方")); return; } int nSel = m_listPPID.GetNextSelectedItem(pos); CString strOldPPID = m_listPPID.GetItemText(nSel, 2); CString strOldDesc = m_listPPID.GetItemText(nSel, 3); CString strNewPPID, strNewDesc; m_editPPID.GetWindowText(strNewPPID); m_editDesc.GetWindowText(strNewDesc); // 判空 if (strOldPPID.IsEmpty() || strNewPPID.IsEmpty()) { AfxMessageBox(_T("PPID 不能为空")); return; } std::string oldPPID = CT2A(strOldPPID); std::string newPPID = CT2A(strNewPPID); std::string newDesc = CT2A(strNewDesc); bool bPPIDChanged = (strOldPPID.Compare(strNewPPID) != 0); bool bDescChanged = (strOldDesc.Compare(strNewDesc) != 0); if (!bPPIDChanged && !bDescChanged) { return; } if (bPPIDChanged) { // 新 PPID 不可重复 if (RecipeManager::getInstance().ppidExists(newPPID)) { AfxMessageBox(_T("新 PPID 已存在,请使用其他值")); return; } // 调用 updatePPID,同时更新描述 if (RecipeManager::getInstance().updatePPID(oldPPID, newPPID)) { m_listPPID.SetItemText(nSel, 2, strNewPPID); } else { AfxMessageBox(_T("更新失败,请检查日志")); } } if (bDescChanged) { // 更新描述 if (RecipeManager::getInstance().updateDescription(oldPPID, newDesc)) { m_listPPID.SetItemText(nSel, 3, strNewDesc); } else { AfxMessageBox(_T("描述更新失败")); } } } void CPageRecipe::OnBnClickedButtonDelete() { // TODO: 在此添加控件通知处理程序代码 POSITION pos = m_listPPID.GetFirstSelectedItemPosition(); if (!pos) { return; } int nSel = m_listPPID.GetNextSelectedItem(pos); CString strPPID = m_listPPID.GetItemText(nSel, 2); std::string ppid = CT2A(strPPID); if (!ppid.empty()) { CString msg; msg.Format(_T("确定要删除配方 [%s] 吗?"), strPPID); if (IDYES == AfxMessageBox(msg, MB_YESNO | MB_ICONQUESTION)) { if (RecipeManager::getInstance().deleteRecipeByPPID(ppid)) { m_listPPID.DeleteItem(nSel); } else { AfxMessageBox(_T("删除失败")); } } } } void CPageRecipe::OnBnClickedButtonDeleteAll() { // TODO: 在此添加控件通知处理程序代码 if (IDYES != AfxMessageBox(_T("确定要删除全部配方记录吗?"), MB_YESNO | MB_ICONWARNING)) { return; } // 获取所有 PPID int nCount = m_listPPID.GetItemCount(); for (int i = 0; i < nCount; ++i) { CString strPPID = m_listPPID.GetItemText(i, 2); std::string ppid = CT2A(strPPID); if (!ppid.empty()) { RecipeManager::getInstance().deleteRecipeByPPID(ppid); } } // 清空列表显示 m_listPPID.DeleteAllItems(); } void CPageRecipe::OnBnClickedButtonRefresh() { // TODO: 在此添加控件通知处理程序代码 auto vecData = RecipeManager::getInstance().getAllRecipes(); FillDataToListCtrl(vecData); } void CPageRecipe::OnLvnItemChangedListPPID(NMHDR* pNMHDR, LRESULT* pResult) { LPNMLISTVIEW pNMLV = reinterpret_cast(pNMHDR); *pResult = 0; if ((pNMLV->uChanged & LVIF_STATE) && (pNMLV->uNewState & LVIS_SELECTED)) { int nItem = pNMLV->iItem; CString strPPID = m_listPPID.GetItemText(nItem, 2); m_editPPID.SetWindowText(strPPID); CString strDesc = m_listPPID.GetItemText(nItem, 3); m_editDesc.SetWindowText(strDesc); } }