// RecipeDeviceBindDlg.cpp: 实现文件 // #include "stdafx.h" #include "Servo.h" #include "afxdialogex.h" #include "RecipeDeviceBindDlg.h" #include "RecipeManager.h" #include "Common.h" #define IDC_EDIT_DEVICEID_BASE 3000 #define IDC_EDIT_DEVICENAME_BASE 3050 #define IDC_COMBO_RECIPEID_BASE 3100 // 绑定界面需要显示的设备 static const std::vector g_vecBindDevices = { { EQ_ID_VACUUMBAKE, EQ_NAME_VACUUMBAKE }, { EQ_ID_Bonder1, EQ_NAME_BONDER1 }, { EQ_ID_Bonder2, EQ_NAME_BONDER2 }, { EQ_ID_BAKE_COOLING, EQ_NAME_BAKE_COOLING }, { EQ_ID_MEASUREMENT, EQ_NAME_MEASUREMENT }, { EQ_ID_EFEM, EQ_NAME_EFEM } }; // CRecipeDeviceBindDlg 对话框 IMPLEMENT_DYNAMIC(CRecipeDeviceBindDlg, CDialogEx) CRecipeDeviceBindDlg::CRecipeDeviceBindDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_DIALOG_RECIPE_DEVICE_BIND, pParent) , m_strPPID(_T("")) , m_strDesc(_T("")) { } CRecipeDeviceBindDlg::~CRecipeDeviceBindDlg() { } const RecipeInfo& CRecipeDeviceBindDlg::GetRecipeInfo() const { return m_recipe; } void CRecipeDeviceBindDlg::SetRecipeInfo(const RecipeInfo& info) { m_recipe = info; } void CRecipeDeviceBindDlg::ReleaseDeviceControls() { for (auto& ctrl : m_vecDevices) { delete ctrl.editDeviceID; ctrl.editDeviceID = nullptr; delete ctrl.editDeviceName; ctrl.editDeviceName = nullptr; delete ctrl.comboRecipeID; ctrl.comboRecipeID = nullptr; } m_vecDevices.clear(); } void CRecipeDeviceBindDlg::CreateDeviceControls(int nXStart, int nYStart, int nTotalControlWidth, int nRowHeight) { for (size_t i = 0; i < g_vecBindDevices.size(); ++i) { int y = nYStart + static_cast(i) * nRowHeight; auto* pEditID = new CEdit; pEditID->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart, y, nXStart + 100, y + 25), this, (UINT)(IDC_EDIT_DEVICEID_BASE + i)); pEditID->SetFont(&m_font); auto* pEditName = new CEdit; pEditName->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER, CRect(nXStart + 110, y, nXStart + 210, y + 25), this, (UINT)(IDC_EDIT_DEVICENAME_BASE + i)); pEditName->SetFont(&m_font); auto* pCombo = new CComboBox; pCombo->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(nXStart + 220, y, nXStart + nTotalControlWidth, y + 25), this, (UINT)(IDC_COMBO_RECIPEID_BASE + i)); pCombo->SetFont(&m_font); m_vecDevices.push_back({ pEditID, pEditName, pCombo }); } } bool CRecipeDeviceBindDlg::FillComboRecipeList(CComboBox* pCombo, int nDeviceID, int nSelectedRecipeID) { auto& master = theApp.m_model.getMaster(); auto* pEq = master.getEquipment(nDeviceID); if (!pEq) { return false; } auto* pRecipeList = pEq->getRecipeList(0); if (!pRecipeList) { return false; } auto& mapRecipeIds = pRecipeList->getIds(); bool bFound = false; pCombo->ResetContent(); for (const auto& pair : mapRecipeIds) { int nRecipeID = pair.second; std::string strRecipeName = RecipeManager::getInstance().getDeviceRecipeName(pEq->getName(), nRecipeID); if (strRecipeName.empty()) { strRecipeName = std::to_string(nRecipeID); } CString str; str.Format(_T("%s"), strRecipeName.c_str()); int idx = pCombo->AddString(str); pCombo->SetItemData(idx, nRecipeID); if (nSelectedRecipeID == nRecipeID) { pCombo->SetCurSel(idx); bFound = true; } } if (nSelectedRecipeID != -1 && !bFound) { pCombo->SetCurSel(CB_ERR); } else if (pCombo->GetCount() > 0 && nSelectedRecipeID == -1) { pCombo->SetCurSel(0); } return true; } bool CRecipeDeviceBindDlg::FillDeviceInfo(int idx, int nDeviceID, const CString& strDeviceName, int nSelectedRecipeID) { if (idx < 0 || idx >= (int)m_vecDevices.size()) { return false; } auto& ctrl = m_vecDevices[idx]; CString strID; strID.Format(_T("%d"), nDeviceID); ctrl.editDeviceID->SetWindowText(strID); ctrl.editDeviceID->SetReadOnly(TRUE); ctrl.editDeviceName->SetWindowText(strDeviceName); ctrl.editDeviceName->SetReadOnly(TRUE); if (!FillComboRecipeList(ctrl.comboRecipeID, nDeviceID, nSelectedRecipeID)) { CString str; str.Format(_T("设备 [%s] 或其配方列表未找到,请检查设备配置"), strDeviceName.GetString()); AfxMessageBox(str); return false; } return true; } void CRecipeDeviceBindDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_PPID, m_strPPID); DDX_Text(pDX, IDC_EDIT_DESC, m_strDesc); } BEGIN_MESSAGE_MAP(CRecipeDeviceBindDlg, CDialogEx) ON_WM_CLOSE() ON_WM_SIZE() ON_BN_CLICKED(IDOK, &CRecipeDeviceBindDlg::OnBnClickedOk) END_MESSAGE_MAP() // CRecipeDeviceBindDlg 消息处理程序 BOOL CRecipeDeviceBindDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 设置对话框标题 SetWindowText(m_recipe.vecDeviceList.empty() ? _T("新建配方") : _T("编辑配方")); // 创建动态控件字体 if (!m_font.m_hObject) { CFont* pDlgFont = GetFont(); LOGFONT lf; if (pDlgFont && pDlgFont->GetLogFont(&lf)) { lf.lfHeight = -16; m_font.CreateFontIndirect(&lf); } } // 计算坐标 CRect rDesc; int nXStart = 30, nYStart = 30, nTotalControlWidth = 340; if (auto* pWndDesc = GetDlgItem(IDC_STATIC_DESC)) { pWndDesc->GetWindowRect(&rDesc); ScreenToClient(&rDesc); nXStart = rDesc.left; } if (auto* pWndEdit = GetDlgItem(IDC_EDIT_DESC)) { pWndEdit->GetWindowRect(&rDesc); ScreenToClient(&rDesc); nYStart = rDesc.bottom + 20; } CRect rClient; GetClientRect(&rClient); nTotalControlWidth = rClient.Width() - nXStart * 2; const int nRowHeight = 30; // 清空旧控件 ReleaseDeviceControls(); // 创建新控件 CreateDeviceControls(nXStart, nYStart, nTotalControlWidth, nRowHeight); auto& master = theApp.m_model.getMaster(); // 填充内容 if (m_recipe.vecDeviceList.empty()) { // 新建 for (size_t i = 0; i < g_vecBindDevices.size(); ++i) { const auto& meta = g_vecBindDevices[i]; FillDeviceInfo((int)i, meta.nDeviceID, meta.strDeviceName); } } else { // 编辑 m_strPPID = CA2T(m_recipe.strPPID.c_str()); m_strDesc = CA2T(m_recipe.strDescription.c_str()); UpdateData(FALSE); for (size_t i = 0; i < m_recipe.vecDeviceList.size() && i < m_vecDevices.size(); ++i) { const auto& d = m_recipe.vecDeviceList[i]; FillDeviceInfo((int)i, d.nDeviceID, d.strDeviceName.c_str(), d.nRecipeID); } } CenterWindow(); return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CRecipeDeviceBindDlg::OnClose() { // TODO: 在此添加消息处理程序代码和/或调用默认值 CDialogEx::OnClose(); // 清理控件 ReleaseDeviceControls(); } void CRecipeDeviceBindDlg::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); // TODO: 在此处添加消息处理程序代码 } void CRecipeDeviceBindDlg::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); // 收集所有设备映射 m_recipe.vecDeviceList.clear(); for (const auto& dev : m_vecDevices) { DeviceRecipe info; CString strID, strName; dev.editDeviceID->GetWindowText(strID); dev.editDeviceName->GetWindowText(strName); int sel = dev.comboRecipeID->GetCurSel(); info.nRecipeID = -1; if (sel != CB_ERR) { info.nRecipeID = (int)dev.comboRecipeID->GetItemData(sel); } info.nDeviceID = _ttoi(strID); info.strDeviceName = CT2A(strName); m_recipe.vecDeviceList.push_back(info); } // 检查 PPID 是否为空 if (m_strPPID.IsEmpty()) { AfxMessageBox(_T("配方 PPID 不能为空")); return; } // PPID和描述 m_recipe.strPPID = CT2A(m_strPPID); m_recipe.strDescription = CT2A(m_strDesc); CDialogEx::OnOK(); }