// 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::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 == NULL) { // 获取对话框的字体 CFont* pDlgFont = GetFont(); LOGFONT lf; if (pDlgFont && pDlgFont->GetLogFont(&lf)) { m_font.CreateFontIndirect(&lf); } } // 计算x起始坐标 CWnd* pWndDesc = GetDlgItem(IDC_STATIC_DESC); CRect rDesc; int nYStart = 0; int nXStart = 0; int nTotalControlWidth = 340; // 默认兜底 if (pWndDesc) { pWndDesc->GetWindowRect(&rDesc); ScreenToClient(&rDesc); nXStart = rDesc.left; } else { nXStart = 30; } // 计算x起始坐标 pWndDesc = GetDlgItem(IDC_EDIT_DESC); if (pWndDesc) { pWndDesc->GetWindowRect(&rDesc); ScreenToClient(&rDesc); nYStart = rDesc.bottom + 20; } else { nYStart = 30; } // 保证每次进来都清空 for (auto& ctrl : m_vecDevices) { if (ctrl.editDeviceID) { delete ctrl.editDeviceID; ctrl.editDeviceID = nullptr; } if (ctrl.editDeviceName) { delete ctrl.editDeviceName; ctrl.editDeviceName = nullptr; } if (ctrl.comboRecipeID) { delete ctrl.comboRecipeID; ctrl.comboRecipeID = nullptr; } } m_vecDevices.clear(); // 创建控件(不管新建还是编辑,都先创建好) CRect rClient; GetClientRect(&rClient); nTotalControlWidth = (rClient.Width() - nXStart * 2); const int nRowHeight = 30; const int nRowCount = static_cast(g_vecBindDevices.size()); for (int i = 0; i < nRowCount; ++i) { int y = nYStart + i * nRowHeight; const auto& meta = g_vecBindDevices[i]; CEdit* pEditID = new CEdit(); pEditID->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(nXStart, y, nXStart + 100, y + 25), this, IDC_EDIT_DEVICEID_BASE + i); CEdit* pEditName = new CEdit(); pEditName->Create(WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(nXStart + 110, y, nXStart + 210, y + 25), this, IDC_EDIT_DEVICENAME_BASE + i); CComboBox* pCombo = new CComboBox(); pCombo->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(nXStart + 220, y, nXStart + nTotalControlWidth, y + 25), this, IDC_COMBO_RECIPEID_BASE + i); pEditID->SetFont(&m_font); pEditName->SetFont(&m_font); pCombo->SetFont(&m_font); m_vecDevices.push_back({ pEditID, pEditName, pCombo }); } // 填充内容 if (m_recipe.vecDeviceList.empty()) { // 新建模式 for (int i = 0; i < nRowCount; ++i) { const auto& meta = g_vecBindDevices[i]; CString strID; strID.Format(_T("%d"), meta.nDeviceID); m_vecDevices[i].editDeviceID->SetWindowText(strID); m_vecDevices[i].editDeviceID->SetReadOnly(TRUE); m_vecDevices[i].editDeviceName->SetWindowText(CA2T(meta.strDeviceName)); m_vecDevices[i].editDeviceName->SetReadOnly(TRUE); // 这里你可以初始化 ComboBox 选项,例如: // for (const auto& r : GetRecipeListForDevice(meta.nDeviceID)) { // int idx = m_vecDevices[i].comboRecipeID->AddString(CA2T(r.strRecipeName)); // m_vecDevices[i].comboRecipeID->SetItemData(idx, r.nRecipeID); // } } } 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 DeviceRecipe& d = m_recipe.vecDeviceList[i]; CString str; // 设备ID str.Format(_T("%d"), d.nDeviceID); m_vecDevices[i].editDeviceID->SetWindowText(str); m_vecDevices[i].editDeviceID->SetReadOnly(TRUE); // 设备名称 m_vecDevices[i].editDeviceName->SetWindowText(CA2T(d.strDeviceName.c_str())); m_vecDevices[i].editDeviceName->SetReadOnly(TRUE); // ComboBox 选项填充 // for (const auto& r : GetRecipeListForDevice(d.nDeviceID)) { // int idx = m_vecDevices[i].comboRecipeID->AddString(CA2T(r.strRecipeName)); // m_vecDevices[i].comboRecipeID->SetItemData(idx, r.nRecipeID); // // 默认选中对应配方ID // if (r.nRecipeID == d.nRecipeID) // m_vecDevices[i].comboRecipeID->SetCurSel(idx); // } } } return TRUE; // return TRUE unless you set the focus to a control // 异常: OCX 属性页应返回 FALSE } void CRecipeDeviceBindDlg::OnClose() { // TODO: 在此添加消息处理程序代码和/或调用默认值 CDialogEx::OnClose(); // 清理控件 for (auto& device : m_vecDevices) { if (device.editDeviceID) { device.editDeviceID->DestroyWindow(); delete device.editDeviceID; } if (device.editDeviceName) { device.editDeviceName->DestroyWindow(); delete device.editDeviceName; } if (device.comboRecipeID) { device.comboRecipeID->DestroyWindow(); delete device.comboRecipeID; } } m_vecDevices.clear(); } 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(); }